Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
3fd70d5
feat(components): expose aggregate context snapshots
thieman Jul 21, 2026
20edec2
fix(components): expose optional snapshot units
thieman Jul 21, 2026
686911b
fix(components): account for snapshot lifecycle
thieman Jul 21, 2026
49d42fc
feat(adp): analyze DogStatsD context artifacts
thieman Jul 21, 2026
db0ffb6
perf(adp): buffer context dump decoding
thieman Jul 21, 2026
bc31245
perf(adp): keep context readers monomorphic
thieman Jul 21, 2026
a82c886
feat(adp): publish secure DogStatsD context dumps
thieman Jul 21, 2026
fda80c8
fix(adp): harden context dump staging
thieman Jul 21, 2026
a7ff331
feat(adp): expose authenticated context dump API
thieman Jul 21, 2026
f482dab
test(adp): cover stopped snapshot owners
thieman Jul 21, 2026
c3f11ef
perf(adp): bound snapshot coordination memory
thieman Jul 21, 2026
4a835be
fix(components): export pending snapshot responses
thieman Jul 21, 2026
165e9d7
feat(adp): authenticate context dump requests
thieman Jul 21, 2026
80d5831
fix(io): normalize supplied HTTP ALPN
thieman Jul 21, 2026
d0cd029
feat(adp): add DogStatsD top commands
thieman Jul 21, 2026
dff7a9f
fix(adp): redact context artifact errors
thieman Jul 21, 2026
6c098ef
feat(adp): wire retained contexts into DogStatsD control
thieman Jul 21, 2026
65e49d5
test(adp): bound context route requests
thieman Jul 22, 2026
32d422f
test(adp): cover retained context lifecycle
thieman Jul 22, 2026
04f0683
perf(adp): benchmark retained context dumps
thieman Jul 22, 2026
b000044
perf(adp): stabilize context dump benchmarks
thieman Jul 22, 2026
420ac1b
docs(adp): explain DogStatsD retained context dumps
thieman Jul 22, 2026
09584d6
docs(adp): keep generated configuration unchanged
thieman Jul 22, 2026
f77bb2b
perf(components): skip abandoned context snapshots
thieman Jul 22, 2026
8ff54e6
fix(adp): secure Windows context dump files
thieman Jul 22, 2026
601a5a1
test(adp): remove root-dependent permission checks
thieman Jul 22, 2026
628c008
test(integration): verify DogStatsD top end to end
thieman Jul 22, 2026
d38aec8
test(integration): verify bidirectional context dump interop
thieman Jul 22, 2026
8a59e08
test(adp): pin NDJSON fixtures to LF
thieman Jul 22, 2026
40386b6
refactor(adp): simplify context dump implementation
thieman Jul 23, 2026
19ecea9
fix(adp): align context dump API with Agent
thieman Jul 23, 2026
f4bac43
docs(adp): record context dump benchmark baselines
thieman Jul 23, 2026
4ab0452
test(integration): cover DogStatsD top on Windows
thieman Jul 23, 2026
60a1f81
fix(airlock): normalize Windows bind source paths
thieman Jul 23, 2026
753aa79
Revert "fix(airlock): normalize Windows bind source paths"
thieman Jul 23, 2026
2d873aa
test(integration): inline Windows DogStatsD top script
thieman Jul 23, 2026
825785d
refactor(adp): simplify context dump publication
thieman Jul 24, 2026
6454800
docs(adp): refresh context dump benchmark baseline
thieman Jul 24, 2026
de53306
refactor(adp): apply simple DogStatsD review cleanups
thieman Jul 27, 2026
c5628a4
fix(adp): drop legacy mum-tags option
thieman Jul 27, 2026
882be00
chore(adp): remove retained-context benchmarks
thieman Jul 27, 2026
530e9fb
test(adp): remove redundant control-surface tests
thieman Jul 28, 2026
b95df47
refactor(adp): rely on privileged API access control
thieman Jul 28, 2026
dcd2a8e
refactor(adp): use existing privileged API client
thieman Jul 28, 2026
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
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# NDJSON fixtures are byte-compared with compressed streams and must not be translated to CRLF.
*.ndjson text eol=lf
Comment thread
thieman marked this conversation as resolved.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion bin/agent-data-plane/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ serde = { workspace = true }
serde_json = { workspace = true }
serde_with = { workspace = true }
stringtheory = { workspace = true }
tempfile = { workspace = true }
tokio = { workspace = true, features = [
"macros",
"net",
Expand All @@ -67,6 +68,7 @@ tokio-util = { workspace = true }
tonic = { workspace = true }
tracing = { workspace = true }
uuid = { workspace = true, features = ["v4"] }
zstd = { workspace = true }

[target.'cfg(target_os = "linux")'.dependencies]
tokio = { workspace = true, features = ["taskdump"] }
Expand All @@ -82,7 +84,8 @@ chrono = { workspace = true }
[dev-dependencies]
datadog-agent-config-testing = { workspace = true }
derive-where = { workspace = true }
saluki-components = { workspace = true }
saluki-components = { workspace = true, features = ["test-util"] }
saluki-config = { workspace = true, features = ["test-util"] }
saluki-core = { workspace = true, features = ["test-util"] }
saluki-metrics = { workspace = true, features = ["test"] }
tower = { workspace = true, features = ["util"] }
70 changes: 46 additions & 24 deletions bin/agent-data-plane/src/cli/dogstatsd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ use saluki_components::sources::DEFAULT_REPLAY_LOOPS;
#[cfg(target_os = "linux")]
use saluki_components::sources::REPLAY_CREDENTIALS_GID;
use saluki_config::{DurationString, GenericConfiguration};
#[cfg(any(target_os = "linux", test))]
use saluki_error::generic_error;
use saluki_error::{ErrorContext as _, GenericError};
use saluki_error::{generic_error, ErrorContext as _, GenericError};
#[cfg(target_os = "linux")]
use saluki_io::net::{unix::uds_sendmsg_with_creds, ProcessCredentials};
use serde::Deserialize;
Expand All @@ -34,6 +32,9 @@ use tracing::{error, info};

use crate::cli::utils::DataPlaneAPIClient;

mod top;
use self::top::{handle_dogstatsd_dump_contexts, handle_dogstatsd_top, DumpContextsCommand, TopCommand};

/// DogStatsD-specific debugging commands.
#[derive(FromArgs, Debug)]
#[argh(subcommand, name = "dogstatsd")]
Expand All @@ -48,6 +49,8 @@ enum DogstatsdSubcommand {
Stats(StatsCommand),
Capture(CaptureCommand),
Replay(ReplayCommand),
Top(TopCommand),
DumpContexts(DumpContextsCommand),
Comment thread
thieman marked this conversation as resolved.
}

/// Prints basic statistics about the metrics received by the data plane.
Expand Down Expand Up @@ -168,34 +171,35 @@ struct StatsResponse<'a> {

/// Entrypoint for the `dogstatsd` commands.
pub async fn handle_dogstatsd_command(bootstrap_config: &GenericConfiguration, cmd: DogstatsdCommand) {
let mut api_client = match DataPlaneAPIClient::from_config(bootstrap_config) {
Ok(client) => client,
Err(e) => {
error!("Failed to create data plane API client: {:#}", e);
std::process::exit(1);
}
};
if let Err(error) = run_dogstatsd_command(bootstrap_config, cmd).await {
error!("{:#}", error);
std::process::exit(1);
}
}

async fn run_dogstatsd_command(
bootstrap_config: &GenericConfiguration, cmd: DogstatsdCommand,
) -> Result<(), GenericError> {
match cmd.subcommand {
DogstatsdSubcommand::Stats(config) => {
if let Err(e) = handle_dogstatsd_stats(&mut api_client, config).await {
error!("Failed to run stats subcommand: {:#}", e);
std::process::exit(1);
}
let mut api_client = data_plane_api_client(bootstrap_config)?;
handle_dogstatsd_stats(&mut api_client, config)
.await
.error_context("Failed to run stats subcommand")
}
DogstatsdSubcommand::Capture(config) => {
if let Err(e) = handle_dogstatsd_capture(&mut api_client, config).await {
error!("Failed to start DogStatsD capture: {:#}", e);
std::process::exit(1);
}
let mut api_client = data_plane_api_client(bootstrap_config)?;
handle_dogstatsd_capture(&mut api_client, config)
.await
.error_context("Failed to start DogStatsD capture")
}
DogstatsdSubcommand::Replay(config) => {
#[cfg(target_os = "linux")]
{
if let Err(e) = handle_dogstatsd_replay(&mut api_client, bootstrap_config, config).await {
error!("Failed to replay DogStatsD traffic: {:#}", e);
std::process::exit(1);
}
let mut api_client = data_plane_api_client(bootstrap_config)?;
handle_dogstatsd_replay(&mut api_client, bootstrap_config, config)
.await
.error_context("Failed to replay DogStatsD traffic")
}

#[cfg(not(target_os = "linux"))]
Expand All @@ -205,13 +209,31 @@ pub async fn handle_dogstatsd_command(bootstrap_config: &GenericConfiguration, c
loops,
} = config;
let _ = (replay_file_path, loops);
error!("DogStatsD replay is only supported on Linux.");
std::process::exit(1);
Err(generic_error!("DogStatsD replay is only supported on Linux."))
}
}
DogstatsdSubcommand::Top(config) => {
let config = config.validate();
let mut output = std::io::stdout();
if config.is_offline() {
handle_dogstatsd_top(None, config, &mut output).await
} else {
let mut api_client = data_plane_api_client(bootstrap_config)?;
handle_dogstatsd_top(Some(&mut api_client), config, &mut output).await
}
}
DogstatsdSubcommand::DumpContexts(_) => {
let mut api_client = data_plane_api_client(bootstrap_config)?;
let mut output = std::io::stdout();
handle_dogstatsd_dump_contexts(&mut api_client, &mut output).await
}
}
}

fn data_plane_api_client(config: &GenericConfiguration) -> Result<DataPlaneAPIClient, GenericError> {
DataPlaneAPIClient::from_config(config).error_context("Failed to create data plane API client")
}

async fn handle_dogstatsd_stats(api_client: &mut DataPlaneAPIClient, cmd: StatsCommand) -> Result<(), GenericError> {
// Trigger a statistics collection and wait for it to complete.
info!(
Expand Down
Loading