Skip to content

feat(aggregate): support configurable sub-10s aggregation windows#1459

Draft
lukesteensen wants to merge 1 commit into
mainfrom
luke/configurable-aggregation
Draft

feat(aggregate): support configurable sub-10s aggregation windows#1459
lukesteensen wants to merge 1 commit into
mainfrom
luke/configurable-aggregation

Conversation

@lukesteensen
Copy link
Copy Markdown
Contributor

Summary

  • Introduces aggregator_bucket_size_seconds as a serde alias for the existing aggregate_window_duration, enabling sub-10s aggregation windows (e.g. 1 Hz) for the aggregated pipeline without changing default behavior.
  • Pins the pass-through (pre-aggregated) batcher to the default bucket size regardless of the new knob. The wire protocol for pass-through metrics carries no client-supplied interval, so letting the knob leak there would silently reinterpret every rate sample from every client on that path.
  • Accepts the config value as either an integer number of seconds (new, matches the _seconds suffix) or the legacy serde Duration struct form (preserves existing configs).

Implementation notes

  • DEFAULT_BUCKET_SIZE = 10s is now the single named constant referenced everywhere the legacy value is still required.
  • AggregateConfiguration::build_passthrough_batcher is the lone construction site for the pass-through batcher and encodes the pinning invariant. A comment explains why (protocol convention, not an internal knob).
  • Custom deserialize_with on window_duration accepts either u64 seconds or the struct form — no new field, no resolver.

Test plan

  • aggregated_counters_at_1s_bucket_width — aggregated pipeline at 1 Hz emits one series with points at the expected bucket starts, interval = 1s, and retains the open-bucket value across a subsequent flush.
  • passthrough_pinned_to_default_despite_1hz_configwindow_duration = 1s does not change the pass-through batcher's emitted rate interval.
  • aliased_bucket_size_config_key_deserializes_as_integer_seconds — new key accepts {"aggregator_bucket_size_seconds": 1}.
  • legacy_window_duration_struct_form_still_deserializes — existing {"aggregate_window_duration": {"secs": 7, "nanos": 0}} configs still work.
  • Existing aggregate tests all pass.

Introduces `aggregator_bucket_size_seconds` as an alias for the existing
`aggregate_window_duration` field, enabling sub-10s aggregation windows
(e.g. 1 Hz) for the aggregated pipeline.

- Adds a `DEFAULT_BUCKET_SIZE` constant and routes both code and tests
  through it to eliminate literal `10`s in aggregation code.
- Pins the pass-through batcher to `DEFAULT_BUCKET_SIZE` via a dedicated
  `build_passthrough_batcher` helper. The pass-through wire protocol
  carries no client-supplied interval, so changing it with the new knob
  would silently reinterpret every rate sample from every client using
  that path.
- Adds a flexible deserializer so the config value can be supplied as
  either an integer number of seconds or the legacy serde `Duration`
  struct form -- preserving pre-existing configs while letting the
  `_seconds`-suffixed alias behave the way its name implies.
- Adds regression tests covering: end-to-end aggregation at 1 Hz with
  retention of open-bucket values across flushes, pass-through pinning
  despite a 1 Hz config, both deserialization forms of the new key, and
  the legacy struct form of the existing key.
@dd-octo-sts dd-octo-sts Bot added area/components Sources, transforms, and destinations. transform/aggregate Aggregate transform. labels Apr 23, 2026
@pr-commenter
Copy link
Copy Markdown

pr-commenter Bot commented Apr 23, 2026

Binary Size Analysis (Agent Data Plane)

Target: dc8f4b9 (baseline) vs 06f3965 (comparison) diff
Analysis Type: Stripped binaries (debug symbols excluded)
Baseline Size: 37.11 MiB
Comparison Size: 37.00 MiB
Size Change: -111.50 KiB (-0.29%)
Pass/Fail Threshold: +5%
Result: PASSED ✅

Changes by Module

