Skip to content

feat(config): add provider_kind and EKS Fargate static tags - #2255

Open
lucastemb wants to merge 6 commits into
mainfrom
lt/2066
Open

feat(config): add provider_kind and EKS Fargate static tags#2255
lucastemb wants to merge 6 commits into
mainfrom
lt/2066

Conversation

@lucastemb

@lucastemb lucastemb commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Added provider_kind support and EKS Fargate related static tags as part of the ongoing OTLP Ingest metrics pipeline related work.

Support will be pipeline agnostic (meaning it will also apply to DogStatsD) since investigation reveals that this is not scoped simply to just the OTLP pipeline.

We have explicitly chosen to omit some Cluster Agent related tags (now tracked by #2254) due to ADP's current narrow implementation and non-blocking nature to our current work

Change Type

  • Bug fix
  • New feature
  • Non-functional (chore, refactoring, docs)
  • Performance

How did you test this PR?

Unit tests.

References

@dd-octo-sts dd-octo-sts Bot added area/components Sources, transforms, and destinations. area/docs Reference documentation. source/otlp OTLP source. labels Aug 3, 2026
@lucastemb
lucastemb marked this pull request as ready for review August 3, 2026 19:51
@lucastemb
lucastemb requested a review from a team as a code owner August 3, 2026 19:51

@datadog-datadog-us1-prod datadog-datadog-us1-prod Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Datadog Autotest: FAIL

The new static-tag path overwrites otlp_config.metrics.tags instead of preserving configured metric tags. Any deployment that combines existing OTLP metric tags with provider_kind or EKS Fargate tagging will silently lose those existing tags, changing metric dimensions and potentially breaking dashboards and monitors.

View proposed fix
Open Bits AI session

🤖 Datadog Autotest · Commit 6e25d0d · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest

let mut otlp = otlp.clone();
let static_tags = resolve_static_metric_tags(&otlp, &shared.tags, |key| std::env::var(key).ok());
if !static_tags.is_empty() {
otlp.metrics.tags = static_tags.join(",");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Static tags discard configured OTLP metric tags

Existing OTLP metric dimensions silently disappear for users adopting provider-kind or EKS Fargate tagging, causing incorrect grouping and broken dashboards or monitors.

Assertion details
  • Input: Configure otlp_config.metrics.tags as service:checkout and enable the new provider_kind:eks setting. resolve_static_metric_tags returns provider_kind:eks, after which from_configuration assigns that result to otlp.metrics.tags.
  • Expected: Configured metric tags remain present and the new static tags are added, producing service:checkout and provider_kind:eks.
  • Actual: The assignment at line 129 replaces the entire configured tag string with provider_kind:eks; service:checkout is absent before the metric translator parses the tags.

Was this helpful? React 👍 or 👎
🤖 Datadog Autotest · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest

Suggested change
otlp.metrics.tags = static_tags.join(",");
otlp.metrics.tags = if otlp.metrics.tags.is_empty() {
static_tags.join(",")
} else {
format!("{},{}", otlp.metrics.tags, static_tags.join(","))
};

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is addressed in the comment below. The Codex bot is effectively pointing out the same thing.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e25d0d689

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +127 to +129
let static_tags = resolve_static_metric_tags(&otlp, &shared.tags, |key| std::env::var(key).ok());
if !static_tags.is_empty() {
otlp.metrics.tags = static_tags.join(",");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve explicitly configured OTLP metric tags

When provider_kind is non-empty or the process is detected as ECS/EKS Fargate, static_tags is non-empty and this assignment discards the existing otlp_config.metrics.tags value. Since build() later parses only self.otlp.metrics.tags, every explicitly configured OTLP tag silently disappears in those environments; merge or append the static tags instead of replacing the configured string.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is intentional parity as seen here. We're correctly overwriting otlp_config.metrics.tags when resolved static tags are non-empty.

Comment on lines +51 to +55
/// Static provider classification added to every OTLP metric when non-empty.
pub provider_kind: String,

/// Whether the Agent runs as an EKS Fargate sidecar.
pub eks_fargate: bool,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Document defaults and boundaries for the new config fields

The newly added Metrics fields only summarize their purpose, and the added GlobalTags fields similarly only name their source; none explicitly states the empty/false default, relevant boundary behavior, or who should change the setting. Expand the Rustdoc for every added configuration field to cover those required details.

AGENTS.md reference: AGENTS.md:L149-L154

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0b443fa

tags.into_shared()
}

/// Resolves static tags that the Core Agent adds to OTLP metrics.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep the generic OTLP component vendor-neutral

This new Rustdoc names the Core Agent inside lib/saluki-components, which is a generic Saluki crate whose documentation and comments must avoid Datadog Agent-specific names and topology. Describe these as static tags supplied by the server process or configuration instead.

AGENTS.md reference: AGENTS.md:L127-L136

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 0b443fa

@pr-commenter

pr-commenter Bot commented Aug 3, 2026

Copy link
Copy Markdown

Binary Size Analysis (Agent Data Plane)

Baseline: ff0b440 · Comparison: 375a82e · diff
Analysis Configuration: stripped binaries · Pass/Fail Threshold: +5%
Sizes: 41.31 MiB (baseline) vs 41.22 MiB (comparison)
Size Change: -88.74 KiB (-0.21%)

✅ Binary size difference within threshold

Changes by Module
Module File Size Symbols
core -64.04 KiB 2270
tokio -41.25 KiB 790
tracing -36.61 KiB 31
hyper +30.93 KiB 83
anon.5ffef35c7768023811ac5ab5fd4f00ff.912.llvm.8895333964273406369 +18.05 KiB 1
hyper_util -17.72 KiB 11
anon.5ffef35c7768023811ac5ab5fd4f00ff.893.llvm.29477675648423616 -17.62 KiB 1
anon.9f7fcabd42bdb20c281b9db2ecef43c6.574.llvm.17066318201269722550 -17.62 KiB 1
anon.245d8324f3a7be21ede53ec209f567de.981.llvm.7474961383244610137 +17.53 KiB 1
anyhow +15.85 KiB 352
saluki_core::runtime::process +15.39 KiB 2
saluki_components::sources::dogstatsd +14.03 KiB 62
figment +13.82 KiB 107
[sections] -13.62 KiB 9
saluki_common::task::instrument +13.55 KiB 9
anon.d7ad85b9e2664b5ab61ba087f7169665.633.llvm.1983921231008832252 +12.46 KiB 1
anon.9f7fcabd42bdb20c281b9db2ecef43c6.687.llvm.17066318201269722550 -12.37 KiB 1
&mut serde_json +11.64 KiB 36
std -10.80 KiB 105
serde_core +10.39 KiB 126
Detailed Symbol Changes
    FILE SIZE        VM SIZE    
 --------------  -------------- 
  [NEW] +22.7Ki  [NEW] +22.4Ki    _<saluki_components::sources::dogstatsd::DogStatsDConfiguration as saluki_core::components::sources::builder::SourceBuilder>::build::_{{closure}}::h294378970e1c6b98
  [NEW] +18.0Ki  [NEW] +18.0Ki    anon.5ffef35c7768023811ac5ab5fd4f00ff.912.llvm.8895333964273406369
  [NEW] +17.5Ki  [NEW]     +76    anon.245d8324f3a7be21ede53ec209f567de.981.llvm.7474961383244610137
  [NEW] +16.6Ki  [NEW] +16.1Ki    core::ptr::drop_in_place<datadog_agent_config::generated::datadog_configuration::DatadogConfiguration>::hc3bd15e999504b18
  [NEW] +15.4Ki  [NEW] +15.3Ki    _<saluki_core::runtime::process::ProcessFuture<F> as core::future::future::Future>::poll::h36bee3cee1041e04
  [NEW] +15.1Ki  [NEW] +15.0Ki    datadog_agent_config::generated::witness::drive::h9aa562b7cfc925a0
  [NEW] +14.8Ki  [NEW] +14.6Ki    agent_data_plane::state::metrics::rules::compat::get_compat_remappings::h5bb445b7815c4600
  [NEW] +12.6Ki  [NEW] +12.5Ki    agent_data_plane::state::metrics::rules::dogstatsd::get_dogstatsd_remappings::ha71516d8223bc1b6
  [NEW] +12.5Ki  [NEW]     +81    anon.d7ad85b9e2664b5ab61ba087f7169665.633.llvm.1983921231008832252
 -93.9% -10.1Ki -95.6% -10.1Ki    agent_data_plane_config::_::_<impl serde_core::ser::Serialize for agent_data_plane_config::SalukiConfiguration>::serialize::ha4890af58c866150
  [DEL] -12.4Ki  [DEL]     -81    anon.9f7fcabd42bdb20c281b9db2ecef43c6.687.llvm.17066318201269722550
  [DEL] -14.2Ki  [DEL] -14.1Ki    agent_data_plane::state::metrics::rules::get_compat_remappings::hecb92936be43ea62
  [DEL] -14.5Ki  [DEL] -14.4Ki    _<tracing::instrument::Instrumented<T> as core::future::future::Future>::poll::h9ff1f931e38a49a3
  [DEL] -14.5Ki  [DEL] -14.4Ki    datadog_agent_config::generated::witness::drive::h1f4ddadd82aeab06
 -71.3% -15.8Ki -71.6% -15.8Ki    h2::proto::connection::DynConnection<B>::recv_frame::h09d92c074afb400d
  [DEL] -15.8Ki  [DEL] -15.3Ki    core::ptr::drop_in_place<datadog_agent_config::generated::datadog_configuration::DatadogConfiguration>::h12005a1fdeb0ffb6
  [DEL] -17.6Ki  [DEL] -17.5Ki    anon.5ffef35c7768023811ac5ab5fd4f00ff.893.llvm.29477675648423616
  [DEL] -17.6Ki  [DEL]     -76    anon.9f7fcabd42bdb20c281b9db2ecef43c6.574.llvm.17066318201269722550
  [DEL] -21.6Ki  [DEL] -21.4Ki    _<saluki_components::sources::dogstatsd::DogStatsDConfiguration as saluki_core::components::sources::builder::SourceBuilder>::build::_{{closure}}::h4481e0171fc4f085
 -98.0% -23.7Ki -98.5% -23.7Ki    agent_data_plane::state::metrics::rules::get_datadog_agent_remappings::hdf20e2a8dcc983e4
  -0.5% -56.0Ki  +0.2% +12.9Ki    [15273 Others]
  -0.2% -88.7Ki  -0.1% -20.0Ki    TOTAL

@pr-commenter

pr-commenter Bot commented Aug 3, 2026

Copy link
Copy Markdown

Regression Detector (Agent Data Plane)

Run ID: 70f7ebff-0192-4677-a4f3-7d5853fc1c6c
Baseline: ff0b4409 · Comparison: 375a82e5 · diff

Optimization Goals: ✅ No significant changes detected

Fine details of change detection per experiment (5)

Experiments configured erratic: true are tagged (ignored) and skipped when determining which experiments regressed or improved. Experiments which are detected as erratic at runtime are tagged (erratic) to flag that the run's sample dispersion was high, but their regression / improvement signal still counts.

experiment goal Δ mean % links
quality_gates_rss_dsd_medium memory ⚪ +0.50 metrics profiles logs
quality_gates_rss_dsd_low memory ⚪ +0.39 metrics profiles logs
quality_gates_rss_idle memory ⚪ +0.28 metrics profiles logs
quality_gates_rss_dsd_heavy memory ⚪ +0.12 metrics profiles logs
quality_gates_rss_dsd_ultraheavy memory ⚪ -0.47 metrics profiles logs
Bounds Checks: ✅ Passed (5)
experiment check replicates observed links
quality_gates_rss_dsd_heavy memory_usage 10/10 ✅ 227 MiB ≤ 250 MiB metrics profiles logs
quality_gates_rss_dsd_low memory_usage 10/10 ✅ 51.4 MiB ≤ 60 MiB metrics profiles logs
quality_gates_rss_dsd_medium memory_usage 10/10 ✅ 88.8 MiB ≤ 100 MiB metrics profiles logs
quality_gates_rss_dsd_ultraheavy memory_usage 10/10 ✅ 381 MiB ≤ 420 MiB metrics profiles logs
quality_gates_rss_idle memory_usage 10/10 ✅ 31.9 MiB ≤ 40 MiB metrics profiles logs
Explanation

A change is flagged as a regression when |Δ mean %| > 5.00% in the regressing direction for its optimization goal AND SMP marks the experiment as a regression (is_regression: true). Improvements use the matching criteria for the improving direction. Experiments configured erratic: true (tagged (ignored)) are skipped outright; experiments detected as erratic at runtime (tagged (erratic)) still count, since that flag describes sample dispersion rather than directional certainty. The Δ mean % cell is colored accordingly: 🟢 = improvement, 🔴 = regression, ⚪ = neutral. Reduction in CPU or memory is an improvement; reduction in ingress throughput is a regression.

if !otlp.metrics.kubernetes_kubelet_nodename.is_empty() {
tags.push(format!("eks_fargate_node:{}", otlp.metrics.kubernetes_kubelet_nodename));
} else {
warn!("Couldn't build the 'eks_fargate_node' tag: kubernetes_kubelet_nodename is not configured.");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this log message (and the equivalent one below) meant to explicitly match a log message from the Core Agent?

It might be good to try and reword it to make it more friendly to users, in a "problem-solution" pattern:

Tag 'eks_fargate_node' will be missing from telemetry ingested via OTLP due to missing configuration data. Ensure 'kubernetes_kubelet_nodename' is set in the configuration.

If this is just something they can set (but more on that in a second), then we should explicitly be telling them not only what to set but where to set it. As is, we're not being that explicit that this is a configuration setting.

Separately: is this actually something users are expected to set manually, or something that would be configured by the Helm chart or Operator? If it's the latter, then we actually might not want to have the "solution" part if there's no way for them to act on it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like it's something that users set manually. I do think the problem-solution pattern for the error message is better than what I had and was added in c299b79 😄

Comment on lines +80 to +81
let ecs_fargate =
environment("AWS_EXECUTION_ENV").as_deref() == Some("AWS_ECS_FARGATE") || environment("ECS_FARGATE").is_some();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is bothering me. It's an environmental side-effect buried in an otherwise relatively pure function. I feel like this check belongs somewhere that is dedicated to setup (right?) and that its environment determination should be passed in to this function. I'm not sure if there's a "place" for that, but it jumped out at me as a kind of hidden form of config/environment sensitivity.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. Fixed in c299b79. I made it such that the check for ECS_Fargate occurs much earlier and is propagated through instead of belonging to that hacky conditional statement you called out.

@dd-octo-sts dd-octo-sts Bot added the area/config Configuration. label Aug 5, 2026

@webern webern left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I was looking at this, the major question that came up in my mind, which I'm having trouble answering is: why did it come up now that we need the tags and extra_tags configuration fields when we did not need these for DogStatsD.

My limited understanding of this is, ADP's HostTagsConfiguration is temporary because normally it's handled by the backend, but a window is needed before the Agent can sent the host and host_tags to the backend. After that, the backend associates those host tags with data from the host.

These tags and extra_tags fields feel suspiciously related to that mechanism, and seemingly, to me, would behave the same way for OTLP-sourced data in the backend as they would for DSD-sourced data.

To state the halting point I have on this PR differently, or again...

It feels like either this behavior is needed for DogStatsD as well as OTLP, or that it is needed by neither of them. It is entirely possible that I am missing something though because this is a very confusing area of Agent/ADP contract.

Edit: After reading the above, AI is helpfully pointing out that:

OTLP could legitimately differ if its metrics bypass the mechanism by which backend host association works for DogStatsD. That is probably the exact question you want need to answer.

}

/// Returns whether the process runs in an Amazon ECS Fargate environment.
pub fn is_ecs_fargate() -> bool {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on what else is in this file, such as "running in docker", this does seem like a reasonable place to put this function.

Comment on lines +1001 to +1002
self.config.domains.dogstatsd.listeners.provider_kind = value.clone();
self.config.domains.otlp.metrics.provider_kind = value;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit suspicious. I wonder if there is a better home for it in config.shared. I recall that early in the typed config process it was considered desirable that we avoid duplication of a value into two different places in the typed config structure.

@dd-octo-sts dd-octo-sts Bot added the source/dogstatsd DogStatsD source. label Aug 7, 2026
@lucastemb lucastemb changed the title feat(otlp): add provider_kind and EKS Fargate static tags feat(config): add provider_kind and EKS Fargate static tags Aug 7, 2026
@lucastemb
lucastemb force-pushed the lt/2066 branch 2 times, most recently from a1964c3 to 11fa9b2 Compare August 10, 2026 14:12
@dd-octo-sts dd-octo-sts Bot added the area/core Core functionality, event model, etc. label Aug 10, 2026
@dd-octo-sts dd-octo-sts Bot removed the area/core Core functionality, event model, etc. label Aug 10, 2026
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. area/config Configuration. area/docs Reference documentation. source/dogstatsd DogStatsD source. source/otlp OTLP source.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add provider_kind and EKS Fargate static tags to OTLP metrics

3 participants