Comprehensive developer toolkit providing reusable skills for Java/Spring Boot, TypeScript/NestJS/React/Next.js, Python, PHP, AWS CloudFormation, AI/RAG, DevOps, and more.
82
82%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Risky
Do not use without reviewing
Spring Boot Actuator provides dependency management and auto-configuration for Micrometer, an application metrics facade that supports numerous monitoring systems, including:
TIP
To learn more about Micrometer's capabilities, see its reference documentation, in particular the concepts section.
Spring Boot auto-configures a composite MeterRegistry and adds a registry to the composite for each of the supported implementations that it finds on the classpath. Having a dependency on micrometer-registry-{system} in your runtime classpath is enough for Spring Boot to configure the registry.
Most registries share common features. For instance, you can disable a particular registry even if the Micrometer registry implementation is on the classpath. The following example disables Datadog:
management:
datadog:
metrics:
export:
enabled: falseYou can also disable all registries unless stated otherwise by the registry-specific property, as the following example shows:
management:
defaults:
metrics:
export:
enabled: falseSpring Boot also adds any auto-configured registries to the global static composite registry on the Metrics class, unless you explicitly tell it not to:
management:
metrics:
use-global-registry: falseYou can register any number of MeterRegistryCustomizer beans to further configure the registry, such as applying common tags, before any meters are registered with the registry:
@Component
public class MyMeterRegistryConfiguration {
@Bean
public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
return registry -> registry.config().commonTags("region", "us-east-1");
}
}You can apply customizations to particular registry implementations by being more specific about the generic type:
@Component
public class MyMeterRegistryConfiguration {
@Bean
public MeterRegistryCustomizer<GraphiteMeterRegistry> graphiteMetricsNamingConvention() {
return registry -> registry.config().namingConvention(this::toGraphiteConvention);
}
private String toGraphiteConvention(String name, Meter.Type type, String baseUnit) {
return name.toLowerCase().replace(".", "_");
}
}Spring Boot also configures built-in instrumentation that you can control through configuration or dedicated annotation markers.
Spring Boot provides automatic meter registration for a wide variety of technologies. In most situations, the defaults provide sensible metrics that can be published to any of the supported monitoring systems.
JVM metrics are published under the jvm. meter name. The following JVM metrics are provided:
System metrics are published under the system., process., and disk. meter names. The following system metrics are provided:
Application startup metrics are published under the application.started.time meter name. The following startup metrics are provided:
HTTP request metrics are automatically recorded for all HTTP requests. Metrics are published under the http.server.requests meter name.
Tags added to HTTP server request metrics:
method: The request's HTTP method (e.g., GET or POST)uri: The request's URI template prior to variable substitution (e.g., /api/person/{id})status: The response's HTTP status code (e.g., 200 or 500)outcome: The request's outcome based on the status code (SUCCESS, REDIRECTION, CLIENT_ERROR, SERVER_ERROR, or UNKNOWN)To customize the tags, provide a @Bean that implements WebMvcTagsContributor:
@Component
public class MyWebMvcTagsContributor implements WebMvcTagsContributor {
@Override
public Iterable<Tag> getTags(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Throwable exception) {
return Tags.of("custom.tag", "custom-value");
}
@Override
public Iterable<Tag> getLongRequestTags(HttpServletRequest request,
Object handler) {
return Tags.of("custom.tag", "custom-value");
}
}WebFlux metrics are automatically recorded for all WebFlux requests. Metrics are published under the http.server.requests meter name.
Tags added to WebFlux request metrics:
method: The request's HTTP methoduri: The request's URI templatestatus: The response's HTTP status codeoutcome: The request's outcomeAuto-configuration enables the instrumentation of all available DataSource objects with metrics prefixed with hikaricp., tomcat.datasource., or dbcp2..
Connection pool metrics are published under the following meter names:
hikaricp.connections (HikariCP)tomcat.datasource.connections (Tomcat)dbcp2.connections (Apache DBCP2)Auto-configuration enables the instrumentation of all available Cache managers on startup with metrics prefixed with cache.. The cache instrumentation is standardized for a basic set of metrics.
Cache metrics include:
Auto-configuration enables the instrumentation of all available ThreadPoolTaskExecutor and ThreadPoolTaskScheduler beans with metrics prefixed with executor. and scheduler. respectively.
Executor metrics include:
To record your own metrics, inject MeterRegistry into your component:
@Component
public class MyService {
private final Counter counter;
private final Timer timer;
private final Gauge gauge;
public MyService(MeterRegistry meterRegistry) {
this.counter = Counter.builder("my.counter")
.description("A simple counter")
.register(meterRegistry);
this.timer = Timer.builder("my.timer")
.description("A simple timer")
.register(meterRegistry);
this.gauge = Gauge.builder("my.gauge")
.description("A simple gauge")
.register(meterRegistry, this, MyService::calculateGaugeValue);
}
public void doSomething() {
counter.increment();
Timer.Sample sample = Timer.start(meterRegistry);
// ... do work
sample.stop(timer);
}
private double calculateGaugeValue(MyService self) {
return Math.random();
}
}You can use the @Timed annotation to time method executions:
@Component
public class MyService {
@Timed(name = "my.method.time", description = "Time taken to execute my method")
public void timedMethod() {
// method body
}
}For the @Timed annotation to work, you need to enable timing support:
@Configuration
@EnableConfigurationProperties
public class TimedConfiguration {
@Bean
public TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}
}You can use the @Counted annotation to count method invocations:
@Component
public class MyService {
@Counted(name = "my.method.count", description = "Number of times my method is called")
public void countedMethod() {
// method body
}
}For the @Counted annotation to work, you need to enable counting support:
@Configuration
public class CountedConfiguration {
@Bean
public CountedAspect countedAspect(MeterRegistry registry) {
return new CountedAspect(registry);
}
}You can register any number of MeterFilter beans to control how meters are registered:
@Configuration
public class MetricsConfiguration {
@Bean
public MeterFilter renameFilter() {
return MeterFilter.rename("old.metric.name", "new.metric.name");
}
@Bean
public MeterFilter denyFilter() {
return MeterFilter.deny(id -> id.getName().contains("unwanted"));
}
@Bean
public MeterFilter tagFilter() {
return MeterFilter.commonTags("application", "my-app");
}
}The metrics endpoint provides access to all the metrics collected by the application. You can view the names of all available meters by visiting /actuator/metrics.
To view the value of a particular meter, specify its name as a path parameter:
GET /actuator/metrics/jvm.memory.usedThe response contains the meter's measurements:
{
"name": "jvm.memory.used",
"description": "The amount of used memory",
"baseUnit": "bytes",
"measurements": [
{
"statistic": "VALUE",
"value": 8.73E8
}
],
"availableTags": [
{
"tag": "area",
"values": ["heap", "nonheap"]
},
{
"tag": "id",
"values": ["Compressed Class Space", "PS Eden Space", "PS Survivor Space"]
}
]
}You can drill down to a particular meter by adding query parameters:
GET /actuator/metrics/jvm.memory.used?tag=area:heap&tag=id:PS%20Eden%20SpaceTo export metrics to Prometheus, add the following dependency:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>This exposes a /actuator/prometheus endpoint that presents metrics in the format expected by a Prometheus server.
Configuration example:
management:
endpoints:
web:
exposure:
include: "prometheus"
metrics:
export:
prometheus:
enabled: true
step: 1m
descriptions: trueTo export metrics to Datadog, add the following dependency:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-datadog</artifactId>
</dependency>Configuration:
management:
metrics:
export:
datadog:
api-key: ${DATADOG_API_KEY}
application-key: ${DATADOG_APP_KEY}
uri: https://api.datadoghq.com
step: 1mTo export metrics to InfluxDB, add the following dependency:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-influx</artifactId>
</dependency>Configuration:
management:
metrics:
export:
influx:
uri: http://localhost:8086
db: mydb
username: ${INFLUX_USERNAME}
password: ${INFLUX_PASSWORD}
step: 1mTo export metrics to New Relic, add the following dependency:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-newrelic</artifactId>
</dependency>Configuration:
management:
metrics:
export:
newrelic:
api-key: ${NEW_RELIC_API_KEY}
account-id: ${NEW_RELIC_ACCOUNT_ID}
step: 1mThe simple registry is automatically configured if no other registry is found on the classpath. It stores metrics in memory and is useful for development and testing:
management:
metrics:
export:
simple:
enabled: true
step: 1mBe mindful of meter cardinality when adding tags. High-cardinality tags (like user IDs) can lead to performance issues:
// Bad - high cardinality
Timer.builder("user.request.time")
.tag("user.id", userId) // Could be millions of different values
.register(registry);
// Good - low cardinality
Timer.builder("user.request.time")
.tag("user.type", userType) // Limited number of values
.register(registry);For high-throughput applications, consider using sampling to reduce overhead:
@Bean
public MeterFilter samplingFilter() {
return MeterFilter.maximumExpectedValue("http.server.requests",
Duration.ofMillis(500));
}Configure appropriate publishing intervals to balance between timeliness and performance:
management:
metrics:
export:
prometheus:
step: 30s # Adjust based on your needsBe careful not to include sensitive information in metric tags or names:
// Bad - exposes sensitive data
Counter.builder("login.attempts")
.tag("username", username) // Could expose usernames
.register(registry);
// Good - uses hashed or anonymized data
Counter.builder("login.attempts")
.tag("outcome", successful ? "success" : "failure")
.register(registry);Secure the metrics endpoint in production:
management:
endpoints:
web:
exposure:
include: "metrics"
endpoint:
metrics:
access: restrictedOr using Spring Security:
@Configuration
public class ActuatorSecurity {
@Bean
public SecurityFilterChain actuatorSecurityFilterChain(HttpSecurity http) throws Exception {
return http
.requestMatcher(EndpointRequest.toAnyEndpoint())
.authorizeHttpRequests(requests ->
requests.anyRequest().hasRole("ACTUATOR"))
.httpBasic(withDefaults())
.build();
}
}plugins
developer-kit-ai
skills
chunking-strategy
prompt-engineering
developer-kit-aws
skills
aws
aws-cli-beast
aws-cost-optimization
aws-drawio-architecture-diagrams
aws-sam-bootstrap
aws-cloudformation
aws-cloudformation-auto-scaling
references
aws-cloudformation-bedrock
references
aws-cloudformation-cloudfront
references
aws-cloudformation-cloudwatch
references
aws-cloudformation-dynamodb
references
aws-cloudformation-ec2
aws-cloudformation-ecs
references
aws-cloudformation-elasticache
aws-cloudformation-iam
references
aws-cloudformation-lambda
references
aws-cloudformation-rds
aws-cloudformation-s3
references
aws-cloudformation-security
references
aws-cloudformation-task-ecs-deploy-gh
aws-cloudformation-vpc
developer-kit-core
skills
developer-kit-java
skills
aws-lambda-java-integration
aws-rds-spring-boot-integration
aws-sdk-java-v2-bedrock
aws-sdk-java-v2-core
aws-sdk-java-v2-dynamodb
aws-sdk-java-v2-kms
aws-sdk-java-v2-lambda
aws-sdk-java-v2-messaging
aws-sdk-java-v2-rds
aws-sdk-java-v2-s3
aws-sdk-java-v2-secrets-manager
graalvm-native-image
langchain4j
langchain4j-mcp-server-patterns
langchain4j-ai-services-patterns
references
langchain4j-mcp-server-patterns
references
langchain4j-rag-implementation-patterns
references
langchain4j-spring-boot-integration
langchain4j-testing-strategies
langchain4j-tool-function-calling-patterns
langchain4j-vector-stores-configuration
references
qdrant
references
spring-ai-mcp-server-patterns
references
spring-boot-actuator
spring-boot-cache
spring-boot-crud-patterns
spring-boot-dependency-injection
spring-boot-event-driven-patterns
spring-boot-openapi-documentation
spring-boot-project-creator
spring-boot-resilience4j
spring-boot-rest-api-standards
spring-boot-saga-pattern
spring-boot-security-jwt
assets
references
scripts
spring-boot-test-patterns
spring-data-jpa
references
spring-data-neo4j
references
unit-test-application-events
unit-test-bean-validation
unit-test-boundary-conditions
unit-test-caching
unit-test-config-properties
unit-test-controller-layer
unit-test-exception-handler
unit-test-json-serialization
unit-test-mapper-converter
unit-test-parameterized
unit-test-scheduled-async
unit-test-service-layer
unit-test-utility-methods
unit-test-wiremock-rest-api
developer-kit-php
skills
aws-lambda-php-integration
developer-kit-python
skills
aws-lambda-python-integration
developer-kit-tools
developer-kit-typescript
skills
aws-lambda-typescript-integration
better-auth
drizzle-orm-patterns
dynamodb-toolbox-patterns
references
nestjs
nestjs-best-practices
nestjs-code-review
nestjs-drizzle-crud-generator
scripts
nextjs-app-router
nextjs-authentication
nextjs-code-review
nextjs-data-fetching
references
nextjs-deployment
nextjs-performance
nx-monorepo
react-code-review
react-patterns
references
shadcn-ui
tailwind-css-patterns
references
tailwind-design-system
references
turborepo-monorepo
typescript-docs
typescript-security-review
zod-validation-utilities