Skip to content

feat(payload): adopt Probability for TimestampConfig::probability#1877

Open
goxberry wants to merge 1 commit into
goxberry/improve-probability-type-ergonomicsfrom
goxberry/probability-timestamp-config
Open

feat(payload): adopt Probability for TimestampConfig::probability#1877
goxberry wants to merge 1 commit into
goxberry/improve-probability-type-ergonomicsfrom
goxberry/probability-timestamp-config

Conversation

@goxberry
Copy link
Copy Markdown
Contributor

@goxberry goxberry commented May 20, 2026

What does this PR do?

Switches TimestampConfig::probability 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, so the matching
check in TimestampConfig::valid() is removed. The new type threads
through MemberGenerator::new and MetricGenerator::new; at the
comparison sites in MetricGenerator::timestamp, .get() extracts the
inner f32 so RNG draws and bit-exact output are preserved.

Motivation

Phase 1, PR 1 of the stacked rollout planned in #1876 — wire
BoundedProbability aliases into lading_payload configs one field at
a time, smallest blast radius first. TimestampConfig is self-contained
and has its own valid(), so it's the cleanest field to start with.

Moving the validation into the type means invalid configs are rejected
at parse time with a structured error instead of after Config::new
returns a string; the in-code field can no longer hold a value outside
[0.0, 1.0].

Related issues

Stacked on #1876 (Phase 0). Follow-ups to land in this stack:
ValueConf::float_probability, Config::sampling_probability,
Config::multivalue_pack_probability, Config::unique_tag_ratio (via
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.

  • No sampler swap. The hot-path comparison stays
    OpenClosed01.sample(rng) < self.timestamp_probability.get(); the
    .get() is a const fn returning a copied scalar and inlines away.

  • Test fixture changes. Test bodies that constructed
    TimestampConfig literally now go through a prob(f32) -> Probability
    helper. The timestamp_probability_must_be_valid test was rewritten
    to timestamp_probability_rejects_out_of_range_on_deserialize and
    pins the new deserialize-time rejection path (using YAML, matching
    lading's config format).

  • Bench delta. cargo bench -p lading_payload --bench dogstatsd
    against the pre-change baseline:

    • dogstatsd_setup: −3.8%
    • dogstatsd_throughput/1 MiB: −12.6% (improved)
    • dogstatsd_throughput/10 MiB: −18.7% (improved)
    • dogstatsd_throughput/100 MiB: −4.7% (improved)
    • dogstatsd_throughput/1 GiB: no change

    All deltas are favorable or neutral; the per-sample variance at small
    buffer sizes is consistent with system noise rather than a real
    speedup. --bench block (Json payload, unrelated) shows noise-level
    variance.

Copy link
Copy Markdown
Contributor Author

goxberry commented May 20, 2026

@datadog-official
Copy link
Copy Markdown

datadog-official Bot commented May 20, 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: 2905d45 | Docs | Datadog PR Page | Give us feedback!

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: 106f2cadb5

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

Self {
range: ConfRange::Constant(1),
probability: 0.0,
probability: Probability::try_new(0.0).expect("0.0 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.

P2 Badge Avoid introducing an expect in Default

For this repo, the provided /workspace/lading/AGENTS.md explicitly says No .unwrap() or .expect() and MUST NOT panic; this new production Default implementation adds an .expect() panic path. Even though 0.0 is currently a valid Probability, keeping construction panic-free preserves the documented error-handling invariant and avoids future refactors of Probability::try_new turning a default config path into a panic.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is a good flag. @goxberry words are failing me now, but I wonder if there's a nice tidy way to express "is 0%" and "is 100%" as infallible constructors.

@goxberry goxberry force-pushed the goxberry/probability-timestamp-config branch from 106f2ca to 91a7f3b Compare May 21, 2026 06:34
Change the public `TimestampConfig::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, so the matching check in `TimestampConfig::valid()` is removed.

The new type threads through `MemberGenerator::new` and
`MetricGenerator::new`. At the comparison sites in `metric::timestamp`,
`.get()` extracts the inner `f32` so RNG sequences and bit-exact output
are preserved.
@goxberry goxberry force-pushed the goxberry/probability-timestamp-config branch from 91a7f3b to 2905d45 Compare May 21, 2026 06:47
R: Rng + ?Sized,
{
if self.timestamp_probability == 0.0 {
if self.timestamp_probability.get() == 0.0 {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

No change needed, vaguely wondering if we should have a is_zero(&Self) -> bool

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think this change is needed because I removed the Eq implementation in #1876. I believe there are a bunch of places in the PR stack where .get() could be removed in comparisons if I restore the PartialOrd and Ord trait implementations in #1876.

Self {
range: ConfRange::Constant(1),
probability: 0.0,
probability: Probability::try_new(0.0).expect("0.0 is in [0.0, 1.0]"),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is a good flag. @goxberry words are failing me now, but I wonder if there's a nice tidy way to express "is 0%" and "is 100%" as infallible constructors.

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