Module File Size Symbols
figment -118.82 KiB 125
otlp_protos::otlp_include::opentelemetry -41.79 KiB 103
hyper +25.69 KiB 76
prost +24.60 KiB 66
hyper_util -14.05 KiB 13
hashbrown +11.34 KiB 72
h2 -8.86 KiB 92
[sections] -8.52 KiB 6
tonic -7.37 KiB 33
core -7.09 KiB 878
serde_core +6.51 KiB 85
serde +6.39 KiB 18
tower +5.15 KiB 11
async_compression +4.62 KiB 19
tokio_util +3.94 KiB 14
alloc +3.76 KiB 50
saluki_components::sources::otlp +3.75 KiB 17
tokio +3.67 KiB 124
saluki_core::data_model::event -3.40 KiB 8
futures_channel -3.35 KiB 7

Detailed Symbol Changes

    FILE SIZE        VM SIZE    
 --------------  -------------- 
  [NEW] +18.5Ki  [NEW] +18.3Ki    saluki_components::transforms::apm_stats::span_concentrator::SpanConcentrator::flush::h4cec187aab531472
  [NEW] +16.5Ki  [NEW] +16.4Ki    saluki_components::transforms::apm_stats::span_concentrator::SpanConcentrator::add_span::hf95b8e429cc5bbe0
  [NEW] +16.1Ki  [NEW] +16.0Ki    saluki_components::transforms::apm_stats::span_concentrator::SpanConcentrator::new_stat_span_from_span::h831751497d326aef
  +283% +15.9Ki  +288% +15.9Ki    h2::proto::connection::DynConnection<B>::recv_frame::h9d7adeb5727e1522
  [NEW] +12.3Ki  [NEW] +12.1Ki    _<core::marker::PhantomData<T> as serde_core::de::DeserializeSeed>::deserialize::hf9a832fc7767a946
  [NEW] +9.39Ki  [NEW] +9.23Ki    _<hyper::proto::h2::server::Server<T,S,B,E> as core::future::future::Future>::poll::h7fad89436d42473e
  +750% +6.74Ki  +828% +6.74Ki    prost::encoding::message::merge_repeated::hc52fda914c63fb75
  [NEW] +6.50Ki  [NEW] +6.28Ki    saluki_components::common::datadog::apm::_::_<impl serde_core::de::Deserialize for saluki_components::common::datadog::apm::ApmConfiguration>::deserialize::h2b55df90d15c8dc3
  +739% +6.39Ki  +819% +6.39Ki    prost::encoding::message::merge_repeated::h125609fe5afef278
  [DEL] -6.56Ki  [DEL] -6.41Ki    _<core::marker::PhantomData<T> as serde_core::de::DeserializeSeed>::deserialize::h14607bccbe25f0f5
 -24.0% -8.01Ki -24.1% -7.98Ki    _<saluki_components::transforms::apm_stats::ApmStats as saluki_core::components::transforms::Transform>::run::_{{closure}}::h63fe22416badd464
  [DEL] -8.13Ki  [DEL] -8.00Ki    figment::value::de::_<impl figment::value::value::Value>::deserialize_from::hc178e2144edf2db7
 -67.1% -9.24Ki -67.7% -9.24Ki    saluki_components::transforms::trace_obfuscation::sql::obfuscate_sql_string::hbc6c7c370aac7ff9
  [DEL] -9.49Ki  [DEL] -9.34Ki    _<figment::value::magic::Tagged<T> as figment::value::magic::Magic>::deserialize_from::h44f59c3078bb5bee
  [DEL] -9.74Ki  [DEL] -9.59Ki    _<figment::value::magic::RelativePathBuf as figment::value::magic::Magic>::deserialize_from::h795d206f112d7dfd
 -81.7% -10.1Ki -82.6% -10.1Ki    _<core::pin::Pin<P> as core::future::future::Future>::poll::h901e76ef802f2f4c
  [DEL] -11.6Ki  [DEL] -11.5Ki    _<figment::value::de::ConfiguredValueDe<I> as serde_core::de::Deserializer>::deserialize_struct::h262edabf8ad9b351
  [DEL] -15.4Ki  [DEL] -15.3Ki    _<figment::value::magic::Tagged<T> as figment::value::magic::Magic>::deserialize_from::hf4491bd4db3bec82
  [DEL] -15.9Ki  [DEL] -15.7Ki    _<figment::value::magic::RelativePathBuf as figment::value::magic::Magic>::deserialize_from::hf41c2cc956726b9d
  [DEL] -32.1Ki  [DEL] -32.0Ki    saluki_components::transforms::apm_stats::ApmStats::process_trace::h7d2f794f20a992a4
  -1.4% -83.5Ki  -1.4% -69.0Ki    [4675 Others]
  -0.3%  -111Ki  -0.3% -96.7Ki    TOTAL

