feat: Explore E2E pipeline latency measurement via synthetic probes (approach 1)#3366
feat: Explore E2E pipeline latency measurement via synthetic probes (approach 1)#3366cijothomas wants to merge 4 commits into
Conversation
|
I like this approach, and I think it's a good first step. One small suggestion would be to call it backend-observed E2E latency (or simply backend E2E latency) to distinguish it from latency measured by the engine itself. One limitation is that the measured latency also includes network and backend ingestion time, which may or may not be desirable depending on the use case. This approach also depends on the probe following the same path as the telemetry of interest. For example, a pipeline that filters logs while exporting only metrics may prevent the probe from reaching the backend. Looking ahead, I wonder whether OTAP PData headers could provide a complementary mechanism for measuring true engine E2E latency. A sampled timestamp attached to the batch header at ingress could be propagated through the engine, with special handling in split, merge, and batching processors. This would avoid introducing synthetic telemetry while keeping the measurement focused on the engine itself. |
Context
Exploring how to measure end-to-end pipeline latency — the time from when a record enters the pipeline to when it is received by the backend.
This PR explores a lightweight approach that does not require any changes to the df-engine itself. The trade-off is that it requires backend cooperation — the backend must recognize probe records and compute the latency. An engine-native approach (where the engine itself tracks and reports latency) would be more self-contained but is likely more complex and expensive to implement correctly. Both directions are worth exploring; this PR starts with the simpler one to validate the concept.
Approach: Synthetic probe traffic + backend-side latency computation
A synthetic log record is periodically injected into the pipeline with
body = "_OTAP_PROBE"and an_otap_internal.probe.emitted_at_unix_nanosattribute carrying the wall-clock timestamp at emission.Probes flow through the entire real pipeline path as ordinary data — same processors, same exporter batching, same wire format. No special handling anywhere in the engine.
The backend detects probes (check if
body == "_OTAP_PROBE"), computesnow() - emitted_at, emits a latency metric, and drops the record.Probe generation options
The probe traffic can be generated by:
probe_emitterreceiver (included in this PR) — a minimal in-engine receiver that emits one probe log per configurable interval.traffic_generatorreceiver — the existing traffic generator could serve this purpose once it gains the ability to stamp an origin timestamp on generated telemetry.Backend convention
Any backend that follows the
_OTAP_PROBEconvention can participate:body == "_OTAP_PROBE"(O(1) string check; short-circuit on first byte_)_otap_internal.probe.emitted_at_unix_nanos, computenow() - emitted_at, emit a latency metricWhy backend-side?
Any measurement taken inside the engine structurally cannot include exporter time (batching, serialization, compression, network, ack) — which is typically the dominant contributor to E2E latency. The backend is the only observer that sees the full path.
Demo
The POC uses the Azure Monitor exporter + mock LA server as an example backend, but the same convention would work with any backend that implements the
_OTAP_PROBEdetection.To try locally
Output from the mock backend:
In steady state, probe latency reflects the exporter's batch flush interval. With the default 3s flush, probes show ~450ms–2450ms depending on position in the batch. With a 1s flush, all probes converge to ~450ms. This confirms the measurement captures real pipeline behavior.
What's included
crates/core-nodes/src/receivers/probe_emitter_receiver/crates/core-nodes/src/processors/probe_sink_processor/e2e-latency-probe-poc.yamlcrates/contrib-nodes/examples/mock_la_server.rsTrade-offs
Pros:
Cons:
_OTAP_PROBEconvention