Advanced Monitoring of Java Applications: Metrics and Alerts
\n\nIn modern software development, monitoring Java applications is no longer an option — it is a necessity. Basic metric collection (CPU, memory) no longer prevents incidents in complex distributed systems. At an advanced level, deep observability is required: understanding the internal state of the application, identifying bottlenecks, and predictive analytics. In this article, we will explore how to organize professional monitoring of Java applications using metrics and alerts, leveraging modern tools and best practices.
\n\n1. Advanced Metric Collection in Java: Micrometer and Prometheus
\n\nThe Micrometer library is the de facto standard for collecting metrics in Spring Boot and other Java frameworks. It provides a unified API that can export metrics to various monitoring systems (Prometheus, Datadog, New Relic). For advanced monitoring, we will use the Micrometer + Prometheus stack.
\n\nWhy is this an advanced level? Instead of simply collecting HTTP requests, we will configure custom metrics: histograms of business logic execution time, error counters with tags, timers for asynchronous operations.
\n\nExample of configuring Micrometer in Spring Boot:
\n\n// Dependency in pom.xml\n<dependency>\n <groupId>io.micrometer</groupId>\n <artifactId>micrometer-registry-prometheus</artifactId>\n</dependency>\n\n// application.yml\nmanagement:\n endpoints:\n web:\n exposure:\n include: "health,prometheus"\n metrics:\n export:\n prometheus:\n enabled: true\n\n\nNow let's add a custom metric — a histogram of method execution time:
\n\nimport io.micrometer.core.instrument.MeterRegistry;\nimport io.micrometer.core.instrument.Timer;\nimport org.springframework.stereotype.Service;\n\nimport java.util.concurrent.TimeUnit;\n\n@Service\npublic class OrderService {\n\n private final Timer orderProcessingTimer;\n\n public OrderService(MeterRegistry registry) {\n this.orderProcessingTimer = Timer.builder("order.processing.time")\n .description("Time taken to process an order")\n .publishPercentiles(0.5, 0.95, 0.99) // p50, p95, p99\n .register(registry);\n }\n\n public void processOrder(String orderId) {\n Timer.Sample sample = Timer.start();\n try {\n // Order processing logic\n Thread.sleep(200); // Simulating work\n } catch (InterruptedException e) {\n Thread.currentThread().interrupt();\n } finally {\n sample.stop(orderProcessingTimer);\n }\n }\n}\n\n\nThis metric will show not just the average time, but percentiles, which is critical for identifying "slow" requests (tail latency).
\n\n2. Configuring Advanced Alerts: Alertmanager and Rules
\n\nCollecting metrics is useless without an alerting system. Prometheus Alertmanager allows you to configure complex alerting rules with grouping, suppression, and notification routing (Slack, PagerDuty, Email).
\n\nAdvanced approach: instead of a simple "CPU > 90%", we use predictive alerts and aggregation by services.
\n\nExample of an alert rule for a Java application (file rules.yml):
groups:\n - name: java_app_alerts\n rules:\n # Alert on high 5xx error rate\n - alert: HighErrorRate\n expr: |\n rate(http_requests_total{status=~"5.."}[5m])\n /\n rate(http_requests_total[5m]) > 0.05\n for: 2m\n labels:\n severity: critical\n annotations:\n summary: "High HTTP 5xx error rate ({{ $value | humanizePercentage }})"\n description: "Error rate for {{ $labels.instance }} is above 5% for 2