@pr-commenter
Copy link
Copy Markdown

pr-commenter Bot commented Apr 23, 2026

Regression Detector (Agent Data Plane)

Regression Detector Results

Run ID: 26ebc309-0848-41cc-bae6-362bc763ec27

Baseline: dc8f4b9
Comparison: 06f3965
Diff

Optimization Goals: ✅ No significant changes detected

Experiments ignored for regressions

Regressions in experiments with settings containing erratic: true are ignored.

perf experiment goal Δ mean % Δ mean % CI trials links
otlp_ingest_logs_5mb_throughput ingress throughput +0.02 [-0.10, +0.14] 1 (metrics) (profiles) (logs)
otlp_ingest_logs_5mb_cpu % cpu utilization -2.15 [-6.95, +2.65] 1 (metrics) (profiles) (logs)
otlp_ingest_logs_5mb_memory memory utilization -10.69 [-11.06, -10.32] 1 (metrics) (profiles) (logs)

Fine details of change detection per experiment

perf experiment goal Δ mean % Δ mean % CI trials links
dsd_uds_10mb_3k_contexts_cpu % cpu utilization +6.51 [-25.35, +38.36] 1 (metrics) (profiles) (logs)
otlp_ingest_traces_ottl_filtering_5mb_cpu % cpu utilization +1.49 [-0.91, +3.88] 1 (metrics) (profiles) (logs)
dsd_uds_500mb_3k_contexts_memory memory utilization +0.50 [+0.35, +0.65] 1 (metrics) (profiles) (logs)
dsd_uds_512kb_3k_contexts_memory memory utilization +0.41 [+0.26, +0.56] 1 (metrics) (profiles) (logs)
dsd_uds_100mb_3k_contexts_memory memory utilization +0.30 [+0.14, +0.45] 1 (metrics) (profiles) (logs)
quality_gates_rss_dsd_medium memory utilization +0.14 [-0.03, +0.31] 1 (metrics) (profiles) (logs)
otlp_ingest_traces_5mb_throughput ingress throughput +0.13 [+0.06, +0.20] 1 (metrics) (profiles) (logs)
otlp_ingest_traces_5mb_memory memory utilization +0.07 [-0.09, +0.24] 1 (metrics) (profiles) (logs)
dsd_uds_1mb_3k_contexts_memory memory utilization +0.04 [-0.11, +0.18] 1 (metrics) (profiles) (logs)
otlp_ingest_metrics_5mb_throughput ingress throughput +0.02 [-0.13, +0.17] 1 (metrics) (profiles) (logs)
otlp_ingest_logs_5mb_throughput ingress throughput +0.02 [-0.10, +0.14] 1 (metrics) (profiles) (logs)
dsd_uds_100mb_3k_contexts_throughput ingress throughput +0.01 [-0.02, +0.03] 1 (metrics) (profiles) (logs)
dsd_uds_1mb_3k_contexts_throughput ingress throughput +0.00 [-0.05, +0.06] 1 (metrics) (profiles) (logs)
dsd_uds_512kb_3k_contexts_throughput ingress throughput +0.00 [-0.05, +0.05] 1 (metrics) (profiles) (logs)
dsd_uds_10mb_3k_contexts_throughput ingress throughput -0.00 [-0.16, +0.16] 1 (metrics) (profiles) (logs)
otlp_ingest_traces_ottl_transform_5mb_memory memory utilization -0.02 [-0.18, +0.15] 1 (metrics) (profiles) (logs)
otlp_ingest_traces_ottl_filtering_5mb_memory memory utilization -0.03 [-0.28, +0.22] 1 (metrics) (profiles) (logs)
quality_gates_rss_dsd_low memory utilization -0.05 [-0.21, +0.11] 1 (metrics) (profiles) (logs)
quality_gates_rss_dsd_heavy memory utilization -0.07 [-0.20, +0.07] 1 (metrics) (profiles) (logs)
dsd_uds_500mb_3k_contexts_throughput ingress throughput -0.07 [-0.22, +0.07] 1 (metrics) (profiles) (logs)
dsd_uds_10mb_3k_contexts_memory memory utilization -0.10 [-0.26, +0.05] 1 (metrics) (profiles) (logs)
otlp_ingest_traces_ottl_transform_5mb_throughput ingress throughput -0.13 [-0.20, -0.05] 1 (metrics) (profiles) (logs)
quality_gates_rss_idle memory utilization -0.21 [-0.25, -0.17] 1 (metrics) (profiles) (logs)
quality_gates_rss_dsd_ultraheavy memory utilization -0.23 [-0.35, -0.10] 1 (metrics) (profiles) (logs)
otlp_ingest_traces_ottl_filtering_5mb_throughput ingress throughput -0.23 [-0.30, -0.15] 1 (metrics) (profiles) (logs)
dsd_uds_100mb_3k_contexts_cpu % cpu utilization -0.80 [-6.76, +5.15] 1 (metrics) (profiles) (logs)
dsd_uds_500mb_3k_contexts_cpu % cpu utilization -1.07 [-2.56, +0.42] 1 (metrics) (profiles) (logs)
otlp_ingest_traces_5mb_cpu % cpu utilization -1.23 [-3.43, +0.97] 1 (metrics) (profiles) (logs)
otlp_ingest_metrics_5mb_cpu % cpu utilization -1.45 [-8.59, +5.69] 1 (metrics) (profiles) (logs)
otlp_ingest_traces_ottl_transform_5mb_cpu % cpu utilization -1.50 [-3.49, +0.48] 1 (metrics) (profiles) (logs)
otlp_ingest_logs_5mb_cpu % cpu utilization -2.15 [-6.95, +2.65] 1 (metrics) (profiles) (logs)
otlp_ingest_metrics_5mb_memory memory utilization -2.49 [-2.70, -2.28] 1 (metrics) (profiles) (logs)
dsd_uds_1mb_3k_contexts_cpu % cpu utilization -2.65 [-54.86, +49.56] 1 (metrics) (profiles) (logs)
dsd_uds_512kb_3k_contexts_cpu % cpu utilization -4.84 [-61.84, +52.17] 1 (metrics) (profiles) (logs)
otlp_ingest_logs_5mb_memory memory utilization -10.69 [-11.06, -10.32] 1 (metrics) (profiles) (logs)

