Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
The `tag_cardinality_limit` transform gained two new configuration capabilities:

- **Per-tag overrides**: each entry in `per_metric_limits` now supports a `per_tag_limits`
map whose entries can override settings for a specific tag key on that metric. Each
per-tag field is optional:
- `value_limit`: caps distinct values for this tag key. Inherits from the enclosing
per-metric `value_limit` when unset.
- `mode`: cardinality tracking mode (`exact`, `probabilistic`, or `excluded`). Inherits
from the enclosing per-metric `mode` when unset.
- `cache_size_per_key`: bloom filter cache size in bytes. Only meaningful when the
effective `mode` is `probabilistic`. Inherits from the enclosing per-metric
`cache_size_per_key` when unset (when the per-metric mode is also probabilistic),
otherwise falls back to the default.

`limit_exceeded_action` and `internal_metrics` are not per-tag-overridable; the metric's
values are used. Per-metric configuration semantics are unchanged from prior versions:
per-metric entries remain self-contained, with each unset field using its existing serde
default.
- **Exclusion**: `mode: excluded` is now available as a third mode option in `per_metric_limits`
and `per_tag_limits` entries (not at the global level). When set, the metric or tag is opted
out of cardinality control — all tag values pass through and nothing is tracked. Other
tracking fields on the entry (`value_limit`) are ignored when `mode: excluded` is selected.
Per-metric exclusion is blanket: when a metric's `mode` is `excluded`, every tag on that
metric is excluded and any `per_tag_limits` overrides on it are ignored.

authors: ArunPiduguDD
137 changes: 134 additions & 3 deletions src/transforms/tag_cardinality_limit/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub enum TrackingScope {
PerMetric,
}

/// Configuration for the `tag_cardinality_limit` transform for a specific group of metrics.
/// Configuration block used at the global level.
#[configurable_component]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Inner {
Expand All @@ -99,7 +99,82 @@ pub struct Inner {
pub internal_metrics: InternalMetricsConfig,
}

/// Controls the approach taken for tracking tag cardinality.
/// Configuration block used at per-metric level. Same shape as the global configuration but
/// with `OverrideMode`, which adds `excluded` for opting that metric out of cardinality
/// control entirely.
#[configurable_component]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct OverrideInner {
/// How many distinct values to accept for any given key. Ignored when `mode: excluded`.
#[serde(default = "default_value_limit")]
pub value_limit: usize,

#[configurable(derived)]
#[serde(default = "default_limit_exceeded_action")]
pub limit_exceeded_action: LimitExceededAction,

#[serde(flatten)]
pub mode: OverrideMode,

#[configurable(derived)]
#[serde(default)]
pub internal_metrics: InternalMetricsConfig,
}

/// Configuration block used at the per-tag level. Same as `OverrideInner` minus
/// `limit_exceeded_action` (inherited from the enclosing per-metric config) and
/// `internal_metrics` (inherited from the enclosing per-metric or global config).
///
/// Unlike `OverrideInner`, this struct does not flatten a tagged `mode` enum;
/// `mode` and `cache_size_per_key` are exposed as independent optional fields so
/// that each can be omitted individually and inherit from the enclosing config.
#[configurable_component]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct PerTagInner {
Comment thread
ArunPiduguDD marked this conversation as resolved.
/// How many distinct values to accept for this tag key. If unset, inherits
/// the `value_limit` from the enclosing per-metric (or global) configuration.
/// Ignored when `mode: excluded`.
#[serde(default)]
pub value_limit: Option<usize>,

/// Cardinality tracking mode for this tag key. If unset, inherits the `mode`
/// from the enclosing per-metric (or global) configuration.
#[configurable(derived)]
#[serde(default)]
pub mode: Option<PerTagModeKind>,

/// The size of the cache for detecting duplicate tags, in bytes. Only used
/// when this tag's effective `mode` is `probabilistic`. If unset, inherits
/// from the enclosing per-metric `cache_size_per_key` (when probabilistic),
/// or falls back to the default.
#[serde(default)]
pub cache_size_per_key: Option<usize>,
}

/// Cardinality tracking mode at the per-tag override level. Same set of variants
/// as `OverrideMode`, but exposed as a plain (untagged) string enum so per-tag
/// entries can omit `mode` independently of other fields and inherit it from the
/// enclosing configuration.
#[configurable_component]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[serde(rename_all = "snake_case")]
#[configurable(metadata(
docs::enum_tag_description = "Controls the approach taken for tracking tag cardinality."
))]
pub enum PerTagModeKind {
/// Tracks cardinality exactly. See `Mode::Exact` for details.
Exact,

/// Tracks cardinality probabilistically. See `Mode::Probabilistic` for details.
Probabilistic,

/// Skip cardinality tracking for this tag. All tag values pass through and
/// nothing is recorded. The sibling `value_limit` and `cache_size_per_key`
/// fields are ignored when this is selected.
Excluded,
}

/// Controls the approach taken for tracking tag cardinality at the global level.
#[configurable_component]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[serde(tag = "mode", rename_all = "snake_case", deny_unknown_fields)]
Expand All @@ -122,6 +197,41 @@ pub enum Mode {
Probabilistic(BloomFilterConfig),
}

/// Controls the approach taken for tracking tag cardinality at the per-metric or per-tag level.
/// Adds `excluded` to the global `Mode` variants.
#[configurable_component]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[serde(tag = "mode", rename_all = "snake_case", deny_unknown_fields)]
#[configurable(metadata(
docs::enum_tag_description = "Controls the approach taken for tracking tag cardinality."
))]
pub enum OverrideMode {
/// Tracks cardinality exactly. See `Mode::Exact` for details.
Exact,

/// Tracks cardinality probabilistically. See `Mode::Probabilistic` for details.
Probabilistic(BloomFilterConfig),

/// Skip cardinality tracking for this scope. All tag values pass through and nothing is
/// recorded. Other tracking fields on the entry (`value_limit`, `limit_exceeded_action`,
/// `internal_metrics`) are ignored when this is selected.
///
/// Only valid in `per_metric_limits` and `per_tag_limits` entries; using it as the global
/// `mode` is a configuration error.
Excluded,
}

impl OverrideMode {
/// Returns the equivalent global `Mode` if this scope is tracked, or `None` if excluded.
pub const fn as_mode(&self) -> Option<Mode> {
match self {
OverrideMode::Exact => Some(Mode::Exact),
OverrideMode::Probabilistic(b) => Some(Mode::Probabilistic(*b)),
OverrideMode::Excluded => None,
}
}
}

/// Bloom filter configuration in probabilistic mode.
#[configurable_component]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -156,8 +266,29 @@ pub struct PerMetricConfig {
#[serde(default)]
pub namespace: Option<String>,

/// Per-tag-key overrides scoped to this metric.
///
/// Each entry may override `value_limit` and `mode` for a specific tag key.
/// `limit_exceeded_action` and `internal_metrics` are always inherited from the enclosing
/// per-metric (or global) configuration and cannot be set per-tag.
/// Tags not listed here use the per-metric configuration.
#[configurable(
derived,
metadata(docs::additional_props_description = "An individual tag configuration.")
)]
#[serde(default)]
pub per_tag_limits: HashMap<String, PerTagConfig>,

#[serde(flatten)]
pub config: OverrideInner,
}

/// Tag cardinality limit configuration for a specific tag key, scoped under a per-metric override.
#[configurable_component]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct PerTagConfig {
#[serde(flatten)]
pub config: Inner,
pub config: PerTagInner,
}

const fn default_limit_exceeded_action() -> LimitExceededAction {
Expand Down
Loading
Loading