Jackson JSON serialization support for Dropwizard Metrics library
npx @tessl/cli install tessl/maven-io-dropwizard-metrics--metrics-json@4.2.0Jackson JSON serialization support for Dropwizard Metrics library. This package provides Jackson modules that serialize various metrics objects (gauges, counters, histograms, meters, timers) and health check results to JSON format, enabling applications to easily export metrics data for monitoring dashboards, APIs, or storage systems.
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-json</artifactId>
<version>4.2.33</version>
</dependency>import com.codahale.metrics.json.MetricsModule;
import com.codahale.metrics.json.HealthCheckModule;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.MetricFilter;
import java.util.concurrent.TimeUnit;import com.codahale.metrics.json.MetricsModule;
import com.codahale.metrics.json.HealthCheckModule;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Gauge;
import java.util.concurrent.TimeUnit;
// Configure ObjectMapper with metrics serialization
ObjectMapper mapper = new ObjectMapper()
.registerModule(new MetricsModule(TimeUnit.SECONDS, TimeUnit.MILLISECONDS, false))
.registerModule(new HealthCheckModule());
// Serialize a MetricRegistry to JSON
MetricRegistry registry = new MetricRegistry();
Counter counter = registry.counter("requests");
counter.inc();
String json = mapper.writeValueAsString(registry);
// Output: {"version":"4.0.0","gauges":{},"counters":{"requests":{"count":1}},"histograms":{},"meters":{},"timers":{}}
// Serialize individual metrics
Gauge<Integer> gauge = () -> 42;
String gaugeJson = mapper.writeValueAsString(gauge);
// Output: {"value":42}Required dependencies:
com.fasterxml.jackson.core:jackson-core (2.12.7)com.fasterxml.jackson.core:jackson-databind (2.12.7.2)io.dropwizard.metrics:metrics-core (4.2.33)Optional dependencies:
io.dropwizard.metrics:metrics-healthchecks (4.2.33) - Required for HealthCheckModuleProvides Jackson module for serializing Dropwizard Metrics objects to JSON format with configurable time units and filtering.
/**
* Jackson module for serializing Dropwizard Metrics objects to JSON
*/
public class MetricsModule extends Module {
/** Module version used for Jackson registration */
static final Version VERSION = new Version(4, 0, 0, "", "io.dropwizard.metrics", "metrics-json");
/**
* Creates a MetricsModule with specified time units and sample visibility
* @param rateUnit Time unit for rate calculations (e.g., TimeUnit.SECONDS)
* @param durationUnit Time unit for duration measurements (e.g., TimeUnit.MILLISECONDS)
* @param showSamples Whether to include raw sample values in histogram/timer serialization
*/
public MetricsModule(TimeUnit rateUnit, TimeUnit durationUnit, boolean showSamples);
/**
* Creates a MetricsModule with time units, sample visibility, and metric filtering
* @param rateUnit Time unit for rate calculations
* @param durationUnit Time unit for duration measurements
* @param showSamples Whether to include raw sample values in serialization
* @param filter Filter for selecting which metrics to serialize
*/
public MetricsModule(TimeUnit rateUnit, TimeUnit durationUnit, boolean showSamples, MetricFilter filter);
/**
* Returns the module name for Jackson registration
* @return "metrics"
*/
public String getModuleName();
/**
* Returns the module version
* @return Version object (4.0.0)
*/
public Version version();
/**
* Configures the Jackson module with serializers for all metric types
* @param context Jackson setup context
*/
public void setupModule(SetupContext context);
}Supported Metric Types:
The module provides JSON serialization for all Dropwizard Metrics types:
Configuration Options:
// Basic configuration with time units
MetricsModule module = new MetricsModule(
TimeUnit.SECONDS, // Rate unit - affects meter/timer rate calculations
TimeUnit.MILLISECONDS, // Duration unit - affects timer duration values
false // showSamples - whether to include raw sample data
);
// Advanced configuration with filtering
MetricsModule filteredModule = new MetricsModule(
TimeUnit.SECONDS,
TimeUnit.MILLISECONDS,
true, // Include sample values
MetricFilter.contains("api") // Only serialize metrics with "api" in name
);Provides Jackson module for serializing health check results with complete error information and metadata.
/**
* Jackson module for serializing health check results to JSON
*/
public class HealthCheckModule extends Module {
/**
* Creates a new HealthCheckModule with default configuration
*/
public HealthCheckModule();
/**
* Returns the module name for Jackson registration
* @return "healthchecks"
*/
public String getModuleName();
/**
* Returns the module version (same as MetricsModule.VERSION)
* @return Version object (4.0.0)
*/
public Version version();
/**
* Configures the Jackson module with health check result serializer
* @param context Jackson setup context
*/
public void setupModule(SetupContext context);
}Serialized Components:
The module serializes HealthCheck.Result objects with complete information:
Usage Example:
import com.codahale.metrics.health.HealthCheck;
import com.codahale.metrics.json.HealthCheckModule;
// Configure ObjectMapper
ObjectMapper mapper = new ObjectMapper()
.registerModule(new HealthCheckModule());
// Serialize health check result
HealthCheck.Result result = HealthCheck.Result.healthy("All systems operational");
String json = mapper.writeValueAsString(result);
// Output: {"healthy":true,"message":"All systems operational","duration":5,"timestamp":"2023-10-15T10:30:00Z"}
// Serialize failed health check with error
HealthCheck.Result failedResult = HealthCheck.Result.unhealthy("Database connection failed",
new SQLException("Connection timeout"));
String failedJson = mapper.writeValueAsString(failedResult);
// Output includes full error details with stack trace{
"value": 42
}On exception:
{
"error": "java.lang.RuntimeException: Gauge calculation failed"
}{
"count": 1337
}{
"count": 1000,
"max": 95.0,
"mean": 45.2,
"min": 1.0,
"p50": 44.0,
"p75": 67.5,
"p95": 89.2,
"p98": 92.1,
"p99": 94.3,
"p999": 95.0,
"stddev": 15.8,
"values": [1.0, 2.0, 3.0]
}Note: values array is only included when showSamples=true
{
"count": 5000,
"m15_rate": 12.5,
"m1_rate": 15.2,
"m5_rate": 13.8,
"mean_rate": 14.1,
"units": "events/second"
}{
"count": 2500,
"max": 250.5,
"mean": 45.2,
"min": 0.5,
"p50": 42.0,
"p75": 65.8,
"p95": 120.4,
"p98": 180.2,
"p99": 220.8,
"p999": 245.1,
"stddev": 25.4,
"values": [0.5, 1.2, 2.8],
"m15_rate": 8.2,
"m1_rate": 10.1,
"m5_rate": 9.5,
"mean_rate": 8.8,
"duration_units": "milliseconds",
"rate_units": "calls/second"
}Note: values array is only included when showSamples=true. All duration values (including individual values in the array) are scaled by the configured duration unit using a conversion factor of 1.0 / durationUnit.toNanos(1)
{
"version": "4.0.0",
"gauges": {
"jvm.memory.heap": {"value": 1234567890}
},
"counters": {
"requests.total": {"count": 12345}
},
"histograms": {
"response.size": {"count": 1000, "max": 95.0, "mean": 45.2, "min": 1.0, "p50": 44.0, "p75": 67.5, "p95": 89.2, "p98": 92.1, "p99": 94.3, "p999": 95.0, "stddev": 15.8}
},
"meters": {
"requests.rate": {"count": 5000, "m15_rate": 12.5, "m1_rate": 15.2, "m5_rate": 13.8, "mean_rate": 14.1, "units": "events/second"}
},
"timers": {
"requests.duration": {"count": 2500, "max": 250.5, "mean": 45.2, "min": 0.5, "p50": 42.0, "p75": 65.8, "p95": 120.4, "p98": 180.2, "p99": 220.8, "p999": 245.1, "stddev": 25.4, "m15_rate": 8.2, "m1_rate": 10.1, "m5_rate": 9.5, "mean_rate": 8.8, "duration_units": "milliseconds", "rate_units": "calls/second"}
}
}{
"healthy": true,
"message": "Database connection is healthy",
"duration": 15,
"timestamp": "2023-10-15T10:30:00Z",
"connection_pool_size": 10,
"active_connections": 3
}With error:
{
"healthy": false,
"message": "Database connection failed",
"error": {
"type": "java.sql.SQLException",
"message": "Connection timeout after 30 seconds",
"stack": [
"java.sql.DriverManager.getConnection(DriverManager.java:681)",
"com.example.DatabaseHealthCheck.check(DatabaseHealthCheck.java:25)"
],
"cause": {
"type": "java.net.SocketTimeoutException",
"message": "Read timeout",
"stack": ["java.net.SocketInputStream.socketRead0(Native Method)"]
}
},
"duration": 30000,
"timestamp": "2023-10-15T10:30:00Z"
}import java.util.concurrent.TimeUnit;
import com.codahale.metrics.MetricFilter;
import com.codahale.metrics.Metric;
import com.fasterxml.jackson.core.Version;
import com.fasterxml.jackson.databind.Module;
/**
* Jackson Module base class
*/
public abstract class Module {
public abstract String getModuleName();
public abstract Version version();
public abstract void setupModule(SetupContext context);
/**
* Setup context provided by Jackson during module registration
*/
public static interface SetupContext {
/** Add serializers for specific types */
void addSerializers(SimpleSerializers serializers);
/** Add deserializers for specific types */
void addDeserializers(SimpleDeserializers deserializers);
/** Add key serializers */
void addKeySerializers(SimpleKeySerializers keySerializers);
/** Add key deserializers */
void addKeyDeserializers(SimpleKeyDeserializers keyDeserializers);
/** Add abstract type resolvers */
void addAbstractTypeResolver(AbstractTypeResolver resolver);
/** Add type modifier */
void addTypeModifier(TypeModifier modifier);
/** Add value instantiators */
void addValueInstantiators(SimpleValueInstantiators instantiators);
/** Set bean serializer modifier */
void addBeanSerializerModifier(BeanSerializerModifier modifier);
/** Set bean deserializer modifier */
void addBeanDeserializerModifier(BeanDeserializerModifier modifier);
}
}
/**
* Predefined metric filters for selecting which metrics to serialize
*/
public interface MetricFilter {
/** Filter that accepts all metrics */
MetricFilter ALL = (name, metric) -> true;
/** Create filter that only accepts metrics whose names contain the given string */
static MetricFilter contains(String substring);
/** Determine if a metric should be included */
boolean matches(String name, Metric metric);
}
/**
* Base interface for all metrics
*/
public interface Metric {
// Marker interface for all metric types
}
/**
* Time units supported for rate and duration configuration
*/
public enum TimeUnit {
NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS;
/** Convert to seconds */
double toSeconds(long duration);
/** Convert to nanoseconds */
long toNanos(long duration);
}The modules handle errors gracefully: