Monitor Java application with prometheus 
Tags: prometheus, java, tutorial
Published: 2022-02-01 07:50:14

Prometheus provides JMX exporter which can export JVM information.

1. Create JMX exporter configuration. Let's call it `jmx_exporter_config.yml`.

```yaml
---
rules:
  - pattern: "java.lang.*"
```

2\. Download JMX exporter

You can find the URL of JMX exporter jar file in Github repository.

https://github.com/prometheus/jmx_exporter

Here is the URL for 0.16.1

https://repo1.maven.org/maven2/io/prometheus/jmx/jmx_prometheus_javaagent/0.16.1/jmx_prometheus_javaagent-0.16.1.jar

3\. Start your Java application

For example, your application is packaged as a jar file `myapp_1.jar`. `jmx_prometheus_javaagent-0.16.1.jar` and `jmx_exporter_config.yml` are saved in `/app`. We expose port `8080` to export metrics.

```shell
java -javaagent:/app/jmx_prometheus_javaagent-0.16.1.jar=8080:/app/jmx_exporter_config.yml -jar myapp_1.jar
```

4\. Download Prometheus

You can find the URL of Prometheus in its official site.

https://prometheus.io/download/

Here is the URL of 2.33.0 (MacOS).

https://github.com/prometheus/prometheus/releases/download/v2.33.0/prometheus-2.33.0.darwin-amd64.tar.gz

5\. Unzip Prometheus

After it is downloaded, unzip it and go to its directory.

```shell
tar xvfz prometheus-*.tar.gz
cd prometheus-*
```

6\. Update prometheus configuration

Add the following to the `prometheus.yml` (under `scrape_configs`). We adds label to help querying.

```yaml
  - job_name: "apps"

    static_configs:
      - targets: ["localhost:8080"]
        labels:
          instance: 'myapp_1'
```

The whole file should look like this.

```yaml
# my global config
global:
  scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["localhost:9090"]

  - job_name: "apps"

    static_configs:
      - targets: ["localhost:8080"]
        labels:
          instance: 'myapp_1'
```

7\. Start Prometheus

```shell
./prometheus --config.file=prometheus.yml
```

8\. Query JVM information

http://localhost:9090/

Query `jvm_memory_bytes_used{area="heap",instance="myapp_1"}`

Here is the query result.

![Query result](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6wm0w98ylralqraues72.png)

Or you prefer a graph (You may need to refresh the browser if you want to see the latest data)

![Query result in graph](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4kzif9bq2zog9qe74bom.png)

Here are other metrics you can try.

* `jvm_gc_collection_seconds_count`

* `jvm_gc_collection_seconds_sum`

* `jvm_memory_bytes_used` - 

* `jvm_memory_bytes_committed`

* `jvm_memory_bytes_max`

* `jvm_memory_bytes_init`

* `process_cpu_seconds_total`