From 342b783e2652cb7adc9c2bf9a6f41dbecddc7a24 Mon Sep 17 00:00:00 2001 From: seonwoo_jung Date: Sun, 24 May 2026 14:15:49 +0900 Subject: [PATCH] Document metrics published by the micrometer module Adds a module-level README under micrometer/ that lists every metric emitted by MicrometerCapability (timers, counters, distribution summaries), its tags, and the observation emitted by MicrometerObservationCapability together with the keys carried by the default convention. The main README's Micrometer section now links to this reference. Fixes #2248 --- README.md | 3 + micrometer/README.md | 127 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 micrometer/README.md diff --git a/README.md b/README.md index 6e31ab89f0..cbaae10766 100644 --- a/README.md +++ b/README.md @@ -1190,6 +1190,9 @@ public class MyApp { } ``` +See the [micrometer module README](./micrometer/README.md) for the full list of +metrics that are published, their tags and how to use `MicrometerObservationCapability`. + #### Static and Default Methods Interfaces targeted by Feign may have static or default methods (if using Java 8+). These allows Feign clients to contain logic that is not expressly defined by the underlying API. diff --git a/micrometer/README.md b/micrometer/README.md new file mode 100644 index 0000000000..d060cefbe1 --- /dev/null +++ b/micrometer/README.md @@ -0,0 +1,127 @@ +Micrometer +=================== + +This module integrates Feign with [Micrometer](https://micrometer.io/) so that +HTTP calls made through Feign clients are observable through any Micrometer-supported +monitoring system (Prometheus, Datadog, CloudWatch, etc.). + +Two capabilities are provided: + +* `MicrometerCapability` — publishes timers, counters and distribution summaries + to a `MeterRegistry`. +* `MicrometerObservationCapability` — publishes Micrometer `Observation`s to an + `ObservationRegistry` (which can in turn produce metrics and tracing spans). + +Pick one — both record the same underlying call, so registering both would +double-count. + +## Usage + +### `MicrometerCapability` + +```java +GitHub github = Feign.builder() + .addCapability(new MicrometerCapability()) + .target(GitHub.class, "https://api.github.com"); +``` + +By default, metrics are registered with `io.micrometer.core.instrument.Metrics.globalRegistry`. +Pass your own registry and/or common tags if you want explicit control: + +```java +MeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); + +GitHub github = Feign.builder() + .addCapability(new MicrometerCapability(registry, Tags.of("application", "my-app"))) + .target(GitHub.class, "https://api.github.com"); +``` + +### `MicrometerObservationCapability` + +```java +ObservationRegistry observationRegistry = ObservationRegistry.create(); + +GitHub github = Feign.builder() + .addCapability(new MicrometerObservationCapability(observationRegistry)) + .target(GitHub.class, "https://api.github.com"); +``` + +To customize the tags or name of the observation, implement +`FeignObservationConvention` (or extend `DefaultFeignObservationConvention`) and +pass it to the constructor: + +```java +new MicrometerObservationCapability(observationRegistry, new MyFeignObservationConvention()); +``` + +## Metrics published by `MicrometerCapability` + +The capability instruments five stages of a Feign call. Each stage emits a +timer; counters and distribution summaries are emitted where noted. + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `feign.Feign` | Timer | Total time spent in the Feign method invocation, including encoding, the HTTP call and decoding. Recorded by `MeteredInvocationHandleFactory`. | +| `feign.Feign.exception` | Timer | Same as above, recorded when the invocation throws (any `Throwable`). | +| `feign.Feign.http_error` | Counter | Incremented once per `FeignException` thrown by an invocation. Adds `http_status` and `error_group` tags. | +| `feign.Client` | Timer | Time spent in the underlying HTTP client for a single request. Recorded by `MeteredClient`. | +| `feign.Client.exception` | Timer | Same as above, recorded when the HTTP call throws. | +| `feign.Client.http_response_code` | Counter | Incremented once per HTTP response (including error responses). Adds `http_status`, `status_group`, `http_method` and `uri` tags. | +| `feign.AsyncClient` | Timer | Async-equivalent of `feign.Client`. Recorded by `MeteredAsyncClient`. | +| `feign.AsyncClient.exception` | Timer | Async-equivalent of `feign.Client.exception`. | +| `feign.AsyncClient.http_response_code` | Counter | Async-equivalent of `feign.Client.http_response_code`. | +| `feign.codec.Encoder` | Timer | Time spent encoding the request body. Recorded by `MeteredEncoder`. | +| `feign.codec.Encoder.response_size` | DistributionSummary | Size, in bytes, of the encoded **request** body. The metric name predates the current behavior. | +| `feign.codec.Decoder` | Timer | Time spent decoding the response body. Recorded by `MeteredDecoder`. | +| `feign.codec.Decoder.exception` | Timer | Same as above, recorded when decoding throws. | +| `feign.codec.Decoder.response_size` | DistributionSummary | Size, in bytes, of the response body read by the decoder. | + +### Tags + +Every metric carries the following tags, populated by `FeignMetricTagResolver`: + +| Tag | Source | Example | +| --- | ------ | ------- | +| `client` | Target interface FQN | `com.example.GitHub` | +| `method` | Java method name | `contributors` | +| `host` | Host extracted from the target URL | `api.github.com` | +| `exception_name` | Exception simple name (only present on error) | `FeignException` | +| `root_cause_name` | Root cause exception simple name (only present on error) | `SocketTimeoutException` | + +Additional tags are added by specific metrics: + +* `feign.Client.http_response_code` / `feign.AsyncClient.http_response_code` — + adds `http_status` (e.g. `404`), `status_group` (e.g. `4xx`), `http_method` + (e.g. `GET`) and `uri` (the templated path, e.g. `/repos/{owner}/{repo}/contributors`). +* `feign.Feign.http_error` — adds `http_status` and `error_group` (e.g. `5xx`). +* `feign.codec.Decoder.*` — adds `uri`. + +You can attach extra common tags either through `MeterRegistry.config().commonTags(...)` +or via the `MicrometerCapability(MeterRegistry, List)` / +`MicrometerCapability(MeterRegistry, Map)` constructors. + +## Observation published by `MicrometerObservationCapability` + +A single observation is produced per HTTP call: + +| Name | Contextual name | Description | +| ---- | --------------- | ----------- | +| `http.client.requests` | `HTTP {method}` (e.g. `HTTP GET`) | One observation per HTTP request issued by the Feign client. The observation is stopped after the response is received or an exception is signalled. | + +The default convention (`DefaultFeignObservationConvention`) attaches the +following low-cardinality key values: + +| Key | Value | +| --- | ----- | +| `http.method` | The HTTP method (`GET`, `POST`, ...). `UNKNOWN` if the request is null. | +| `http.url` | The templated URL of the method. | +| `http.status_code` | The response status code, or `CLIENT_ERROR` if no response was received. | +| `clientName` | The target interface FQN. | + +The following key names are also declared on `FeignObservationDocumentation` and +are available for custom conventions to populate: `http.scheme`, `net.peer.host`, +`net.peer.port`. + +Whatever observation handlers are registered on the `ObservationRegistry` +(for example `DefaultMeterObservationHandler` for metrics, a tracing handler +for spans) decide what is ultimately emitted.