A command-line tool for querying Datadog logs, APM spans, and metrics. Outputs NDJSON for easy piping to jq or other tools.
# Install
cargo install --path .
# Set credentials
export DD_API_KEY="your-api-key"
export DD_APP_KEY="your-app-key"
# Search logs
ddog logs search "service:api AND status:error"
# Query metrics
ddog metrics query "avg:system.cpu.user{*}" --from now-1h
# Search spans
ddog spans search "service:web @duration:>1s"Download the latest release from GitHub Releases:
# macOS (Apple Silicon)
curl -L https://github.com/tmcinerney/ddog/releases/latest/download/ddog-darwin-aarch64.tar.gz | tar xz
sudo mv ddog /usr/local/bin/
# macOS (Intel)
curl -L https://github.com/tmcinerney/ddog/releases/latest/download/ddog-darwin-x86_64.tar.gz | tar xz
sudo mv ddog /usr/local/bin/
# Linux (x86_64)
curl -L https://github.com/tmcinerney/ddog/releases/latest/download/ddog-linux-x86_64.tar.gz | tar xz
sudo mv ddog /usr/local/bin/Install from local source using cargo:
# Install from local source
cargo install --path .
# Or build and install with locked dependencies
cargo install --path . --lockedThis installs ddog to your cargo bin directory (typically ~/.cargo/bin), which should be in your PATH if you're using rustup.
Alternatively, build and copy manually:
cargo build --release
cp target/release/ddog /usr/local/bin/# If installed via cargo
cargo uninstall ddog
# If installed manually
rm /usr/local/bin/ddogSet the following environment variables:
| Variable | Required | Description |
|---|---|---|
DD_API_KEY |
Yes | Datadog API key |
DD_APP_KEY |
Yes | Datadog application key |
DD_SITE |
No | Datadog site (default: datadoghq.com, use datadoghq.eu for EU) |
export DD_API_KEY="your-api-key"
export DD_APP_KEY="your-app-key"Your application key must have the following scopes/permissions:
| Command | Required Scope | Description |
|---|---|---|
logs search |
logs_read_data |
Read log data |
spans search |
apm_read |
Read APM span data |
metrics query |
timeseries_query |
Query metrics timeseries data |
metrics list |
metrics_read |
List available metrics |
Note: If you get a 403 Forbidden error, check that your application key has the required permissions in your Datadog account settings.
All commands output newline-delimited JSON (NDJSON), with one record per line. This format works seamlessly with:
jq- For JSON filtering and transformation- Line tools -
grep,head,tail,wc - Streaming - Pipe to files or other processes
# Filter with jq
ddog logs search "service:api" | jq '.attributes.message'
# Count results
ddog logs search "status:error" | wc -l
# Get first 10 results
ddog spans search "service:web" | head -10Most commands share these options:
-f, --from <TIME>- Start time (default:now-1h)-t, --to <TIME>- End time (default:now)
Supported Time Formats:
| Format | Description | Example | Supported By |
|---|---|---|---|
| Relative | Time relative to now | now-15m, now-1h, now-1d |
All commands |
| ISO8601 | ISO 8601 timestamp | 2024-01-15T10:00:00Z |
Logs, Spans |
| Unix | Unix timestamp (ms) | 1705315200000 |
All commands |
Relative Time Units:
s(seconds),m(minutes),h(hours),d(days),w(weeks),mo(months),y(years)- Examples:
now-30s,now-2h,now-1w,now-3mo
Note: Metrics commands do not yet support ISO8601 format.
-l, --limit <N>- Maximum results/data points (default varies by command, use 0 for unlimited)
ddog logs search <QUERY> [OPTIONS]Options:
-f, --from <TIME>- Start time (default:now-1h) - See Common Options-t, --to <TIME>- End time (default:now) - See Common Options-l, --limit <N>- Max results (default: 100, use 0 for unlimited)-i, --indexes <LIST>- Log indexes to search (comma-separated, default: all)
Examples:
# Search for errors in the last hour
ddog logs search "service:api AND status:error"
# Search last 15 minutes with custom limit
ddog logs search "service:web @http.status_code:500" --from now-15m --limit 50
# Search specific indexes
ddog logs search "env:production" --indexes main,web
# Pipe to jq for filtering
ddog logs search "service:api" | jq '.attributes.message'ddog spans search <QUERY> [OPTIONS]Options:
-f, --from <TIME>- Start time (default:now-1h) - See Common Options-t, --to <TIME>- End time (default:now) - See Common Options-l, --limit <N>- Max results (default: 100, use 0 for unlimited)
Examples:
# Search spans by service
ddog spans search "service:web env:prod"
# Find slow spans
ddog spans search "service:api @duration:>1s" --limit 50
# Search with absolute time range (ISO8601)
ddog spans search "service:db" --from "2024-01-15T10:00:00Z" --to "2024-01-15T11:00:00Z"
# Search with Unix timestamp (milliseconds)
ddog spans search "service:api" --from "1705315200000" --to "1705318800000"ddog metrics query <QUERY> [OPTIONS]Options:
-f, --from <TIME>- Start time (default:now-1h) - See Common Options (ISO8601 not supported)-t, --to <TIME>- End time (default:now) - See Common Options-l, --limit <N>- Max data points (default: 1000, use 0 for unlimited)
Examples:
# Query average CPU usage over last hour
ddog metrics query "avg:system.cpu.user{*}" --from now-1h --to now
# Query with host filter
ddog metrics query "max:system.mem.used{host:prod-*}" --from now-15m --to now
# Query multiple metrics
ddog metrics query "avg:system.cpu.user{*},avg:system.cpu.system{*}" --from now-6h --to now
# Pipe to jq for processing
ddog metrics query "avg:redis.net.connections{*}" --from now-1d --to now | jq '.value'
# Filter by specific timestamp
ddog metrics query "avg:system.load.1{*}" | jq 'select(.timestamp > 1705315200)'
# Get average of all values
ddog metrics query "avg:system.cpu.idle{*}" --from now-1h | jq -s 'add / length | .value'ddog metrics list [OPTIONS]Options:
-f, --from <TIME>- Start time (default:now-1h) - Metrics active after this time will be listed - See Common Options-t, --to <TIME>- End time (default:now) - See Common Options
Examples:
# List all metrics active in the last hour
ddog metrics list --from now-1h
# Find specific metrics with grep
ddog metrics list --from now-1h | grep "system.cpu"
# Count total active metrics
ddog metrics list --from now-1h | wc -l
# List and filter with jq
ddog metrics list --from now-1d | jq -r '.metric' | sort | uniqQueries use Datadog's native query syntax:
- Attributes:
@http.status_code:500 - Tags:
env:production - Wildcards:
service:web* - Ranges:
@http.status_code:[200 TO 299] - Boolean:
service:api AND status:error - Negation:
-env:development
Metrics queries use Datadog's metric query syntax:
- Basic:
avg:system.cpu.user{*}- Average CPU across all hosts - Aggregation:
sum,avg,min,max,count - Tag filtering:
avg:system.cpu.user{env:prod} - Multiple tags:
avg:system.cpu.user{env:prod,service:web} - Wildcards:
avg:system.cpu.user{host:web-*} - Arithmetic:
avg:system.cpu.user{*} + avg:system.cpu.system{*} - Functions:
avg:system.cpu.user{*}.rollup(avg, 60)- 60s rollup
| Code | Meaning |
|---|---|
| 0 | Success |
| 2 | Authentication failure |
| 3 | API error |
| 4 | Invalid query |
| 5 | Configuration error |
| 6 | IO error |
| 7 | Serialization error |
This project uses cargo-husky for Rust-native git hooks. The hooks are automatically installed when you run cargo test for the first time.
To manually install the hooks:
# Run cargo test once to trigger hook installation
cargo test
# Or manually install the hook
cp .husky/pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commitThe pre-commit hooks will:
- Check code formatting with
cargo fmt - Run clippy linter with strict warnings
- Run unit tests
CI/CD is configured via GitHub Actions:
CI Workflow (.github/workflows/ci.yml):
- Check: Formatting, clippy linting, and unit tests (runs first)
- Build: Release build (only after checks pass)
Release Workflow (.github/workflows/release.yml):
- Uses release-please for automated releases
- Parses conventional commits to determine version bumps
- Creates release PRs with changelogs
- Builds and uploads binaries for Linux and macOS when releases are created
This project uses Conventional Commits for automatic versioning:
| Commit Type | Example | Version Bump |
|---|---|---|
fix: |
fix: handle empty query |
Patch (0.0.X) |
feat: |
feat: add trace search |
Minor (0.X.0) |
feat!: or BREAKING CHANGE: |
feat!: change output format |
Major (X.0.0) |
docs:, chore:, refactor: |
docs: update README |
No release |
Examples:
git commit -m "fix: correct time parsing for negative offsets"
git commit -m "feat: add support for trace ID lookup"
git commit -m "feat!: change default output to JSON Lines"# Run all unit tests
cargo test
# Run integration tests (requires DD_API_KEY and DD_APP_KEY)
cargo test --test integration_tests -- --ignoredsrc/- Main source codecli/- Command-line interface definitionsargs.rs- Main CLI structure and domain enumshared.rs- Shared argument structures (TimeRange, Pagination)logs.rs,spans.rs,metrics.rs- Domain-specific action enums
client/- Datadog API client wrapperslogs.rs- Logs API clientspans.rs- Spans API clientmetrics.rs- Metrics API client
commands/- Command implementations organized by domainlogs/search.rs- Logs search commandspans/search.rs- Spans search commandmetrics/query.rs- Metrics query commandmetrics/list.rs- List metrics command
config.rs- Configuration loadingerror.rs- Error types and exit codesoutput.rs- NDJSON output writertime.rs- Time parsing and validation utilities
tests/- Integration tests
MIT