Skip to content

scenarios: full_host_otlp_cpu (full-host CPU via OTLP, standalone) - #178

Open
r1viollet wants to merge 1 commit into
mainfrom
r1viollet/full-host-otlp-cpu
Open

scenarios: full_host_otlp_cpu (full-host CPU via OTLP, standalone)#178
r1viollet wants to merge 1 commit into
mainfrom
r1viollet/full-host-otlp-cpu

Conversation

@r1viollet

@r1viollet r1viollet commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

What

Adds full_host_otlp_cpu: full-host CPU profiling exercised through the
analyzer's OTLP input path (the CPU counterpart to the pprof full_host
scenario). Depends on the OTLP support merged in #173.

Reusable building blocks (kept out of the scenario)

  • tools/otlp-dump — a generic, dependency-free OTLP/HTTP receiver that
    persists a profiler's OTLP export as .otlp files the analyzer reads
    natively. Reusable by any OTLP-emitting scenario. It exists because getting a
    local-dump option upstream is hard; whether a sidecar dump is the capture
    mechanism we want long-term is an open project question.
  • base_images/Dockerfile.fullhost-otlp (→ prof-fullhost-otlp) — the
    standalone full-host profiler image
    (registry.datadoghq.com/ddot-ebpf-dev:devtest-latest, the host-profiler
    as an OTel Collector distribution) with otlp_dump baked in. Self-contained:
    no agent, no hand-built binary, no binaries/ prerequisite. Moving
    devtest-latest tag is intentional, to surface drift.

The scenario itself (thin: workload + config + start.sh)

  • Assertion: a load-independent CPU rate — the workload pins one core,
    so at the ~20 Hz sampler it accounts for ~20 samples/sec regardless of host
    load (value-matching-sum: 20, scale_by_duration: true), mirroring
    full_host's 1e9 ns/s. profile-type is samples (count), not cpu-time.
  • Timing: the workload runs longer than the profiling window and the
    profiler is stopped while it's still busy, so there's no idle cool-down tail
    report; only the first (start-up) report is partial, tolerated via
    allow_first_profile_failure.

Validated

End-to-end against the real image, built the way the harness does (base image →
scenario, --privileged --pid=host): warm-up report tolerated, steady-state
reports 0–3% error vs the 30% margin. Schema + ruff clean.

Open questions (first cut)

  • Capture mechanism — the otlp_dump sidecar vs some other form. Project
    question.
  • CI — requires pulling registry.datadoghq.com/ddot-ebpf-dev and the
    full_host.* job running --privileged --pid=host (+ debugfs/tracefs).
  • Expectation shape across formats — surfaces the OTLP-vs-pprof differences
    from feature: OTLP format support #173 (samples vs cpu-time, count vs ns, mapping-basename frames).
    Standalone mode is the intended direction (no agent dependency).

Config note

The image's Datadog-flavored otlp_http exporter requires a dd-api-key
header even when pointed at the local sink; the value is unused.

Full-host CPU profiling exercised through the analyzer's OTLP input path (the
CPU counterpart to the pprof `full_host` scenario).

Generic, reusable building blocks (kept out of the scenario):
- tools/otlp-dump: a dependency-free OTLP/HTTP receiver that persists a
  profiler's OTLP export as .otlp files the analyzer reads natively. Reusable by
  any OTLP-emitting scenario. (Whether a sidecar dump is the capture mechanism
  we want long-term is an open project question.)
- base_images/Dockerfile.fullhost-otlp -> prof-fullhost-otlp: the standalone
  full-host profiler image (registry.datadoghq.com/ddot-ebpf-dev:devtest-latest,
  the host-profiler as an OTel Collector distribution) with otlp_dump baked in.
  Self-contained: no agent, no hand-built binary. Moving devtest-latest tag is
  intentional, to surface drift.

The scenario itself is thin (workload + config + start.sh):
- Assertion: a load-independent CPU rate — the workload pins one core, so at the
  ~20 Hz sampler it accounts for ~20 samples/sec regardless of host load
  (value-matching-sum: 20, scale_by_duration: true), mirroring full_host's
  1e9 ns/s. profile-type is "samples" (count), not "cpu-time".
- Timing: the workload runs longer than the profiling window and the profiler
  is stopped while it is still busy, so no idle cool-down tail report is
  produced; only the first (start-up) report is partial, tolerated via
  allow_first_profile_failure.

Config note: the image's Datadog-flavored otlp_http exporter requires a
dd-api-key header even when pointed at the local sink (value unused).

Validated end-to-end against the real image (base image + scenario built as the
harness would): warm-up report tolerated, steady reports 0-3% error vs the 30%
margin.
@r1viollet
r1viollet force-pushed the r1viollet/full-host-otlp-cpu branch from 3a1b0c6 to 3ee20e7 Compare August 3, 2026 08:59
"profile-type": "samples",
"stack-content": [
{
"regular_expression": ".*cpu_workload.*",

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

remote symbolication won't make this very interesting 😄

@r1viollet

Copy link
Copy Markdown
Collaborator Author

@codex review

@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: 3ee20e7633

ℹ️ 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".

sleep 3

echo "=== running cpu_workload for ${WORKLOAD_SECS}s (profiling for ${PROFILE_SECS}s) ==="
DD_SERVICE=cpu_workload_test timeout "${WORKLOAD_SECS}"s /app/cpu_workload &

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep the workload alive until the profiler stops

The workload inherits EXECUTION_TIME_SEC, and workload.c uses that variable as its own duration, so it exits after PROFILE_SECS; the longer timeout "${WORKLOAD_SECS}"s is only an upper bound and cannot extend it. Because the script also sleeps exactly PROFILE_SECS before stopping the profiler, shutdown and the final flush race with—or follow—the workload's exit, potentially producing an idle tail that violates the 20-samples/s assertion. Pass WORKLOAD_SECS to the child or otherwise disable its shorter internal timer.

Useful? React with 👍 / 👎.

{
"test_name": "full_host_otlp_cpu",
"note": "Full-host CPU profiling via the datadog-agent host-profiler, exported as OTLP and captured to .otlp by the otlp_dump sidecar. OTLP-vs-pprof difference: profile-type is 'samples' (a count, unit 'count'), NOT 'cpu-time' (nanoseconds). Like the pprof full_host scenario we assert a load-independent RATE: the workload pins one core, so at the eBPF sampler frequency (~20 Hz) it accounts for ~20 samples/sec regardless of what else runs on the host (value-matching-sum with scale_by_duration:true). Frames are mapping basenames (no symbol upload), so we match the workload binary by regex.",
"pprof-regex": ".*\\.otlp$",

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

not the best name 😄

"scale_by_duration": true,
"stacks": [
{
"profile-type": "samples",

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

samples is not a very convincing name

@r1viollet

Copy link
Copy Markdown
Collaborator Author

maybe I should create a CPU profile type with nanos, asserting on count is strange

@r1viollet
r1viollet marked this pull request as ready for review August 4, 2026 14:04
@r1viollet
r1viollet requested a review from a team as a code owner August 4, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant