javalin-micrometer/README.md
Micrometer metrics integration for Javalin! This plugin provides automatic HTTP request metrics and supports various metrics registries.
Add the dependency to your project:
<dependency>
<groupId>io.javalin</groupId>
<artifactId>javalin-micrometer</artifactId>
<version>${javalin.version}</version>
</dependency>
implementation("io.javalin:javalin-micrometer:$javalinVersion")
This module provides full Java Module System (JPMS) support:
io.javalin.micrometerio.javalin.micrometer (for non-modular environments)Add to your module-info.java:
requires io.javalin.micrometer;
Register the plugin when creating your Javalin application:
import io.javalin.micrometer.MicrometerPlugin;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
Javalin.create(config -> {
config.registerPlugin(new MicrometerPlugin()); // Uses global registry
// OR with custom configuration
config.registerPlugin(new MicrometerPlugin(plugin -> {
plugin.registry = new SimpleMeterRegistry();
plugin.tags = Tags.of("service", "my-app", "version", "1.0");
plugin.tagExceptionName = true;
}));
});
import io.javalin.micrometer.MicrometerPlugin
import io.micrometer.core.instrument.simple.SimpleMeterRegistry
Javalin.create { config ->
config.registerPlugin(MicrometerPlugin()) // Uses global registry
// OR with custom configuration
config.registerPlugin(MicrometerPlugin { plugin ->
plugin.registry = SimpleMeterRegistry()
plugin.tags = Tags.of("service", "my-app", "version", "1.0")
plugin.tagExceptionName = true
})
}
| Option | Type | Default | Description |
|---|---|---|---|
registry | MeterRegistry | Metrics.globalRegistry | The meter registry to use for metrics |
tags | Iterable<Tag> | Tags.empty() | Additional tags to add to all metrics |
tagExceptionName | boolean | false | Whether to tag exception names in metrics |
tagRedirectPaths | boolean | false | Whether to tag redirect paths with actual path instead of "REDIRECTION" |
tagNotFoundMappedPaths | boolean | false | Whether to tag 404s from mapped paths with actual path instead of "NOT_FOUND" |
http.server.requests - Request duration with tags:
method - HTTP method (GET, POST, etc.)uri - Request URI template (parameterized to avoid high cardinality)status - HTTP status codeoutcome - Request outcome (SUCCESS, CLIENT_ERROR, SERVER_ERROR, REDIRECTION)exception - Exception name (if tagExceptionName is enabled and exception was thrown)The plugin works with any Micrometer registry:
// Prometheus
PrometheusMeterRegistry prometheusRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
// InfluxDB
InfluxMeterRegistry influxRegistry = new InfluxMeterRegistry(InfluxConfig.DEFAULT);
// CloudWatch
CloudWatchMeterRegistry cloudWatchRegistry = new CloudWatchMeterRegistry(CloudWatchConfig.DEFAULT);
// Use any registry
config.registerPlugin(new MicrometerPlugin(plugin -> {
plugin.registry = prometheusRegistry; // or influxRegistry, cloudWatchRegistry, etc.
}));
import io.javalin.Javalin;
import io.javalin.micrometer.MicrometerPlugin;
import io.micrometer.core.instrument.Tags;
import io.micrometer.prometheus.PrometheusConfig;
import io.micrometer.prometheus.PrometheusMeterRegistry;
public class App {
public static void main(String[] args) {
PrometheusMeterRegistry prometheusRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT);
Javalin app = Javalin.create(config -> {
config.registerPlugin(new MicrometerPlugin(plugin -> {
plugin.registry = prometheusRegistry;
plugin.tags = Tags.of("service", "my-api");
plugin.tagExceptionName = true;
}));
});
app.get("/", ctx -> ctx.result("Hello World"));
app.get("/metrics", ctx -> ctx.result(prometheusRegistry.scrape()));
// Delegate exceptions to Micrometer for proper tagging
app.exception(Exception.class, MicrometerPlugin.exceptionHandler);
app.start(7000);
}
}
To properly tag exceptions in metrics, you need to delegate to the Micrometer exception handler:
app.exception(Exception.class, MicrometerPlugin.exceptionHandler);
// Or for specific exceptions:
app.exception(IllegalArgumentException.class, (e, ctx) -> {
MicrometerPlugin.exceptionHandler.handle(e, ctx);
});
For WebSocket exception handling, use the dedicated WebSocket exception handler:
Javalin.create(config -> {
// Note: registering a wsException handler prevents Javalin's default behavior
// of closing the socket on uncaught exceptions. You should close the session yourself:
config.routes.wsException(Exception.class, (e, ctx) -> {
MicrometerPlugin.wsExceptionHandler.handle(e, ctx);
ctx.closeSession(WsCloseStatus.SERVER_ERROR, e.getMessage());
});
});