Skip to content

Commit 9c1abde

Browse files
authored
enhancement(antithesis): Introduce rig intake API (#1826)
## Summary This commit introduces an intake API for antithesis tests. It's a new implementation compared to the pre-existing intake in the project as this intake has different concerns. It will rapidly diverge from the other intake, being focused on allowing driver and check claims when running under Antithesis. ## Change Type - [ ] Bug fix - [ ] New feature - [x] Non-functional (chore, refactoring, docs) - [ ] Performance
1 parent d63c8c5 commit 9c1abde

22 files changed

Lines changed: 1011 additions & 103 deletions

Cargo.lock

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ members = [
3333
"lib/saluki-tls",
3434
"lib/stringtheory",
3535
"test/antithesis/harness",
36+
"test/antithesis/intake",
3637
]
3738
resolver = "2"
3839

@@ -235,6 +236,7 @@ lru-slab = { version = "0.1.2", default-features = false }
235236
hickory-resolver = { version = "0.26", default-features = false }
236237
antithesis-instrumentation = { version = "0.1" }
237238
antithesis_sdk = { git = "https://github.com/antithesishq/antithesis-sdk-rust", rev = "78c9db56771f0f6b01cb5404765c5a96852c159c", default-features = false } # 0.2.8 is pinned to rand 0.8, rev version allows us to select workspace rand
239+
mime = "0.3"
238240

239241
[patch.crates-io]
240242
# Forked version of `hyper-http-proxy` that removes an unused dependency on `rustls-native-certs`, which transitively depends

test/antithesis/deploy/Dockerfile

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55
# Build context is the repository root. Three named targets:
66
# - adp : agent-data-plane built WITH Antithesis coverage instrumentation + SDK (the SUT)
7-
# - intake : datadog-intake mock Datadog intake (dependency)
7+
# - intake : antithesis-intake mock Datadog intake + W-property assertions (dependency)
88
# - workload : DogStatsD driver + test templates + setup-complete (the client)
99
#
1010
# ADP is built native x86_64-unknown-linux-gnu (glibc), so no musl cross-compile headers are needed.
@@ -67,7 +67,7 @@ RUN --mount=type=cache,target=/adp/target,id=antithesis-adp-target \
6767
echo "Instrumentation symbols present."
6868

6969
# ---------------------------------------------------------------------------
70-
# Build the correctness tools (datadog-intake) and the test-command binaries, uninstrumented.
70+
# Build the antithesis-intake mock and the test-command binaries, uninstrumented.
7171
# These are supporting harness components, not the SUT, so they need no coverage instrumentation.
7272
# ---------------------------------------------------------------------------
7373
FROM build-base AS tools-builder
@@ -77,14 +77,13 @@ RUN --mount=type=cache,target=/tools/target,id=antithesis-tools-target \
7777
--mount=type=cache,target=/root/.cargo/registry,id=cargo-registry \
7878
--mount=type=cache,target=/root/.cargo/git,id=cargo-git \
7979
cargo build --release \
80-
--bin datadog-intake \
80+
--bin antithesis-intake \
8181
--bin parallel_driver_send_dogstatsd --bin parallel_driver_sketchburst \
82-
--bin finally_verify_delivery --bin eventually_adp_alive \
82+
--bin eventually_adp_alive \
8383
--bin first_sample_config && \
84-
cp /tools/target/release/datadog-intake /usr/local/bin/datadog-intake && \
84+
cp /tools/target/release/antithesis-intake /usr/local/bin/antithesis-intake && \
8585
cp /tools/target/release/parallel_driver_send_dogstatsd /usr/local/bin/parallel_driver_send_dogstatsd && \
8686
cp /tools/target/release/parallel_driver_sketchburst /usr/local/bin/parallel_driver_sketchburst && \
87-
cp /tools/target/release/finally_verify_delivery /usr/local/bin/finally_verify_delivery && \
8887
cp /tools/target/release/eventually_adp_alive /usr/local/bin/eventually_adp_alive && \
8988
cp /tools/target/release/first_sample_config /usr/local/bin/first_sample_config
9089

@@ -118,12 +117,15 @@ ENTRYPOINT ["/entrypoint.sh"]
118117
CMD ["run"]
119118

120119
# ---------------------------------------------------------------------------
121-
# Runtime: datadog-intake (mock Datadog intake dependency).
120+
# Runtime: antithesis-intake (mock Datadog intake + W-property assertions).
122121
# ---------------------------------------------------------------------------
123122
FROM ${APP_IMAGE} AS intake
124123
ENV NO_COLOR=1
125-
COPY --from=tools-builder /usr/local/bin/datadog-intake /usr/local/bin/datadog-intake
126-
ENTRYPOINT ["/usr/local/bin/datadog-intake"]
124+
# W17 resolves each series' host resource against this hostname. Keep it in sync
125+
# with `hostname:` in adp/datadog.yaml and the DD_HOSTNAME default in the harness.
126+
ENV DD_HOSTNAME=antithesis-adp
127+
COPY --from=tools-builder /usr/local/bin/antithesis-intake /usr/local/bin/antithesis-intake
128+
ENTRYPOINT ["/usr/local/bin/antithesis-intake"]
127129

128130
# ---------------------------------------------------------------------------
129131
# Runtime: workload client (DogStatsD driver + test templates).
@@ -141,7 +143,6 @@ COPY test/antithesis/deploy/workload/test/ /opt/antithesis/test/
141143
COPY --from=tools-builder --chmod=755 /usr/local/bin/first_sample_config /opt/antithesis/test/v1/main/first_sample_config
142144
COPY --from=tools-builder --chmod=755 /usr/local/bin/parallel_driver_send_dogstatsd /opt/antithesis/test/v1/main/parallel_driver_send_dogstatsd
143145
COPY --from=tools-builder --chmod=755 /usr/local/bin/parallel_driver_sketchburst /opt/antithesis/test/v1/main/parallel_driver_sketchburst
144-
COPY --from=tools-builder --chmod=755 /usr/local/bin/finally_verify_delivery /opt/antithesis/test/v1/main/finally_verify_delivery
145146
COPY --from=tools-builder --chmod=755 /usr/local/bin/eventually_adp_alive /opt/antithesis/test/v1/main/eventually_adp_alive
146147
COPY --chmod=755 test/antithesis/deploy/workload/entrypoint.sh /entrypoint.sh
147148
ENTRYPOINT ["/entrypoint.sh"]

test/antithesis/deploy/docker-compose.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ services:
1414
environment:
1515
NO_COLOR: "1"
1616
healthcheck:
17-
# datadog-intake serves HTTP on :2049. /dev/tcp avoids needing curl in the image.
17+
# antithesis-intake serves HTTP on :2049. /dev/tcp avoids needing curl in the image.
1818
test: ["CMD-SHELL", "bash -c 'exec 3<>/dev/tcp/localhost/2049'"]
1919
interval: 2s
2020
timeout: 2s

test/antithesis/harness/src/bin/finally_verify_delivery.rs

Lines changed: 0 additions & 92 deletions
This file was deleted.

test/antithesis/intake/Cargo.toml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
[package]
2+
name = "antithesis-intake"
3+
version = "0.1.0"
4+
edition = { workspace = true }
5+
license = { workspace = true }
6+
repository = { workspace = true }
7+
publish = false
8+
9+
[[bin]]
10+
name = "antithesis-intake"
11+
path = "src/bin/intake.rs"
12+
13+
[lints]
14+
workspace = true
15+
16+
[dependencies]
17+
antithesis_sdk = { workspace = true, features = ["full"] }
18+
anyhow = { workspace = true, features = ["std"] }
19+
axum = { workspace = true, features = ["http1", "json", "tokio", "tracing"] }
20+
clap = { workspace = true, features = ["derive", "env", "error-context", "help", "std", "usage"] }
21+
datadog-protos = { workspace = true }
22+
headers = { workspace = true }
23+
mime = { workspace = true }
24+
protobuf = { workspace = true }
25+
serde_json = { workspace = true }
26+
tokio = { workspace = true, features = [
27+
"macros",
28+
"net",
29+
"rt",
30+
"rt-multi-thread",
31+
"signal",
32+
] }
33+
tower = { workspace = true }
34+
tower-http = { workspace = true, features = [
35+
"decompression-deflate",
36+
"decompression-gzip",
37+
"decompression-zstd",
38+
] }
39+
tracing = { workspace = true }
40+
tracing-subscriber = { workspace = true, features = [
41+
"ansi",
42+
"env-filter",
43+
"fmt",
44+
"local-time",
45+
"registry",
46+
"std",
47+
"tracing-log",
48+
] }

test/antithesis/intake/README.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# A property asserting intake for Datadog Agent-like artifacts
2+
3+
This intake asserts structural and aggregation properties on payloads from
4+
Datadog Agent-like programs and is intended to mimic the constraints set by
5+
Datadog Intake API. This implementation is forked from the other intake in this
6+
project and may be later merged back up, although the goals to make aggregation
7+
assertions here is invasive.
8+
9+
### How This Project Works
10+
11+
This document is the 'specification' for an abstract DogStatsD Agent. We assert
12+
that for any given input stream ADP emits to the intake data that is correctly
13+
shaped and, in a future update, that the aggregation model of ADP is accurate to
14+
the reference implementation of Datadog Agent DogStatsD.
15+
16+
# Properties
17+
18+
## Payloads
19+
20+
The Agent emits outputs to Datadog intake endpoints as payloads. The current
21+
specification covers `/api/v2/series` only. The Agent also emits to
22+
`/api/v3/series`, which a future revision will add.
23+
24+
In this section we define properties that hold for `/api/v2/series` payloads
25+
irrespective of load generation profile. Precisely, a 'payload' is an HTTP
26+
envelope wrap around the compressed bytes of a
27+
[`MetricPayload`](https://github.com/DataDog/agent-payload/blob/0a5f9ebbbe9c2a1f1e671467511f6189d3a3b443/proto/metrics/agent_payload.proto#L30-L72).
28+
29+
Some properties reference rig-controlled parameters. `MaxTags(orgID)` and
30+
`MaxResources(orgID)` are per-org caps with defaults 100 and 500 respectively.
31+
`hostname` is the value the rig passes to the Agent via the `DD_HOSTNAME`
32+
environment variable. The Agent's hostname provider chain resolves this first,
33+
short-circuiting cloud-metadata and OS fallbacks.
34+
35+
| Number | Category | Name | Description |
36+
|--------|---------------|------------------------|----------------------------------------------------------------|
37+
| Pyld01 | Envelope | Content-Type | `Content-Type` in `{application/x-protobuf, application/json}` |
38+
| Pyld02 | Envelope | Content-Encoding | `Content-Encoding` in `{deflate, gzip, zstd, identity}` |
39+
| Pyld03 | Envelope | API Key | `DD-Api-Key` header present and non-empty |
40+
| Pyld05 | Bytes | Compressed Size | body < 500 KiB compressed |
41+
| Pyld06 | Bytes | Uncompressed Size | body <= 5 MiB uncompressed |
42+
| Pyld07 | MetricPayload | Decode | body decodes as v2 `MetricPayload` via `rust-protobuf`. |
43+
| Pyld08 | MetricPayload | Point Count | total points <= configured `serializer_max_series_points_per_payload` |
44+
| Pyld09 | MetricSeries | Metric Non-Empty | `MetricSeries.metric` is non-empty |
45+
| Pyld10 | MetricSeries | Metric Length | `len(metric) <= 350` bytes |
46+
| Pyld11 | MetricSeries | Metric Alphabetic | `metric` contains at least one ASCII alphabetic char |
47+
| Pyld12 | MetricSeries | Type Enum | `type` in `{COUNT, RATE, GAUGE}` |
48+
| Pyld13 | MetricSeries | Tag Count | `len(tags) <= MaxTags(orgID)` |
49+
| Pyld14 | MetricSeries | Tag Prefix Reserved | no tag starts with `device:` or `dd.internal.resource:` |
50+
| Pyld15 | MetricSeries | Per-Series Point Count | `len(points) <=` configured `serializer_max_series_points_per_payload` |
51+
| Pyld16 | MetricSeries | Origin Populated | `origin.{product, category, service}` enum-valid |
52+
| Pyld17 | Resource | Host Resource Resolved | intake's `Host()` scan resolves a `(type="host", name=hostname)` resource |
53+
| Pyld18 | Resource | Resource Count | `len(resources) <= MaxResources(orgID)` |
54+
| Pyld19 | Resource | Host Name Length | host `name <= 255` bytes |
55+
| Pyld20 | MetricPoint | Value Not-NaN | `value` is not NaN |
56+
| Pyld21 | MetricPoint | Timestamp Future Bound | `timestamp <= intake_now + 600s` |
57+
| Pyld22 | Bytes | Content-Length | `Content-Length` absent or value equals body byte count |

0 commit comments

Comments
 (0)