Skip to content

Define a default tracing policy #584

Closed

Description

Expected Behavior

Users of substrate should be able to use tracing to identify problems in their systems by default.

See also #580, #581

Actual Behavior

Today, users cannot really use tracing to investigate failures because

  • every components hardcodes its sampler at startup
  • router is set to NeverSample
  • ateapi requires --trace via the CLI to be traces
  • we never read OTEL_TRACES_SAMPLER

Proposal

To follow OpenTelemetry recommendations, sampling should happen in the pipeline, not in the observed application itself.

So I am proposing the following:

  • Control-plane sampled by default:
    • ateapi, atelet, ateom set ParentBased(AlwaysSample)
    • Control plane request volume is small compared to the data plane, and these are the traces we need when suspend/resume/restore needs troubleshooting.
    • We can extend this via exemplars on the upcoming lifecycle duration histograms.
  • Data plane parent-based with a low default ratio at the root: The router sets ParentBased(TraceIDRatioBased(small)). Clients sampled already stay sampled; the ratio defines how many unsampled requests we pull in.
  • Leverage OTEL_TRACES_SAMPLER: This is the OTel-native way of exposing this to end users

Non-goals

Open questions

  1. Is a ratio at the router root acceptable for everyone as the data plane default, and what is a sane starting value? I would start conservative, e.g. 1%, it's configurable anyway.
  2. Do we want always_on for the lifecycle plane at target scale (1B actors means a lot of lifecycle ops), or should ateapi also default to a higher (than 1%) ratio?

Activity

  1. zlammerts-svg commented on Jul 30, 2026

    @zlammerts-svg
    Collaborator

    Da Huang (@git286) will review and provide feedback directly. Thanks!

  2. git286 commented on Jul 30, 2026

    @git286
    Collaborator

    Thanks for this proposal and agreed with the direction! Sampling policy being unowned and unconfigurable is a real problem.

    On the open questions: (1) yeah, let's be more conservative here (1% or less). I have some concern of the scalability of the centralized otel collector and we need to do more stress testing and benchmarking (cc Max Smythe (@maxsmythe) Jeff Luo (@JeffLuoo)) to understand the limit. (2) Can we split into operator-initiated (e.g., human run cmd, always on) vs. machine-driven lifecycle (ratio)?

  3. krisztianfekete commented on Jul 31, 2026

    @krisztianfekete
    CollaboratorAuthor

    Thanks Da Huang (@git286)!

    Re. (1): agreed, let's start at 1% or lower, I am fine with either, since it's configurable via the env var. Worth noting the low ratio we set is basically head sampling in the SDK, so whatever we drop at the root never reaches the collector at all. Happy to do the benchmarking work too to have actual numbers.

    Re. (2): we can do the split via ParentBased I think:

    • Human run is via --trace, and every parent-based downstream keeps the whole request sampled
    • Machine-driven lifecycle: internal callers don't set the flag, so ratio will be applied

    One thing to keep in mind with the operator path is that honoring a client-set sampled flag means any caller can force sampling for its own requests. I think that's acceptable as long as the collector owns the real volume limits (as it should), but if it ever becomes a concern, we can think about gating --trace.

    If all sounds right I'll put up the PR with these defaults.

  4. git286 commented on Jul 31, 2026

    @git286
    Collaborator

    yeah, the collector should limit the volume to the backend. Sounds good! Thanks, Krisztian F (@krisztianfekete) !

  5. krisztianfekete commented on Aug 3, 2026

    @krisztianfekete
    CollaboratorAuthor

    Thanks Da Huang (@git286), the PR is open here: #711

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions