fix(telemetry): order the metrics pipeline by instrument kind

beast::insight instruments are created during ApplicationImp's member-init
list, and opentelemetry-cpp 1.28 never rebinds an already-vended Meter, so an
instrument created before the MeterProvider is published records nothing for
the rest of the process. Observable instruments carry the opposite constraint:
registering one arms the SDK reader thread, and its callbacks run hook handlers
that read services which do not exist that early.

Publish the provider in Telemetry's constructor, ahead of every producer, and
defer only the observables. Collector gains onCollectionReady() and
onCollectionStopping(); OTelCollector arms and disarms its gauges in response.
StatsDCollector starts its polling thread in its own constructor and had the
same hazard, so it uses the pair to gate that thread.

The metrics resource carries service.instance.id and is immutable once built,
so the node public key is resolved in Main.cpp, where a config error can still
be reported, and passed to makeApplication(). getNodeIdentity() remains
authoritative; both paths now share readNodeIdentity(), so telemetry cannot
report a key the node has abandoned.

An explicit ~ApplicationImp stops observing and stops telemetry, covering the
setup() failure paths that never reach run(). Telemetry::stop() is once-only
and no longer clears another instance's global pointer. The histogram view's
meter selector now matches the meter actually in use, so its bucket boundaries
apply for the first time.
This commit is contained in:
Pratik Mankawde
2026-08-20 16:36:41 +01:00
parent e6688d8a0b
commit 4278014ab0
12 changed files with 580 additions and 125 deletions

View File

@@ -65,9 +65,8 @@ trace_ledger=1
# endpoint and prefix are informational only. OTelCollector records on the
# global MeterProvider that [telemetry] configures, and formatName() does not
# apply the prefix, so metric names are bare and lowercase.
# Known limitation: the collector is built before the MeterProvider is
# registered, so beast::insight instruments bind to a no-op meter and are not
# exported yet. Tracing and the [telemetry] metrics pipeline are unaffected.
# Requires [telemetry] enabled=1: the MeterProvider these instruments record on
# is owned by the telemetry module, and without it they are discarded.
[insight]
server=otel
endpoint=http://localhost:4318/v1/metrics