Skip to content

feat(payload): adopt Probability for Config::multivalue_pack_probability#1880

Open
goxberry wants to merge 1 commit into
goxberry/probability-sampling-probfrom
goxberry/probability-multivalue-pack-prob
Open

feat(payload): adopt Probability for Config::multivalue_pack_probability#1880
goxberry wants to merge 1 commit into
goxberry/probability-sampling-probfrom
goxberry/probability-multivalue-pack-prob

Conversation

@goxberry
Copy link
Copy Markdown
Contributor

@goxberry goxberry commented May 21, 2026

What does this PR do?

Switches Config::multivalue_pack_probability (in
lading_payload::dogstatsd) from bare f32 to Probability
(BoundedProbability<{ f32::to_bits(0.0) }> from #1876). The try_from
impl enforces finite + [0.0, 1.0] at deserialize time. Config::valid()
did not previously validate this field, so no check is removed — the new
type adds parse-time validation that did not exist before. The new type
threads through MemberGenerator::new and MetricGenerator::new; at the
hot-path comparison site in <MetricGenerator as Generator>::generate,
.get() extracts the inner f32 so RNG draws and bit-exact output are
preserved.

Motivation

Phase 1, PR 4 of the stacked rollout planned in #1876 — wire
BoundedProbability aliases into lading_payload configs one field at a
time, smallest blast radius first. After TimestampConfig::probability
(#1877), ValueConf::float_probability (#1878), and
Config::sampling_probability (#1879), Config::multivalue_pack_probability
is next: it threads through the same MemberGenerator::new ->
MetricGenerator::new constructor chain in dogstatsd.rs /
dogstatsd/metric.rs, with one hot-path comparison site.

Moving the validation into the type means an invalid
multivalue_pack_probability is rejected at parse time with a structured
error; the in-code field can no longer hold a value outside [0.0, 1.0].
Previously this field had no validation at all in Config::valid(), so a
NaN or out-of-range value would have been accepted silently and reached
the OpenClosed01.sample(rng) < p comparison.

Related issues

Stacked on #1879 (PR 3: Config::sampling_probability), which sits atop
#1878 (PR 2), #1877 (PR 1), and #1876 (Phase 0). One field remains in this
rollout: Config::unique_tag_ratio (PR 5, AtLeastOneHundredth).

Additional Notes

  • Wire format unchanged. Probability serializes as a bare f32 via
    serde(into = "f32", try_from = "f32"), so YAML/JSON configs written
    for the previous field type continue to parse.
  • Public API breakage at the Config struct literal. The
    multivalue_pack_probability field is pub; external callers that
    construct Config literally (rather than via Default) must now wrap
    the value in Probability::try_new(...). The in-tree default and all
    test fixtures use ..Default::default() for this field, so no in-tree
    fixtures need updating.
  • No sampler swap. The hot-path comparison stays
    OpenClosed01.sample(rng) < multivalue_pack_probability.get(); .get()
    is a const fn returning a copied scalar and inlines away.
  • Default value preserved. Default for Config now constructs
    Probability::try_new(0.08).expect("0.08 is in [0.0, 1.0]") in place
    of the bare 0.08.
  • Verified. cargo check --workspace --all-targets, cargo clippy -p lading-payload --all-targets -- -D warnings, cargo fmt --all -- --check, and cargo test -p lading-payload --lib --tests (250 pass)
    all clean.
  • Bench delta. Per the rollout plan, cargo bench -p lading-payload --bench dogstatsd (and --bench block) should be run against the
    feat(payload): adopt Probability for Config::sampling_probability #1879 tip; deltas are expected to be machine noise since .get()
    inlines away. Benches pending in a follow-up commit on this branch.

Copy link
Copy Markdown
Contributor Author

goxberry commented May 21, 2026

@datadog-prod-us1-3
Copy link
Copy Markdown

datadog-prod-us1-3 Bot commented May 21, 2026

Pipelines

Fix all issues with BitsAI

⚠️ Warnings

🚦 1 Pipeline job failed

Changelog Check | changelog-check   View in Datadog   GitHub Actions

🛟 This job is unlikely to succeed on retry. Please review your pipeline configuration. No changes to CHANGELOG.md detected. Add 'no-changelog' label if this is intentional.

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: ce4d6c2 | Docs | Datadog PR Page | Give us feedback!

@goxberry
Copy link
Copy Markdown
Contributor Author

PR 4 plan: adopt Probability for Config::multivalue_pack_probability

Per .claude/probability-type-rollout-plan.md, Phase 1, PR 4.

Scope

Change the public Config::multivalue_pack_probability field from f32 to the
Probability alias of BoundedProbability<{ f32::to_bits(0.0) }>. Thread the
type through MemberGenerator::newMetricGenerator::new. At the comparison
site in the generate hot path, call .get() to extract the f32.

Config::valid() currently does not validate
multivalue_pack_probability, so there is no validation block to remove.
Deserialize-time validation is supplied by Probability::try_from.

Stack position

Parent: goxberry/probability-sampling-prob (PR 3, sampling_probability).
This PR is goxberry/probability-multivalue-pack-prob.

Edits

lading_payload/src/dogstatsd.rs

  • Line 165–167: doc comment "Probability between 0 and 1 that a given dogstatsd
    msg / contains multiple values" → drop "between 0 and 1" (bounds are now in
    the type). Change field type from f32 to Probability.
  • Line 274: multivalue_pack_probability: 0.08
    multivalue_pack_probability: Probability::try_new(0.08).expect("0.08 is in [0.0, 1.0]").
  • Line 423: multivalue_pack_probability: f32Probability in
    MemberGenerator::new signature.

lading_payload/src/dogstatsd/metric.rs

  • Line 36: pub(crate) multivalue_pack_probability: f32Probability on
    MetricGenerator.
  • Line 53: multivalue_pack_probability: f32Probability in
    MetricGenerator::new signature.
  • Line 165: prob < self.multivalue_pack_probability
    prob < self.multivalue_pack_probability.get(). The .get() is a const fn
    returning a copied scalar — inlines to identical machine code, preserves the
    OpenClosed01 < p sampler and the user-visible RNG sequence.

Verification

  1. cargo check -p lading_payload (and --all-features).
  2. cargo test -p lading_payload --lib dogstatsd::test.
  3. cargo clippy -p lading_payload --all-targets -- -D warnings.
  4. Run the existing payload_not_exceed_max_bytes proptests
    (already in the test module) — they construct Config::default() so they
    exercise the new Probability value.

Out of scope

  • No swap of OpenClosed01 < p for sample_bernoulli.
  • No YAML/JSON wire format change.
  • No criterion bench run in this turn (per the rollout plan, benches are run
    in a follow-up; the change is mechanical and .get() inlines away).

@goxberry goxberry force-pushed the goxberry/probability-sampling-prob branch from 391a801 to 742fc08 Compare May 21, 2026 05:44
@goxberry goxberry force-pushed the goxberry/probability-multivalue-pack-prob branch from ff156a8 to 52e6ac8 Compare May 21, 2026 05:44
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

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: 52e6ac86e4

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

tags_per_msg: ConfRange::Inclusive { min: 2, max: 50 },
multivalue_count: ConfRange::Inclusive { min: 2, max: 32 },
multivalue_pack_probability: 0.08,
multivalue_pack_probability: Probability::try_new(0.08).expect("0.08 is in [0.0, 1.0]"),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Replace the new expect in Config::default

This new .expect() violates the repository error-handling rule in /workspace/lading/AGENTS.md, which says No .unwrap() or .expect() and that production code must not panic. Even though 0.08 is currently valid, Config::default() is normal construction code, so keep this path panic-free by using an infallible constant/helper or otherwise avoiding .expect().

Useful? React with 👍 / 👎.

@goxberry goxberry force-pushed the goxberry/probability-multivalue-pack-prob branch from 52e6ac8 to 24aaa41 Compare May 21, 2026 06:34
@goxberry goxberry force-pushed the goxberry/probability-sampling-prob branch from 742fc08 to 03dd039 Compare May 21, 2026 06:34
Change the public `Config::multivalue_pack_probability` field from `f32` to
the `Probability` alias of `BoundedProbability<{ f32::to_bits(0.0) }>`. The
`try_from` impl enforces the finite + `[0.0, 1.0]` invariant at deserialize
time. `Config::valid` did not previously validate this field, so no check is
removed.

The new type threads through `MemberGenerator::new` and `MetricGenerator::new`.
At the comparison site in `<MetricGenerator as Generator>::generate`, `.get()`
extracts the inner `f32` so RNG sequences and bit-exact output are preserved.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@goxberry goxberry force-pushed the goxberry/probability-multivalue-pack-prob branch from 24aaa41 to ce4d6c2 Compare May 21, 2026 06:47
@goxberry goxberry force-pushed the goxberry/probability-sampling-prob branch from 03dd039 to 7d6eabc Compare May 21, 2026 06:47
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.

2 participants