Bounds Checks: ✅ Passed

perf experiment bounds_check_name replicates_passed observed_value links
quality_gates_rss_dsd_heavy memory_usage 10/10 119.79MiB ≤ 140MiB (metrics) (profiles) (logs)
quality_gates_rss_dsd_low memory_usage 10/10 39.70MiB ≤ 50MiB (metrics) (profiles) (logs)
quality_gates_rss_dsd_medium memory_usage 10/10 60.33MiB ≤ 75MiB (metrics) (profiles) (logs)
quality_gates_rss_dsd_ultraheavy memory_usage 10/10 177.33MiB ≤ 200MiB (metrics) (profiles) (logs)
quality_gates_rss_idle memory_usage 10/10 26.91MiB ≤ 40MiB (metrics) (profiles) (logs)

Explanation

Confidence level: 90.00%
Effect size tolerance: |Δ mean %| ≥ 5.00%

Performance changes are noted in the perf column of each table:

  • ✅ = significantly better comparison variant performance
  • ❌ = significantly worse comparison variant performance
  • ➖ = no significant change in performance

A regression test is an A/B test of target performance in a repeatable rig, where "performance" is measured as "comparison variant minus baseline variant" for an optimization goal (e.g., ingress throughput). Due to intrinsic variability in measuring that goal, we can only estimate its mean value for each experiment; we report uncertainty in that value as a 90.00% confidence interval denoted "Δ mean % CI".

For each experiment, we decide whether a change in performance is a "regression" -- a change worth investigating further -- if all of the following criteria are true:

  1. Its estimated |Δ mean %| ≥ 5.00%, indicating the change is big enough to merit a closer look.

  2. Its 90.00% confidence interval "Δ mean % CI" does not contain zero, indicating that if our statistical model is accurate, there is at least a 90.00% chance there is a difference in performance between baseline and comparison variants.

  3. Its configuration does not mark it "erratic".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/components Sources, transforms, and destinations. transform/aggregate Aggregate transform.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant