Skip to main content

aggregate

Attribute Macro aggregate 

Source
#[aggregate]
Expand description

Generates aggregation support for metrics structs.

This macro enables combining multiple observations of the same metric into a single aggregated entry. It must be placed before #[metrics] and generates:

  • An Aggregated{StructName} struct with aggregated field types
  • An AggregateEntry trait implementation for merging observations

For renaming fields and adding unit, #[aggregate] relies on the #[metrics] macro.

§Container Attributes

AttributeTypeDescriptionExample
directFlagAggregates on the struct itself instead of the closed entry (default: aggregates on closed entry)#[aggregate(direct)]

§Field Attributes

AttributeTypeDescriptionExample
strategyPathSpecifies the aggregation strategy (required for non-key fields)#[aggregate(strategy = Histogram<Duration>)]
keyFlagMarks a field as part of the aggregation key - observations with different keys are aggregated separately#[aggregate(key)]
ignoreFlagIgnore a field during aggregation. The field will still be part of the non-aggregated metric entry unless also marked #[metrics(ignore)]

§Aggregation Modes

§Entry Mode (Default)

By default, #[aggregate] implements aggregation on the closed metric entry. This means aggregation happens after CloseValue has been applied to all fields:

use metrique::unit_of_work::metrics;
use metrique_aggregation::{aggregate, histogram::Histogram, value::Sum};
use std::time::Duration;

#[aggregate]
#[metrics]
struct ApiCall {
    #[aggregate(strategy = Histogram<Duration>)]
    #[metrics(unit = metrique::writer::unit::Millisecond)]
    latency: Duration,  // Aggregates Duration values

    #[aggregate(strategy = Sum)]
    response_size: usize,
}

§Direct Mode

Use #[aggregate(direct)] to aggregate on the struct iteslf. In direct mode:

  • Aggregation strategies receive the raw field type before CloseValue is applied
  • Use this if the base struct is not also a metric

§Aggregation Keys

Fields marked with #[aggregate(key)] define the aggregation key. Observations with different keys are aggregated into separate entries:

use metrique::unit_of_work::metrics;
use metrique_aggregation::{aggregate, histogram::Histogram};
use std::time::Duration;

#[aggregate]
#[metrics]
struct ApiCall {
    #[aggregate(key)]
    endpoint: String,  // Separate aggregation per endpoint

    #[aggregate(strategy = Histogram<Duration>)]
    latency: Duration,
}

Key behavior:

  • Key fields are cloned into the aggregated struct unchanged
  • Multiple key fields create a tuple key: (Field1, Field2, ...)
  • Without key fields, all observations aggregate into a single entry
  • Key fields must implement Clone

§Aggregation Strategies

Each non-key field must specify an aggregation strategy that implements AggregateValue<T>:

§Built-in Strategies

  • Sum - Sums numeric values together
  • Histogram<T> - Collects values into a distribution. Histogram has a second generic that can control how values are stored. See the Histogram docs for more info.
  • KeepLast - Keeps the most recent value
use metrique::unit_of_work::metrics;
use metrique_aggregation::{aggregate, histogram::Histogram, value::Sum};
use std::time::Duration;

#[aggregate]
#[metrics]
struct ApiCall {
    #[aggregate(strategy = Histogram<Duration>)]
    latency: Duration,

    #[aggregate(strategy = Sum)]
    bytes_sent: usize,
}

§Generated Types

For a struct with #[aggregate], the macro generates:

  • AggregatedMyMetrics: The aggregated struct where each field is replaced with its aggregated type
  • impl AggregateEntry for MyMetrics: Trait implementation for merging observations

For more details on the aggregation trait system, see the traits module documentation.

The aggregated struct can be used with Aggregate<T> or MutexSink<T>:

use metrique::unit_of_work::metrics;
use metrique_aggregation::{aggregate, histogram::Histogram, aggregator::Aggregate};
use std::time::Duration;

#[aggregate]
#[metrics]
struct ApiCall {
    #[aggregate(strategy = Histogram<Duration>)]
    latency: Duration,
}

#[metrics]
struct RequestMetrics {
    request_id: String,
    #[metrics(flatten)]
    api_calls: Aggregate<ApiCall>,
}

For more examples, see the examples directory in metrique-aggregation