# kenshoo/anodot-metrics-bridge architecture

> Architecture diagram of the GitHub repository kenshoo/anodot-metrics-bridge, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-22). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/kenshoo/anodot-metrics-bridge
- Repository: https://github.com/kenshoo/anodot-metrics-bridge

## Overview

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: [`anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2ReporterBuilder.java`](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2ReporterBuilder.java) (Reporter builder), [`anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3ReporterBuilder.java`](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3ReporterBuilder.java) (Reporter builder), [`anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotGlobalProperties.java`](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotGlobalProperties.java) (Global props), [`anodot-reporter-example/src/main/java/com/kenshoo/metrics/anodot/example/AnodotReporterFactoryExample.java`](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter-example/src/main/java/com/kenshoo/metrics/anodot/example/AnodotReporterFactoryExample.java) (Example wiring)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_external["External systems"]
  node_app_registry[("Metrics registry<br/>app metric store")]
  node_anodot[("Anodot<br/>metrics backend")]
end

subgraph group_shared["Shared bridge core"]
  node_anodot_properties["Properties<br/>config model"]
  node_global_properties["Global props<br/>metadata layer"]
  node_dw_parser["Name parser<br/>name translation"]
  node_reporter_config["Reporter config<br/>reporting config"]
  node_reporter_wrapper["Reporter wrapper<br/>export wrapper"]
  node_default_globals["Default globals<br/>default metadata"]
  node_empty_globals["Empty globals<br/>null metadata"]
end

subgraph group_metrics2["Metrics v2 adapter"]
  node_metrics2_converter["Name converter<br/>metrics2 adapter"]
  node_metrics2_filter["Non-zero filter<br/>metrics2 filter"]
  node_metrics2_registry["Registry factory<br/>metrics2 adapter"]
  node_metrics2_builder["Reporter builder<br/>metrics2 assembly"]
  node_metrics2_factory["Reporter factory<br/>metrics2 entrypoint"]
end

subgraph group_metrics3["Metrics v3 adapter"]
  node_metrics3_converter["Name converter<br/>metrics3 adapter"]
  node_metrics3_filter["Non-zero filter<br/>metrics3 filter"]
  node_metrics3_registry["Registry factory<br/>metrics3 adapter"]
  node_metrics3_builder["Reporter builder<br/>metrics3 assembly"]
  node_metrics3_factory["Reporter factory<br/>metrics3 entrypoint"]
end

subgraph group_example["Example app"]
  node_example_app["Example wiring<br/>sample app"]
end

node_app_registry -->|"mirror registry"| node_metrics2_registry
node_app_registry -->|"mirror registry"| node_metrics3_registry
node_metrics2_registry -->|"convert names"| node_metrics2_converter
node_metrics2_registry -->|"apply filter"| node_metrics2_filter
node_metrics2_builder -->|"compose"| node_reporter_wrapper
node_metrics2_builder -->|"use config"| node_anodot_properties
node_metrics2_builder -->|"attach globals"| node_global_properties
node_metrics2_builder -->|"use config"| node_reporter_config
node_metrics2_factory -->|"create"| node_metrics2_builder
node_metrics3_registry -->|"convert names"| node_metrics3_converter
node_metrics3_registry -->|"apply filter"| node_metrics3_filter
node_metrics3_builder -->|"compose"| node_reporter_wrapper
node_metrics3_builder -->|"use config"| node_anodot_properties
node_metrics3_builder -->|"attach globals"| node_global_properties
node_metrics3_builder -->|"use config"| node_reporter_config
node_metrics3_factory -->|"create"| node_metrics3_builder
node_reporter_config -->|"parse names"| node_dw_parser
node_global_properties -->|"default impl"| node_default_globals
node_global_properties -->|"no-op impl"| node_empty_globals
node_reporter_wrapper -->|"export"| node_anodot
node_example_app -->|"demonstrates"| node_metrics2_factory
node_example_app -->|"demonstrates"| node_metrics3_factory
node_example_app -->|"uses"| node_app_registry

