How kenshoo/anodot-metrics-bridge works
1. What this repo is
- anodot-metrics-bridge is a Java/Gradle library that bridges an existing Dropwizard/Yammer Metrics registry into Anodot.
- The application keeps using its normal MetricRegistry/MetricsRegistry; this library mirrors that registry into Anodot-specific structures and periodically exports metrics to Anodot.
2. Top-level structure
- The repo is a multi-module Gradle project.
- Main modules are:
- anodot-reporter for the older metrics API line.
- anodot-reporter2 for one major metrics version.
- anodot-reporter3 for the other major metrics version.
- anodot-reporter-example as a usage sample.
- There is no application/server runtime here; this is a reusable library with tests and an example program.
3. Core architectural idea
- The bridge sits between an application’s metric collection layer and Anodot.
- Input boundary: the application’s existing metrics registry.
- Processing boundary: conversion of metric names and application of filters/global properties.
- Output boundary: an Anodot reporter wrapper that sends the mirrored metrics onward.
4. Shared concerns in the reporter layer
- The anodot-reporter module contains the shared configuration and property abstractions:
- AnodotProperties
- AnodotGlobalProperties
- AnodotReporterConfiguration
- AnodotReporterWrapper
- It also includes name parsing and default/empty global-property implementations.
- This module is the common architectural base for the version-specific reporter modules.
5. Metric name translation
- A key subsystem is metric-name parsing/conversion.
- DWMetricNameParser converts dot-separated Metrics names into Anodot-friendly key/value properties.
- The repository’s README shows the main mapping concepts: package, class, and what.
- This translation is important because Anodot models metrics as properties, not hierarchical dotted names.
6. Version-specific compatibility layers
- anodot-reporter2 and anodot-reporter3 provide separate compatibility stacks for the two major Metrics APIs.
- Each module has its own:
- metric name converter
- non-zero filter
- registry factory
- reporter builder
- reporter factory
- This separation lets both API families be supported independently, and the README says they can even coexist in the same application.
7. Filtering pipeline
- Metrics do not all get exported blindly.
- The default behavior is to suppress metrics until they have at least one non-zero value.
- The version-specific NonZeroFilter classes implement that default policy, and the builders allow turning it off or adding custom filters.
- This makes filtering a first-class part of the reporting pipeline, not an afterthought.
8. Global properties
- Another important transformation step is attaching static properties to every reported metric.
- AnodotGlobalProperties and DefaultAnodotGlobalProperties support values like server, version, build, and custom app identifiers.
- These properties are added per registry/reporting instance, which means they function as a deployment/runtime metadata layer over the metrics stream.
9. Factory and builder pattern
- The versioned modules use builders and factories to assemble the bridge:
- build the Anodot registry mirror
- apply name conversion
- attach filters
- attach global properties
- produce a stoppable/restartable reporter wrapper
- This indicates a composition-based design rather than direct instantiation, which is useful for integrating into different application lifecycles.
10. Example application boundary
- anodot-reporter-example demonstrates how an application would wire the reporter together.
- It acts as the integration reference point for consumers, showing the expected boundary between application code and the bridge library.
11. Tests as subsystem validation
- Each module has focused unit tests around the conversion and filtering behavior.
- The tests are concentrated in the version-specific modules, which matches the architecture: the riskiest logic is compatibility, parsing, and filter semantics.
12. Build and delivery
- The project is built with Gradle and published as versioned artifacts intended for JitPack.
- GitHub Actions workflows include CodeQL and dependency review/submission, so the repo has CI and security scanning around the library code rather than a deployment pipeline.
- Travis metadata is still present in the README badge, suggesting older CI history.
13. How to draw the architecture
- A useful diagram would show:
- an application emitting metrics into its existing Metrics registry
- a version-specific bridge module mirroring that registry
- a conversion/filtering stage
- optional global-property enrichment
- an AnodotReporterWrapper exporting to Anodot
- The primary external dependency is Anodot itself; the primary internal boundary is between common bridging logic and the two Metrics-version adapters.
Main entry points: Anodot2ReporterBuilder.java Reporter builder · Anodot3ReporterBuilder.java Reporter builder · AnodotGlobalProperties.java Global props · AnodotReporterFactoryExample.java Example wiring
Components 20
External systems
Input and output boundaries around the bridge library.
- Metrics registry · Existing Dropwizard/Yammer registry owned by the application and mirrored by the bridge.
- Anodot · External destination that receives exported metrics.
Shared bridge core
Common configuration, naming, and wrapper abstractions used by all reporter variants.
- Properties · Per-reporter property definitions and configuration inputs.
anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotProperties.java - Global props · Static deployment/runtime metadata attached to every reported metric.
anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotGlobalProperties.java - Name parser · Converts dotted metric names into Anodot-friendly properties such as package, class, and what.
anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/DWMetricNameParser.java - Reporter config · Shared reporter configuration and defaults for bridge assembly.
anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotReporterConfiguration.java - Reporter wrapper · Stoppable/restartable bridge that forwards mirrored metrics onward to Anodot.
anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotReporterWrapper.java - Default globals · Default implementation of global properties for common deployments.
anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/DefaultAnodotGlobalProperties.java - Empty globals · No-op global properties implementation when enrichment is not needed.
anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/EmptyAnodotGlobalProperties.java
Metrics v2 adapter
Compatibility layer for one major metrics API family.
- Name converter · Version-specific name conversion for the Metrics v2 compatibility stack.
anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2MetricNameConverter.java - Non-zero filter · Suppresses metrics until they have a non-zero value by default.
anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2NonZeroFilter.java - Registry factory · Builds the mirrored registry for the Metrics v2 path.
anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2RegistryFactory.java - Reporter builder · Composes conversion, filtering, and globals into a runnable reporter.
anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2ReporterBuilder.java - Reporter factory · Public entrypoint that creates the Metrics v2 reporter instance.
anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2ReporterFactory.java
Metrics v3 adapter
Compatibility layer for the other major metrics API family.
- Name converter · Version-specific name conversion for the Metrics v3 compatibility stack.
anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3MetricNameConverter.java - Non-zero filter · Suppresses metrics until they have a non-zero value by default.
anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3NonZeroFilter.java - Registry factory · Builds the mirrored registry for the Metrics v3 path.
anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3RegistryFactory.java - Reporter builder · Composes conversion, filtering, and globals into a runnable reporter.
anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3ReporterBuilder.java - Reporter factory · Public entrypoint that creates the Metrics v3 reporter instance.
anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3ReporterFactory.java
Example app
Usage sample showing how consumers wire the bridge.
- Example wiring · Usage example showing how an application wires the bridge together.
anodot-reporter-example/src/main/java/com/kenshoo/metrics/anodot/example/AnodotReporterFactoryExample.java
Connections 23
- Metrics registry → Registry factory: mirror registry · Metrics v2 adapter reads the application's registry and mirrors it into Anodot structures.
- Metrics registry → Registry factory: mirror registry · Metrics v3 adapter reads the application's registry and mirrors it into Anodot structures.
- Registry factory → Name converter: convert names · Registry factory relies on version-specific name conversion before export.
- Registry factory → Non-zero filter: apply filter · Registry factory suppresses metrics until they meet the default non-zero policy.
- Reporter builder → Reporter wrapper: compose · Builder assembles the shared reporter wrapper with adapter-specific pieces.
- Reporter builder → Properties: use config · Builder consumes shared configuration abstractions.
- Reporter builder → Global props: attach globals · Builder enriches metrics with static deployment/runtime metadata.
- Reporter builder → Reporter config: use config · Builder relies on shared reporter configuration and defaults.
- Reporter factory → Reporter builder: create · Factory is the public entrypoint for constructing the v2 reporter.
- Registry factory → Name converter: convert names · Registry factory relies on version-specific name conversion before export.
- Registry factory → Non-zero filter: apply filter · Registry factory suppresses metrics until they meet the default non-zero policy.
- Reporter builder → Reporter wrapper: compose · Builder assembles the shared reporter wrapper with adapter-specific pieces.
- Reporter builder → Properties: use config · Builder consumes shared configuration abstractions.
- Reporter builder → Global props: attach globals · Builder enriches metrics with static deployment/runtime metadata.
- Reporter builder → Reporter config: use config · Builder relies on shared reporter configuration and defaults.
- Reporter factory → Reporter builder: create · Factory is the public entrypoint for constructing the v3 reporter.
- Reporter config → Name parser: parse names · Shared configuration includes the common naming translation layer.
- Global props → Default globals: default impl · Default global-properties implementation provides common metadata values.
- Global props → Empty globals: no-op impl · Empty implementation disables enrichment when required.
- Reporter wrapper → Anodot: export · Final reporting wrapper sends the mirrored metrics to Anodot.
- Example wiring → Reporter factory: demonstrates · Example shows how consumers can wire the v2 reporter path.
- Example wiring → Reporter factory: demonstrates · Example shows how consumers can wire the v3 reporter path.
- Example wiring → Metrics registry: uses · Sample application starts from a normal metrics registry.