Dual shipping metrics support#704
Conversation
|
Can you rebase this with main? it's got a bunch of old commits which landed there a while ago |
cf7be12 to
d05296e
Compare
d05296e to
e09063e
Compare
There was a problem hiding this comment.
Pull Request Overview
Adds support for dual shipping metrics by introducing an additional_endpoints config field (from YAML or DD_ADDITIONAL_ENDPOINTS), wiring it into the EnvConfig merge logic, and updating component revisions.
- Deserialize and test
additional_endpointsin both YAML and env contexts - Merge
additional_endpointsintoEnvConfigwhen not provided via env - Bump
serverless-componentsrevisions; accidental license removal inLICENSE-3rdparty.yml
Reviewed Changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| bottlecap/src/config/yaml.rs | Added additional_endpoints field and YAML parsing test |
| bottlecap/src/config/mod.rs | Merge logic for additional_endpoints into runtime config |
| bottlecap/src/config/env.rs | deserialize_additional_endpoints function, struct field, and tests |
| bottlecap/LICENSE-3rdparty.yml | Removed third-party license block for datadog-fips |
| bottlecap/Cargo.toml | Updated serverless-components git revisions |
Comments suppressed due to low confidence (4)
bottlecap/LICENSE-3rdparty.yml:4239
- The license block for
datadog-fipswas removed, which may violate third-party license compliance. Please restore the removed Apache-2.0 license text.
- Licensed under the Apache License, Version 2.0 (the "License");
bottlecap/src/config/mod.rs:249
- There’s no test for the merge behavior when both env and YAML provide
additional_endpoints. Consider adding a unit test to validate thatEnvConfigpicks the correct source.
if config.additional_endpoints.is_empty() {
bottlecap/src/config/env.rs:4
- The function
deserialize_additional_endpointsrelies onserde_json::Valuebut it isn’t imported; adduse serde_json::Value;so the code will compile.
use tracing::error;
bottlecap/src/config/env.rs:292
- The signature of
deserialize_additional_endpointsexpects aDeserializer, but in tests you’re passing aValuedirectly. Consider refactoring the function to accept aValueor use a properDeserializer(e.g.,serde_json::value::Deserializer) in tests.
let result = deserialize_additional_endpoints(input).unwrap();
| metric_flush_handles: FuturesOrdered<JoinHandle<MetricsRetryBatch>>, | ||
| } | ||
|
|
||
| struct MetricsRetryBatch { |
There was a problem hiding this comment.
Eventually we should move this to a metrics owned folder
| async fn blocking_flush_all( | ||
| logs_flusher: &LogsFlusher, | ||
| metrics_flusher: &mut MetricsFlusher, | ||
| metrics_flusher: &mut [MetricsFlusher], |
There was a problem hiding this comment.
Can we be more explicit here with Vec<...>? Just for readability
There was a problem hiding this comment.
I initially had this as Vec<...> but clippy doesn't like it
| tokio::join!( | ||
| logs_flusher.flush(None), | ||
| metrics_flusher.flush(), | ||
| futures::future::join_all(metrics_futures), |
| for (endpoint_url, api_keys) in &config.additional_endpoints { | ||
| let dd_url = DdUrl::new(endpoint_url.clone()).expect("can't parse additional endpoint URL"); | ||
| let prefix_override = MetricsIntakeUrlPrefixOverride::maybe_new(Some(dd_url), None); | ||
| let metrics_intake_url = MetricsIntakeUrlPrefix::new(None, prefix_override) | ||
| .expect("can't parse additional endpoint URL"); | ||
|
|
||
| // Create a flusher for each endpoint URL and API key pair | ||
| for api_key in api_keys { | ||
| let additional_flusher_config = MetricsFlusherConfig { | ||
| api_key: api_key.clone(), | ||
| aggregator: metrics_aggr.clone(), | ||
| metrics_intake_url_prefix: metrics_intake_url.clone(), | ||
| https_proxy: config.https_proxy.clone(), | ||
| timeout: Duration::from_secs(config.flush_timeout), | ||
| retry_strategy: DsdRetryStrategy::Immediate(3), | ||
| }; | ||
| flushers.push(MetricsFlusher::new(additional_flusher_config)); |
There was a problem hiding this comment.
Wondering if this logic should live in main, not something to address now
There was a problem hiding this comment.
I was thinking about this too, I can work on refactoring this when implementing dual shipping for log/traces if that could live together?
| flushers.push(MetricsFlusher::new(flusher_config)); | ||
|
|
||
| for (endpoint_url, api_keys) in &config.additional_endpoints { | ||
| let dd_url = DdUrl::new(endpoint_url.clone()).expect("can't parse additional endpoint URL"); |
There was a problem hiding this comment.
There are a few more expects here. While previously we've tolerated them, can we update this so the program doesn't crash if the user provides an invalid site? We can log a fatal error and then replace it with datadoghq.com maybe?
There was a problem hiding this comment.
Yes sounds good
There was a problem hiding this comment.
Fixed this, tested that it falls back and ships data as expected
Adds support for dual shipping metrics to endpoints configured using the `additional_endpoints` YAML or `DD_ADDITIONAL_ENDPOINTS` env var config. For each configured endpoint/API key combination, we now create a separate `MetricsFlusher` to flush the same batch of metrics to multiple endpoints in parallel. Also, updates the retry logic to retry flushing for the specific flusher that encountered an error. Tested dual shipping metrics to 2 additional orgs/endpoints including eu1. Depends on dogstatsd changes: DataDog/serverless-components#20
Adds support for dual shipping metrics to endpoints configured using the
additional_endpointsYAML orDD_ADDITIONAL_ENDPOINTSenv var config.For each configured endpoint/API key combination, we now create a separate
MetricsFlusherto flush the same batch of metrics to multiple endpoints in parallel. Also, updates the retry logic to retry flushing for the specific flusher that encountered an error.Tested dual shipping metrics to 2 additional orgs/endpoints including eu1.
Depends on dogstatsd changes: DataDog/serverless-components#20
SVLS-6884