rursprung opened a new pull request, #906:
URL: https://github.com/apache/httpcomponents-client/pull/906

   (full disclosure: AI-generated, reviewed by me)
   
   ### What
   
   Adds request and response body size metrics to `httpclient5-observation`
   for classic and async clients:
   
   | Meter | Type | Unit |
   |---|---|---|
   | `<prefix>.request.body.size` | `DistributionSummary` | bytes |
   | `<prefix>.response.body.size` | `DistributionSummary` | bytes |
   
   Enable with the new `ObservingOptions.MetricSet.BODY_SIZE`:
   
   ```java
   ObservingOptions opts = ObservingOptions.builder()
           .metrics(EnumSet.of(MetricSet.BASIC, MetricSet.BODY_SIZE))
           .build();
   HttpClientObservationSupport.enable(builder, obsReg, meterReg, opts);
   ```
   
   All four `enable(...)` variants (classic, async, caching classic, caching
   async) install the new `BodySizeExec` / `AsyncBodySizeExec` interceptors.
   The interceptors are public, so they can also be added by hand.
   
   ### Why
   
   Many libraries are built on HttpClient 5 and leave metrics to the user
   (for example `opensearch-java`). Users want to know how big their payloads
   are, for example large OpenSearch `_bulk` requests. The existing `IO`
   counters only give a total.
   
   Background:
   
   * micrometer-metrics/micrometer#880 asks for HTTP request/response size
     metrics. The Micrometer team said
     
([comment](https://github.com/micrometer-metrics/micrometer/issues/880#issuecomment-1625381050))
     that it must be done per HTTP library: `Content-Length` is missing for
     chunked bodies, and compression makes the body size differ from the bytes
     on the network.
   * micrometer-metrics/micrometer#7158 deprecates Micrometer's own hc5 binder
     (since 1.17.0) in favor of `httpclient5-observation`. New HttpClient 5
     instrumentation features therefore belong here.
   
   ### Design
   
   * **Additive and opt-in.** The `IO` counters keep their names, types and
     tags. Changing them to `DistributionSummary` would break dashboards and
     alerts, and Micrometer does not allow two meter types with the same name.
     So the new meters have new names and a new `MetricSet`.
     `ObservingOptions.DEFAULT` (BASIC only) is unchanged. Note:
     `ObservingOptions.allMetricSets()` now includes `BODY_SIZE`, so users of
     that helper get the new meters after upgrading. japicmp reports the enum
     change as compatible.
   * **Names.** `<prefix>.request.body.size` / `<prefix>.response.body.size`
     follow the module's `<prefix>.*` scheme. With the default prefix
     `http.client` they are exactly the OpenTelemetry semantic convention
     names `http.client.request.body.size` / `http.client.response.body.size`
     (Prometheus: `http_client_request_body_size_bytes`). The older
     Micrometer proposal `http.client.request.size` was not used because it
     does not say "body" and does not match OTel.
   * **Type.** `DistributionSummary` with base unit `bytes`, so users get
     count, total, max, and (via `MetricConfig.percentiles` or a `MeterFilter`)
     percentiles or histograms.
   * **Tags.** Same low-cardinality tags as the request timer: `method`,
     `status` (`599` if no response was received), and with
     `TagLevel.EXTENDED` also `protocol` and `target`. `MetricConfig.commonTags`
     and `ObservingOptions.tagCustomizer` apply. The `perUriIo` flag is not
     used, because it is documented for the IO counters and would add a
     high-cardinality `uri` tag.
   * **Source of the size.**
     * Classic: `HttpEntity#getContentLength()` of the request and response
       entities.
     * Async: `AsyncEntityProducer#getContentLength()` for the request,
       `EntityDetails#getContentLength()` for the response.
   * **No overhead on the data path.** Entities and data streams are never
     wrapped, counted or buffered. The interceptors read one `long` per message
     and record at most two values per exchange. `spanSampling` is honored.
     When neither size is known, no tags are built and nothing is recorded.
   * **Failures.** If no response is received (for example connection refused),
     the request size is recorded with `status=599`, consistent with the timer.
     HTTP error responses (4xx/5xx) are recorded with their status.
   
   ### Limitations
   
   * **Unknown length is not recorded.** Bodies sent or received with
     `Transfer-Encoding: chunked` (or any entity with `getContentLength() == 
-1`)
     are skipped. This also applies to responses that the client decompresses
     transparently: the decompressing wrappers report `-1`.
   * **Uncompressed body sizes, not wire bytes.** The value is the body size as
     the client sees it: before any `Content-Encoding` is applied to the
     request, and after transparent decompression of the response. It does not
     include headers or transfer framing, and it is not the number of bytes on
     the network. For wire-level traffic, other tools (for example connection
     level byte counts) are needed.
   * The value is the declared length. If a response is aborted mid-body, the
     declared length is still recorded.
   
   ### Possible follow-up (out of scope)
   
   Count bytes for chunked or unknown-length bodies by wrapping request and
   response entities (classic) and data producers/consumers (async). This adds
   per-chunk overhead and more complex lifecycle handling (partial reads,
   aborted streams, reuse of repeatable entities), so it should be a separate,
   explicitly opt-in feature.
   
   ### Tests
   
   * `BodySizeExecTest` (classic) and `AsyncBodySizeExecTest` (async):
     known length, chunked/unknown length, no entity (`GET` / `204`), `GET`
     with response body, error response (`500`), no response (connection
     refused → `status=599`), extended and common tags, `spanSampling`
     skip, and default options not installing the meters.
   * `./mvnw -pl httpclient5-observation verify` passes: tests, checkstyle,
     japicmp (against 5.6), Javadoc (`doclint all`) and apache-rat.
   
   ### Docs
   
   * Javadoc on `BodySizeExec`, `AsyncBodySizeExec`,
     `ObservingOptions.MetricSet.BODY_SIZE` and `HttpClientObservationSupport`
     explains what is and is not measured. All new public API has
     `@since 5.7`.
   * The module guide (`observation.md`) lives in 
`apache/httpcomponents-website`
     and has no 5.7.x version yet. A follow-up website PR is proposed below.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to