0
# Metrics System
1
2
Spring Boot Actuator integrates with Micrometer to provide comprehensive application metrics collection, measurement, and export capabilities. It automatically configures metrics for common application components and supports export to various monitoring systems.
3
4
## Capabilities
5
6
### Metrics Endpoint
7
8
Primary endpoint for accessing collected application metrics.
9
10
```java { .api }
11
/**
12
* Endpoint for application metrics
13
*/
14
@Endpoint(id = "metrics")
15
public class MetricsEndpoint {
16
17
/**
18
* List all available metric names
19
* @return response containing all metric names
20
*/
21
@ReadOperation
22
public ListNamesResponse listNames() { /* ... */ }
23
24
/**
25
* Get details for a specific metric
26
* @param requiredMetricName the name of the metric
27
* @param tag optional tag filters in the format key:value
28
* @return the metric response with measurements and metadata
29
*/
30
@ReadOperation
31
public MetricResponse metric(@Selector String requiredMetricName,
32
@Nullable List<String> tag) { /* ... */ }
33
34
/**
35
* Response containing available metric names
36
*/
37
public static final class ListNamesResponse {
38
private final Set<String> names;
39
40
public Set<String> getNames() { return this.names; }
41
}
42
43
/**
44
* Response containing metric details
45
*/
46
public static final class MetricResponse {
47
private final String name;
48
private final String description;
49
private final String baseUnit;
50
private final List<Sample> measurements;
51
private final List<AvailableTag> availableTags;
52
53
public String getName() { return this.name; }
54
public String getDescription() { return this.description; }
55
public String getBaseUnit() { return this.baseUnit; }
56
public List<Sample> getMeasurements() { return this.measurements; }
57
public List<AvailableTag> getAvailableTags() { return this.availableTags; }
58
}
59
60
/**
61
* A single metric measurement sample
62
*/
63
public static final class Sample {
64
private final Statistic statistic;
65
private final Double value;
66
67
public Statistic getStatistic() { return this.statistic; }
68
public Double getValue() { return this.value; }
69
}
70
71
/**
72
* Available tag for filtering metrics
73
*/
74
public static final class AvailableTag {
75
private final String tag;
76
private final Set<String> values;
77
78
public String getTag() { return this.tag; }
79
public Set<String> getValues() { return this.values; }
80
}
81
}
82
```
83
84
### Automatic Timing Configuration
85
86
Configuration for automatic timing of web requests and method calls.
87
88
```java { .api }
89
/**
90
* Configuration for automatic timing
91
*/
92
public final class AutoTimer {
93
94
/**
95
* AutoTimer that is enabled
96
*/
97
public static final AutoTimer ENABLED = new AutoTimer(true);
98
99
/**
100
* AutoTimer that is disabled
101
*/
102
public static final AutoTimer DISABLED = new AutoTimer(false);
103
104
/**
105
* Create a new AutoTimer
106
* @param enabled whether timing is enabled
107
*/
108
public AutoTimer(boolean enabled) { /* ... */ }
109
110
/**
111
* Return whether auto-timing is enabled
112
* @return true if enabled
113
*/
114
public boolean isEnabled() { /* ... */ }
115
}
116
```
117
118
### Prometheus Integration
119
120
Endpoints and utilities for Prometheus metrics export.
121
122
```java { .api }
123
/**
124
* Endpoint for Prometheus metrics scraping
125
*/
126
@Endpoint(id = "prometheus", enableByDefault = false)
127
public class PrometheusScrapeEndpoint {
128
129
/**
130
* Scrape metrics in Prometheus format
131
* @return metrics in Prometheus text format
132
*/
133
@ReadOperation(produces = "text/plain;version=0.0.4;charset=utf-8")
134
public String scrape() { /* ... */ }
135
136
/**
137
* Scrape metrics for specific names
138
* @param includedNames names of metrics to include
139
* @return filtered metrics in Prometheus format
140
*/
141
@ReadOperation(produces = "text/plain;version=0.0.4;charset=utf-8")
142
public String scrape(@Nullable Set<String> includedNames) { /* ... */ }
143
}
144
145
/**
146
* Output format options for Prometheus metrics
147
*/
148
public enum PrometheusOutputFormat {
149
150
/**
151
* Prometheus text format version 0.0.4
152
*/
153
CONTENT_TYPE_004("text/plain;version=0.0.4;charset=utf-8"),
154
155
/**
156
* OpenMetrics text format version 1.0.0
157
*/
158
CONTENT_TYPE_OPENMETRICS_100("application/openmetrics-text;version=1.0.0;charset=utf-8");
159
160
private final String type;
161
162
PrometheusOutputFormat(String type) { this.type = type; }
163
164
public String getType() { return this.type; }
165
}
166
167
/**
168
* Manager for Prometheus push gateway integration
169
*/
170
public class PrometheusPushGatewayManager {
171
172
/**
173
* Create a new push gateway manager
174
* @param pushGateway the Prometheus push gateway
175
* @param registry the meter registry
176
* @param scheduler the task scheduler
177
*/
178
public PrometheusPushGatewayManager(PushGateway pushGateway,
179
CollectorRegistry registry,
180
TaskScheduler scheduler) { /* ... */ }
181
182
/**
183
* Push metrics to the gateway
184
*/
185
public void push() { /* ... */ }
186
187
/**
188
* Shutdown the push gateway manager
189
*/
190
public void shutdown() { /* ... */ }
191
}
192
```
193
194
### Cache Metrics
195
196
Metrics providers for various caching solutions.
197
198
```java { .api }
199
/**
200
* Provider for cache meter binders
201
*/
202
@FunctionalInterface
203
public interface CacheMeterBinderProvider<C> {
204
205
/**
206
* Return a MeterBinder for the given cache
207
* @param cache the cache to instrument
208
* @param tags additional tags
209
* @return the meter binder or null if not supported
210
*/
211
@Nullable
212
MeterBinder getMeterBinder(C cache, Iterable<Tag> tags);
213
}
214
```
215
216
### Database Connection Pool Metrics
217
218
Metrics for monitoring database connection pools.
219
220
```java { .api }
221
/**
222
* Metrics for data source connection pools
223
*/
224
public class DataSourcePoolMetrics {
225
226
/**
227
* Create metrics for a data source
228
* @param dataSource the data source
229
* @param dataSourceName the data source name
230
* @param tags additional tags
231
* @return the meter binder
232
*/
233
public static MeterBinder createMeterBinder(DataSource dataSource,
234
String dataSourceName,
235
Iterable<Tag> tags) { /* ... */ }
236
}
237
238
/**
239
* Metrics for R2DBC connection pools
240
*/
241
public class ConnectionPoolMetrics {
242
243
/**
244
* Create metrics for an R2DBC connection pool
245
* @param connectionPool the connection pool
246
* @param name the pool name
247
* @param tags additional tags
248
* @return the meter binder
249
*/
250
public static MeterBinder createMeterBinder(ConnectionPool connectionPool,
251
String name,
252
Iterable<Tag> tags) { /* ... */ }
253
}
254
```
255
256
## Usage Examples
257
258
### Accessing Metrics via HTTP
259
260
```bash
261
# List all available metrics
262
curl http://localhost:8080/actuator/metrics
263
264
# Get JVM memory usage
265
curl http://localhost:8080/actuator/metrics/jvm.memory.used
266
267
# Get HTTP request metrics with tags
268
curl "http://localhost:8080/actuator/metrics/http.server.requests?tag=status:200&tag=method:GET"
269
270
# Get database connection pool metrics
271
curl http://localhost:8080/actuator/metrics/hikaricp.connections.active
272
```
273
274
### Custom Metrics with Micrometer
275
276
```java
277
@Service
278
public class BusinessMetricsService {
279
280
private final Counter orderCounter;
281
private final Timer orderProcessingTimer;
282
private final Gauge activeUsersGauge;
283
private final DistributionSummary orderValueSummary;
284
285
public BusinessMetricsService(MeterRegistry meterRegistry) {
286
this.orderCounter = Counter.builder("orders.placed")
287
.description("Number of orders placed")
288
.tag("type", "business")
289
.register(meterRegistry);
290
291
this.orderProcessingTimer = Timer.builder("order.processing.time")
292
.description("Time taken to process orders")
293
.register(meterRegistry);
294
295
this.activeUsersGauge = Gauge.builder("users.active")
296
.description("Number of active users")
297
.register(meterRegistry, this, BusinessMetricsService::getActiveUserCount);
298
299
this.orderValueSummary = DistributionSummary.builder("order.value")
300
.description("Distribution of order values")
301
.baseUnit("USD")
302
.register(meterRegistry);
303
}
304
305
public void recordOrderPlaced(Order order) {
306
orderCounter.increment(Tags.of("product", order.getProduct()));
307
orderValueSummary.record(order.getValue());
308
}
309
310
public void recordOrderProcessing(Runnable orderProcessing) {
311
orderProcessingTimer.recordCallable(() -> {
312
orderProcessing.run();
313
return null;
314
});
315
}
316
317
private double getActiveUserCount() {
318
// Implementation to get active user count
319
return 0.0;
320
}
321
}
322
```
323
324
### Automatic Web Request Timing
325
326
```java
327
@Configuration
328
public class MetricsConfiguration {
329
330
@Bean
331
public WebMvcMetricsFilter webMvcMetricsFilter(MeterRegistry registry) {
332
return new WebMvcMetricsFilter(registry,
333
new DefaultWebMvcTagsProvider(),
334
"http.server.requests",
335
AutoTimer.ENABLED);
336
}
337
338
@Bean
339
public TimedAspect timedAspect(MeterRegistry registry) {
340
return new TimedAspect(registry);
341
}
342
}
343
344
@RestController
345
public class OrderController {
346
347
@Timed(name = "orders.create", description = "Time taken to create order")
348
@PostMapping("/orders")
349
public ResponseEntity<Order> createOrder(@RequestBody CreateOrderRequest request) {
350
// Order creation logic
351
return ResponseEntity.ok(order);
352
}
353
}
354
```
355
356
### Custom Health Indicator with Metrics
357
358
```java
359
@Component
360
public class DatabaseHealthWithMetrics extends AbstractHealthIndicator {
361
362
private final DataSource dataSource;
363
private final Counter healthCheckCounter;
364
private final Timer healthCheckTimer;
365
366
public DatabaseHealthWithMetrics(DataSource dataSource, MeterRegistry registry) {
367
this.dataSource = dataSource;
368
this.healthCheckCounter = Counter.builder("health.check")
369
.description("Database health check attempts")
370
.tag("component", "database")
371
.register(registry);
372
this.healthCheckTimer = Timer.builder("health.check.time")
373
.description("Database health check duration")
374
.tag("component", "database")
375
.register(registry);
376
}
377
378
@Override
379
protected void doHealthCheck(Health.Builder builder) throws Exception {
380
healthCheckCounter.increment();
381
382
Timer.Sample sample = Timer.start();
383
try {
384
// Perform health check
385
try (Connection connection = dataSource.getConnection()) {
386
// Simple query to verify connection
387
connection.isValid(1);
388
builder.up()
389
.withDetail("database", "available")
390
.withDetail("validationQuery", "connection.isValid(1)");
391
}
392
} finally {
393
sample.stop(healthCheckTimer);
394
}
395
}
396
}
397
```
398
399
### Prometheus Configuration
400
401
```java
402
@Configuration
403
@ConditionalOnProperty(name = "management.metrics.export.prometheus.enabled",
404
havingValue = "true", matchIfMissing = true)
405
public class PrometheusConfiguration {
406
407
@Bean
408
public PrometheusMeterRegistry prometheusMeterRegistry(PrometheusConfig config,
409
CollectorRegistry registry,
410
Clock clock) {
411
return new PrometheusMeterRegistry(config, registry, clock);
412
}
413
414
@Bean
415
@ConditionalOnProperty(name = "management.metrics.export.prometheus.pushgateway.enabled",
416
havingValue = "true")
417
public PrometheusPushGatewayManager prometheusPushGatewayManager(
418
PrometheusProperties.Pushgateway properties,
419
CollectorRegistry registry,
420
TaskScheduler scheduler) {
421
422
PushGateway pushGateway = new PushGateway(properties.getBaseUrl());
423
return new PrometheusPushGatewayManager(pushGateway, registry, scheduler);
424
}
425
}
426
```
427
428
### Cache Metrics Integration
429
430
```java
431
@Configuration
432
@EnableCaching
433
public class CacheMetricsConfiguration {
434
435
@Bean
436
public CacheManager cacheManager(MeterRegistry meterRegistry) {
437
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
438
cacheManager.setCacheSpecification("maximumSize=1000,expireAfterWrite=10m");
439
440
// Bind cache metrics
441
cacheManager.getCacheNames().forEach(cacheName -> {
442
Cache cache = cacheManager.getCache(cacheName);
443
if (cache instanceof CaffeineCache) {
444
CaffeineCacheMetrics.monitor(meterRegistry,
445
((CaffeineCache) cache).getNativeCache(),
446
cacheName);
447
}
448
});
449
450
return cacheManager;
451
}
452
}
453
```
454
455
## Built-in Metrics
456
457
Spring Boot automatically provides metrics for:
458
459
### JVM Metrics
460
- `jvm.memory.used` - JVM memory usage
461
- `jvm.memory.committed` - JVM committed memory
462
- `jvm.memory.max` - JVM maximum memory
463
- `jvm.gc.pause` - Garbage collection pause times
464
- `jvm.threads.live` - Live thread count
465
- `jvm.classes.loaded` - Loaded class count
466
467
### Web Metrics
468
- `http.server.requests` - HTTP request metrics
469
- `tomcat.sessions.active.max` - Maximum active sessions
470
- `tomcat.threads.busy` - Busy thread count
471
472
### Database Metrics
473
- `hikaricp.connections.active` - Active database connections
474
- `hikaricp.connections.idle` - Idle database connections
475
- `hikaricp.connections.pending` - Pending database connections
476
477
### Cache Metrics
478
- `cache.gets` - Cache get operations
479
- `cache.puts` - Cache put operations
480
- `cache.evictions` - Cache evictions
481
- `cache.size` - Cache size
482
483
## Configuration
484
485
Metrics system behavior can be configured through application properties:
486
487
```properties
488
# Enable/disable metrics endpoint
489
management.endpoint.metrics.enabled=true
490
491
# Configure Micrometer registry
492
management.metrics.enable.all=true
493
management.metrics.enable.jvm=true
494
management.metrics.enable.system=true
495
management.metrics.enable.web=true
496
497
# Prometheus export configuration
498
management.metrics.export.prometheus.enabled=true
499
management.endpoint.prometheus.enabled=true
500
501
# Push gateway configuration
502
management.metrics.export.prometheus.pushgateway.enabled=true
503
management.metrics.export.prometheus.pushgateway.base-url=http://localhost:9091
504
management.metrics.export.prometheus.pushgateway.job=spring-boot-app
505
506
# Distribution percentiles
507
management.metrics.distribution.percentiles.http.server.requests=0.5,0.95,0.99
508
management.metrics.distribution.slo.http.server.requests=50ms,100ms,200ms,500ms
509
510
# Tags for all metrics
511
management.metrics.tags.application=my-app
512
management.metrics.tags.environment=production
513
514
# Web request timing
515
management.metrics.web.server.request.autotime.enabled=true
516
management.metrics.web.server.request.autotime.percentiles=0.5,0.95,0.99
517
518
# Database metrics
519
management.metrics.jdbc.datasource-proxy.enabled=true
520
521
# Cache metrics
522
management.metrics.cache.instrument-cache=true
523
```