click node_anodot_properties "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotProperties.java"
click node_global_properties "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotGlobalProperties.java"
click node_dw_parser "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/DWMetricNameParser.java"
click node_reporter_config "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotReporterConfiguration.java"
click node_reporter_wrapper "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotReporterWrapper.java"
click node_default_globals "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/DefaultAnodotGlobalProperties.java"
click node_empty_globals "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/EmptyAnodotGlobalProperties.java"
click node_metrics2_converter "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2MetricNameConverter.java"
click node_metrics2_filter "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2NonZeroFilter.java"
click node_metrics2_registry "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2RegistryFactory.java"
click node_metrics2_builder "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2ReporterBuilder.java"
click node_metrics2_factory "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2ReporterFactory.java"
click node_metrics3_converter "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3MetricNameConverter.java"
click node_metrics3_filter "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3NonZeroFilter.java"
click node_metrics3_registry "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3RegistryFactory.java"
click node_metrics3_builder "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3ReporterBuilder.java"
click node_metrics3_factory "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3ReporterFactory.java"
click node_example_app "https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter-example/src/main/java/com/kenshoo/metrics/anodot/example/AnodotReporterFactoryExample.java"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_app_registry,node_anodot toneBlue
class node_anodot_properties,node_global_properties,node_dw_parser,node_reporter_config,node_reporter_wrapper,node_default_globals,node_empty_globals toneAmber
class node_metrics2_converter,node_metrics2_filter,node_metrics2_registry,node_metrics2_builder,node_metrics2_factory toneMint
class node_metrics3_converter,node_metrics3_filter,node_metrics3_registry,node_metrics3_builder,node_metrics3_factory toneRose
class node_example_app toneIndigo
```

## Components

### External systems

Input and output boundaries around the bridge library.

- **Metrics registry**: app metric store · Existing Dropwizard/Yammer registry owned by the application and mirrored by the bridge.
- **Anodot**: metrics backend · External destination that receives exported metrics.

### Shared bridge core

Common configuration, naming, and wrapper abstractions used by all reporter variants.

- [Properties](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotProperties.java): config model · Per-reporter property definitions and configuration inputs. · `anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotProperties.java`
- [Global props](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotGlobalProperties.java): metadata layer · Static deployment/runtime metadata attached to every reported metric. · `anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotGlobalProperties.java`
- [Name parser](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/DWMetricNameParser.java): name translation · 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](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotReporterConfiguration.java): reporting config · Shared reporter configuration and defaults for bridge assembly. · `anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotReporterConfiguration.java`
- [Reporter wrapper](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotReporterWrapper.java): export wrapper · Stoppable/restartable bridge that forwards mirrored metrics onward to Anodot. · `anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/AnodotReporterWrapper.java`
- [Default globals](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/DefaultAnodotGlobalProperties.java): default metadata · Default implementation of global properties for common deployments. · `anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/DefaultAnodotGlobalProperties.java`
- [Empty globals](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter/src/main/java/com/kenshoo/metrics/anodot/EmptyAnodotGlobalProperties.java): null metadata · 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](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2MetricNameConverter.java): metrics2 adapter · 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](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2NonZeroFilter.java): metrics2 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](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2RegistryFactory.java): metrics2 adapter · Builds the mirrored registry for the Metrics v2 path. · `anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2RegistryFactory.java`
- [Reporter builder](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2ReporterBuilder.java): metrics2 assembly · Composes conversion, filtering, and globals into a runnable reporter. · `anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2ReporterBuilder.java`
- [Reporter factory](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter2/src/main/java/com/kenshoo/metrics/anodot/metrics2/Anodot2ReporterFactory.java): metrics2 entrypoint · 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](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3MetricNameConverter.java): metrics3 adapter · 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](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3NonZeroFilter.java): metrics3 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](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3RegistryFactory.java): metrics3 adapter · Builds the mirrored registry for the Metrics v3 path. · `anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3RegistryFactory.java`
- [Reporter builder](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3ReporterBuilder.java): metrics3 assembly · Composes conversion, filtering, and globals into a runnable reporter. · `anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3ReporterBuilder.java`
- [Reporter factory](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter3/src/main/java/com/kenshoo/metrics/anodot/metrics3/Anodot3ReporterFactory.java): metrics3 entrypoint · 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](https://github.com/kenshoo/anodot-metrics-bridge/blob/master/anodot-reporter-example/src/main/java/com/kenshoo/metrics/anodot/example/AnodotReporterFactoryExample.java): sample app · Usage example showing how an application wires the bridge together. · `anodot-reporter-example/src/main/java/com/kenshoo/metrics/anodot/example/AnodotReporterFactoryExample.java`

## Connections

- 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.
