mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-21 14:20:56 +00:00
beast::insight::Event documents itself as carrying "a millisecond time, or
other integral value", but both backends assumed the first case: the OTel
bridge declared every instrument with unit `ms` and StatsD tagged every
sample `|ms`. One Event does not measure time -- ServerHandler's "size"
records the serialized RPC response length -- so it exported as
rpc_size_milliseconds and inherited the millisecond bucket ladder. A quarter
of its samples landed above that ladder's top edge, and since Prometheus
returns the second-highest edge for a quantile in the `+Inf` bucket, its p95
panel showed a flat 5.00 kB rather than a measurement.
Adds beast::insight::Unit (Millis, Bytes) plus otelUnitCode(), carried on
EventImpl and selectable at makeEvent(). Naming the unit at creation is what
lets a backend pick the export unit and, through it, the bucket ladder.
- Collector gains a virtual makeEvent(name, Unit) whose default delegates to
the millisecond overload, so a collector that cannot act on a unit keeps
working unchanged. NullCollector and the Groups wrapper override it.
- The Groups override matters most: call sites reach a collector through a
Group, so forwarding only the prefixed name would silently drop the unit.
A test covers that hop specifically.
- Event gains notify(std::uint64_t) for non-duration samples, replacing
ServerHandler's `Event::value_type{response.size()}` -- wrapping a byte
count in a std::chrono::milliseconds compiles but reads as a duration to
everything downstream.
- EventImpl::value_type stays std::chrono::milliseconds. Widening it would
change the wire value of every existing StatsD timer, and metrics needing
finer resolution use the OTel-native microsecond instruments.
The StatsD collector deliberately keeps emitting `|ms`: that path is retired
here (its UDP port is commented out of the compose file and the integration
test fails if anything listens on 8125), so changing its wire format would
alter a legacy contract with no consumer and no way to verify it.
The exported name does not change yet -- OTelEventImpl still hardcodes its
unit. That follows with the unit-keyed histogram views.
60 lines
1.6 KiB
C++
60 lines
1.6 KiB
C++
#pragma once
|
|
|
|
#include <xrpl/beast/insight/Unit.h>
|
|
|
|
#include <chrono>
|
|
#include <memory>
|
|
|
|
namespace beast::insight {
|
|
|
|
class Event;
|
|
|
|
class EventImpl : public std::enable_shared_from_this<EventImpl>
|
|
{
|
|
public:
|
|
/**
|
|
* The integral type every sample is stored as.
|
|
*
|
|
* Named for the common case -- durations -- and deliberately left as a
|
|
* duration type. Widening it would change the wire value of every
|
|
* existing StatsD timer, and metrics that need finer resolution than a
|
|
* whole millisecond use the OTel-native microsecond instruments instead.
|
|
* A sample whose unit() is not a duration is carried in the same integral
|
|
* field and interpreted per unit() by the backend.
|
|
*/
|
|
using value_type = std::chrono::milliseconds;
|
|
|
|
virtual ~EventImpl() = 0;
|
|
virtual void
|
|
notify(value_type const& value) = 0;
|
|
|
|
/**
|
|
* @brief What this Event's samples measure. Fixed at construction.
|
|
*
|
|
* The OTel backend reads this to choose the instrument's declared unit
|
|
* and, through that, its bucket ladder. The StatsD backend ignores it.
|
|
*/
|
|
[[nodiscard]] Unit
|
|
unit() const noexcept
|
|
{
|
|
return unit_;
|
|
}
|
|
|
|
protected:
|
|
/**
|
|
* @param unit What the samples measure. Defaults to milliseconds so
|
|
* existing implementations keep their behaviour unchanged.
|
|
*/
|
|
explicit EventImpl(Unit unit = Unit::Millis) : unit_(unit)
|
|
{
|
|
}
|
|
|
|
private:
|
|
/**
|
|
* What the samples measure; selects the export unit and bucket ladder.
|
|
*/
|
|
Unit unit_;
|
|
};
|
|
|
|
} // namespace beast::insight
|