Introduction: Why Monitoring Java Applications is Essential
\nA modern Java application is a complex distributed system. Without monitoring, you are working blind: a drop in response speed, memory leak, or sudden OutOfMemoryError can go unnoticed until a user complains. Properly configured monitoring of metrics and alerts allows you not only to respond quickly to incidents but also to predict bottlenecks before they become critical.
\nIn this article, we will cover the full cycle: from collecting basic JVM metrics to setting up alerts in Prometheus and visualization in Grafana. All code examples are written in Java using the popular Micrometer library.
\n\n1. Key Metrics of a Java Application
\nMonitoring starts with choosing the right metrics. They can be divided into three groups: JVM metrics, business metrics, and infrastructure metrics.
\n\n1.1. JVM Metrics
\nThese metrics show the state of the Java Virtual Machine. The most important ones are:
\n- \n
- Heap memory usage — heap usage (used / maximum memory). A sharp increase may indicate a leak. \n
- GC pauses — frequency and duration of garbage collections. Long pauses (over 1 second) are a sign of problems. \n
- Thread states — number of threads in RUNNABLE, BLOCKED, WAITING states. Many BLOCKED threads may indicate a deadlock. \n
- CPU usage — CPU load of the JVM process. \n
1.2. Business Metrics
\nThese reflect your application's logic. Examples:
\n- \n
- Number of processed orders per minute. \n
- External API response time. \n
- Number of validation errors. \n
1.3. Infrastructure Metrics
\n- \n
- Disk, network, and host memory usage. \n
- Database connection pool status. \n
- Message queue delays (Kafka, RabbitMQ). \n
2. Tools for Collecting Metrics: Micrometer + Prometheus
\nFor Java applications, the de facto standard is the Micrometer library. It provides a facade for various monitoring systems (Prometheus, Datadog, Graphite). Combined with Prometheus (metric storage) and Grafana (visualization), you get a powerful and free ecosystem.
\n\n2.1. Adding Micrometer in Spring Boot
\nIf you are using Spring Boot 2.x or 3.x, add the following dependency to your pom.xml:
<dependency>\n <groupId>io.micrometer</groupId>\n <artifactId>micrometer-registry-prometheus</artifactId>\n</dependency>\nAfter this, Spring Boot Actuator will automatically enable the /actuator/prometheus endpoint, which will expose metrics in Prometheus format.
2.2. Creating a Custom Metric
\nSuppose you want to count the number of successful and failed method calls. Create a counter:
\nimport io.micrometer.core.instrument.MeterRegistry;\nimport io.micrometer.core.instrument.Counter;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class OrderService {\n\n private final Counter successCounter;\n private final Counter errorCounter;\n\n public OrderService(MeterRegistry registry) {\n this.successCounter = Counter.builder("orders.success")\n .description("Number of successful orders")\n .register(registry);\n this.errorCounter = Counter.builder("orders.error")\n .description("Number of failed orders")\n .register(registry);\n }\n\n public void processOrder(String orderId) {\n try {\n // order processing logic\n successCounter.increment();\n } catch (Exception e) {\n errorCounter.increment();\n throw e;\n }\n }\n}\nIn Prometheus, the metric will appear as orders_succ