Native Observability 1.0.10
Eleven commits on top of 1.0.9. The headline themes: outbound HTTP
tracing reworked as a Guzzle middleware on the shared
http_handler_stack (so consumers that depend on the concrete
GuzzleHttp\Client keep working), a buffered-span race that left
duration_ms = NULL is closed, four CI repairs land on top of the
refactor, the documentation is brought back in sync with the new
instrumentation shape — including a worked guide on how to trace
third-party HTTP integrations such as Typesense and Facets — and the
static-analysis baseline is tightened from phpstan level 1 to
level 2 with strict docblock types.
Added
- GuzzleSpanMiddleware (native_observability_spans) — outbound HTTP
spans recorded by a middleware on the shared http_handler_stack
instead of by a decorator on http_client. Per-call categorisation
is opt-in via GuzzleSpanMiddleware::OPTION (subtype + name).
- GuzzleTraceMiddleware (native_observability_execution) reworked
along the same lines for execution-side outbound tracing.
- drush no:token:* commands (TokenCommands) — generate, store and
revoke the bearer token used by the export endpoints
(/native-observability/prometheus, /native-observability/elastic).
- RouteMetricsAggregator::aggregateAndPersistWindow($start, $end) —
explicit wrapper companion to aggregateLatestCompletedWindow() and
aggregateRollingWindow(), used to back-fill past 5-minute buckets.
Changed
- http_client is no longer wrapped by decorators.
\Drupal::httpClient() returns a real GuzzleHttp\Client again, so
consumers that type-hint the concrete class (most notably
search_api_typesense) keep working without patches.
- ServiceIntegrityInspector extended to recognise the two new
middlewares (http_client.spans, http_client.execution) as
integration points.
- OpenTelemetryExporter and LivePrometheusMetricsReader updated to
consume the new middleware-side span payload shape.
Removed
- HttpClientSpanDecorator — superseded by GuzzleSpanMiddleware.
- InstrumentedHttpClientDecorator — superseded by
GuzzleTraceMiddleware.
Fixed
- Buffered spans now close in place inside the deferred-persistence
buffer (DatabaseSpanStorage + DeferredPersistenceBuffer::applyPatch),
fixing a race that left duration_ms = NULL on bursts of outbound
requests within the same kernel cycle.
- drush no:k6:report no longer crashes with "Call to undefined method
RouteMetricsAggregator::aggregateAndPersistWindow()" — the orphan
call from K6ReportCommands::refreshAggregationForRun() is restored
by the new wrapper.
- GuzzleSpanMiddlewareTest no longer uses the deprecated
Assert::isType() (PHPUnit 11) — the two with(...) expectations
switch to IsType::TYPE_ARRAY, unblocking the phpstan job.
- CI: phpunit test signatures, the obsolete unused-variable phpcs
rule and a phpcs array-indentation pass in inline markup builders
all repaired.
QA
- phpstan bumped from level 1 to level 2 with
treatPhpDocTypesAsCertain: true. Closes the two gaps that let the
aggregateAndPersistWindow() regression through in the first place
(callers of methods that exist only on a docblock-typed property,
and undefined-method calls revealed only after a rename); src/ is
clean at the new level.
- Two narrowly scoped ignoreErrors entries (Prophecy ObjectProphecy
intercepted methods, PHPUnit createMock()->method('x') builder API)
added with path: '*/tests/*' so src/ stays fully strict while the
dynamic-dispatch blind spots of the test frameworks are accepted.
Docs
- _spans and _execution README files re-synced with the
handler-stack middleware refactor (no more references to
HttpClientSpanDecorator / "decorates http_client").
- New "Tracing third-party HTTP integrations" section with three
integration patterns (constructor injection / local variable /
facade), a Typesense + Facets worked example, and two caveats:
search_api_typesense issues read queries from the browser via
InstantSearch (no PHP path to instrument server-side), and
drush php-script does not dispatch kernel.terminate (ad-hoc
scripts must flush the span buffer explicitly).