Back to Javalin

Javalin Micrometer Plugin

javalin-micrometer/README.md

7.1.06.2 KB
Original Source

Javalin Micrometer Plugin

Micrometer metrics integration for Javalin! This plugin provides automatic HTTP request metrics and supports various metrics registries.

Getting started

Add the dependency to your project:

Maven

xml
<dependency>
  <groupId>io.javalin</groupId>
  <artifactId>javalin-micrometer</artifactId>
  <version>${javalin.version}</version>
</dependency>

Gradle

kotlin
implementation("io.javalin:javalin-micrometer:$javalinVersion")

Module Support

This module provides full Java Module System (JPMS) support:

  • Module name: io.javalin.micrometer
  • Automatic-Module-Name: io.javalin.micrometer (for non-modular environments)

Add to your module-info.java:

java
requires io.javalin.micrometer;

Configuration

Register the plugin when creating your Javalin application:

Java

java
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;
    }));
});

Kotlin

kotlin
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
    })
}

Configuration Options

OptionTypeDefaultDescription
registryMeterRegistryMetrics.globalRegistryThe meter registry to use for metrics
tagsIterable<Tag>Tags.empty()Additional tags to add to all metrics
tagExceptionNamebooleanfalseWhether to tag exception names in metrics
tagRedirectPathsbooleanfalseWhether to tag redirect paths with actual path instead of "REDIRECTION"
tagNotFoundMappedPathsbooleanfalseWhether to tag 404s from mapped paths with actual path instead of "NOT_FOUND"

Metrics Collected

HTTP Request Metrics

  • Timer: 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 code
    • outcome - Request outcome (SUCCESS, CLIENT_ERROR, SERVER_ERROR, REDIRECTION)
    • exception - Exception name (if tagExceptionName is enabled and exception was thrown)
    • Any custom tags configured

Jetty Server Metrics

  • Thread pool metrics - Jetty server thread pool statistics
  • Connection metrics - HTTP connection statistics

Registry Support

The plugin works with any Micrometer registry:

java
// 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.
}));

Example with Prometheus

java
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);
    }
}

Exception Tagging

To properly tag exceptions in metrics, you need to delegate to the Micrometer exception handler:

java
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:

java
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());
    });
});

Requirements

  • Java 17+
  • Javalin 7.0+
  • Jetty 12+
  • Micrometer Core 1.14+

About Javalin