Skip to content

Commit f92621d

Browse files
committed
feat(dogstatsd): allowlist tag values by metric prefix
1 parent 92e9dc0 commit f92621d

13 files changed

Lines changed: 944 additions & 347 deletions

File tree

bin/agent-data-plane/src/cli/run.rs

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -737,11 +737,7 @@ fn build_dogstatsd_context_dump_api_handler(
737737
}
738738

739739
async fn add_dsd_pipeline_to_blueprint(
740-
blueprint: &mut TopologyBlueprint,
741-
config: &GenericConfiguration,
742-
// Threaded in ready for the typed-config component cutover (aggregate/debug-log); unused until
743-
// those components read from it, hence the leading underscore.
744-
_config_system: &ConfigurationSystem,
740+
blueprint: &mut TopologyBlueprint, config: &GenericConfiguration, config_system: &ConfigurationSystem,
745741
env_provider: &ADPEnvironmentProvider,
746742
) -> Result<DogStatsDControlSurface, GenericError> {
747743
// We're creating the "front half" of the DogStatsD pipeline, which deals solely with accepting DogStatsD payloads,
@@ -793,7 +789,8 @@ async fn add_dsd_pipeline_to_blueprint(
793789
let dsd_mapper_config = DogStatsDMapperConfiguration::from_configuration(config)?;
794790
let dsd_enrich_config =
795791
ChainedConfiguration::default().with_transform_builder("dogstatsd_mapper", dsd_mapper_config);
796-
let dsd_tag_filterlist_config = TagFilterlistConfiguration::from_configuration(config)
792+
let dogstatsd_config = config_system.live(|config| &config.domains.dogstatsd);
793+
let dsd_tag_filterlist_config = TagFilterlistConfiguration::from_configuration(dogstatsd_config)
797794
.error_context("Failed to configure metric tag filterlist transform.")?;
798795
let dsd_agg_config =
799796
AggregateConfiguration::from_configuration(config).error_context("Failed to configure aggregate transform.")?;
@@ -962,6 +959,13 @@ fn write_sizing_guide(bounds: ComponentBounds) -> Result<(), GenericError> {
962959
mod tests {
963960
use std::{path::Path, sync::Mutex, time::Duration};
964961

962+
use agent_data_plane_config::{
963+
domains::dogstatsd::{
964+
Domain as DogStatsDDomain, FilterAction, MetricTagFilterEntry, MetricTagValueAllowlistEntry,
965+
TagValueMismatchAction,
966+
},
967+
Live,
968+
};
965969
use async_trait::async_trait;
966970
use http::{Request, StatusCode};
967971
use http_body_util::{BodyExt as _, Empty};
@@ -1019,11 +1023,6 @@ mod tests {
10191023
"statsd_metric_namespace_blocklist": [],
10201024
"metric_filterlist": ["tenant.raw.blocked"],
10211025
"metric_filterlist_match_prefix": false,
1022-
"metric_tag_filterlist": [{
1023-
"metric_name": "tenant.mapped.requests",
1024-
"action": "exclude",
1025-
"tags": ["remove"]
1026-
}],
10271026
"aggregate_flush_interval": { "secs": 60, "nanos": 0 }
10281027
}))
10291028
.await;
@@ -1033,8 +1032,23 @@ mod tests {
10331032
let mapper_chain = ChainedConfiguration::default().with_transform_builder("dogstatsd_mapper", mapper);
10341033
let prefix_filter = DogStatsDPrefixFilterConfiguration::from_configuration(&config)
10351034
.expect("prefix filter configuration should parse");
1036-
let tag_filter =
1037-
TagFilterlistConfiguration::from_configuration(&config).expect("tag filter configuration should parse");
1035+
let dogstatsd_config = DogStatsDDomain {
1036+
tag_filterlist: vec![MetricTagFilterEntry {
1037+
metric_name: "tenant.mapped.requests".to_string(),
1038+
action: FilterAction::Exclude,
1039+
tags: vec!["remove".to_string()],
1040+
}],
1041+
tag_value_allowlist: vec![MetricTagValueAllowlistEntry {
1042+
metric_prefix: "tenant.mapped.".to_string(),
1043+
tag_name: "customer_id".to_string(),
1044+
values: vec!["top-1".to_string()],
1045+
on_miss: TagValueMismatchAction::Remove,
1046+
replacement: "other".to_string(),
1047+
}],
1048+
..Default::default()
1049+
};
1050+
let tag_filter = TagFilterlistConfiguration::from_configuration(Live::new_fixed(dogstatsd_config))
1051+
.expect("tag filter configuration should be valid");
10381052
let aggregate =
10391053
AggregateConfiguration::from_configuration(&config).expect("aggregate configuration should parse");
10401054
let snapshot_handle = aggregate.context_snapshot_handle();
@@ -1084,14 +1098,24 @@ mod tests {
10841098
.send(Event::Metric(Metric::counter("raw.blocked", 1.0)))
10851099
.await
10861100
.expect("controlled source should accept the blocked metric");
1087-
let input_context = Context::from_static_parts("raw.requests.checkout", &["keep:client", "remove:secret"]);
1101+
let input_context = Context::from_static_parts(
1102+
"raw.requests.checkout",
1103+
&[
1104+
"customer_id:top-1",
1105+
"customer_id:long-tail",
1106+
"keep:client",
1107+
"remove:secret",
1108+
],
1109+
);
10881110
events_tx
10891111
.send(Event::Metric(Metric::counter(input_context.clone(), 1.0)))
10901112
.await
10911113
.expect("controlled source should accept the retained metric");
10921114

1093-
let expected_context =
1094-
Context::from_static_parts("tenant.mapped.requests", &["keep:client", "route:checkout"]);
1115+
let expected_context = Context::from_static_parts(
1116+
"tenant.mapped.requests",
1117+
&["customer_id:top-1", "keep:client", "route:checkout"],
1118+
);
10951119
let snapshot = loop {
10961120
let snapshot = snapshot_handle
10971121
.snapshot()
@@ -1106,7 +1130,15 @@ mod tests {
11061130
assert_eq!(snapshot.len(), 1);
11071131
assert_eq!(snapshot[0].context(), &expected_context);
11081132
assert_eq!(snapshot[0].metric_type(), AggregateMetricType::Counter);
1109-
assert_eq!(snapshot[0].context().tags().len(), 2);
1133+
assert_eq!(snapshot[0].context().tags().len(), 3);
1134+
assert_eq!(
1135+
snapshot[0]
1136+
.context()
1137+
.tags()
1138+
.get_single_tag("customer_id")
1139+
.and_then(|tag| tag.value()),
1140+
Some("top-1")
1141+
);
11101142
assert_eq!(
11111143
snapshot[0]
11121144
.context()

bin/agent-data-plane/src/components/dogstatsd_filterlist.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ use stringtheory::MetaString;
66
pub(super) const METRIC_FILTERLIST_CONFIG_KEY: &str = "metric_filterlist";
77
/// Configuration key for prefix matching on the current Agent metric filterlist.
88
pub(super) const METRIC_FILTERLIST_MATCH_PREFIX_CONFIG_KEY: &str = "metric_filterlist_match_prefix";
9-
/// Configuration key for per-metric tag filter rules.
10-
pub(super) const METRIC_TAG_FILTERLIST_CONFIG_KEY: &str = "metric_tag_filterlist";
119
/// Configuration key for the legacy Agent DogStatsD metric blocklist.
1210
pub(super) const STATSD_METRIC_BLOCKLIST_CONFIG_KEY: &str = "statsd_metric_blocklist";
1311
/// Configuration key for prefix matching on the legacy Agent DogStatsD metric blocklist.

0 commit comments

Comments
 (0)