Skip to content

feat(c-binding): accept explicit span timestamps#309

Merged
adeshkumar1 merged 2 commits intomainfrom
c-binding/explicit-timestamps
Apr 21, 2026
Merged

feat(c-binding): accept explicit span timestamps#309
adeshkumar1 merged 2 commits intomainfrom
c-binding/explicit-timestamps

Conversation

@adeshkumar1
Copy link
Copy Markdown
Contributor

@adeshkumar1 adeshkumar1 commented Apr 17, 2026

Summary

Adds start_time_ns to dd_span_options_t and dd_span_set_end_time(span, end_time_ns) so FFI callers (Kong) can pass wall-clock nanoseconds captured before the FFI crossing instead of letting the binding record "now." start_time_ns = DD_TRACE_CURRENT_TIME (-1) preserves the current behaviour; dd_span_finish is unchanged.

Notes

  • At span create, start.tick is derived from a current system/steady offset sample (the canonical C++17 pattern; C++20's clock_cast isn't available). In dd_span_set_end_time, end.tick is anchored to start.tick + (end_wall − start_wall) so mid-span clock adjustments (NTP, VM suspend) don't distort the caller's reported duration.
  • End-time is clamped to start-time — serialization casts duration to uint64_t, so end < start would ship as a bogus huge value.
  • Appending to dd_span_options_t is source-compatible (designated initializers zero-init the new field, which is then treated as the 1970-epoch); ABI grows by 8 bytes, so recompilation is required. Callers who want "use current time" must set .start_time_ns = DD_TRACE_CURRENT_TIME explicitly.

@pr-commenter
Copy link
Copy Markdown

pr-commenter Bot commented Apr 17, 2026

Benchmarks

Benchmark execution time: 2026-04-21 15:21:04

Comparing candidate commit 616f1e5 in PR branch c-binding/explicit-timestamps with baseline commit 1f76c5c in branch main.

Found 0 performance improvements and 0 performance regressions! Performance is the same for 1 metrics, 0 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

@adeshkumar1 adeshkumar1 force-pushed the c-binding/explicit-timestamps branch from 2341445 to 79fa0bf Compare April 17, 2026 18:12
@adeshkumar1
Copy link
Copy Markdown
Contributor Author

@codex review

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: 79fa0bfd18

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

Comment thread binding/c/src/tracer.cpp Outdated
@adeshkumar1 adeshkumar1 force-pushed the c-binding/explicit-timestamps branch 2 times, most recently from db1bf1b to 2049e78 Compare April 17, 2026 18:37
@adeshkumar1 adeshkumar1 marked this pull request as ready for review April 17, 2026 18:37
@adeshkumar1 adeshkumar1 requested review from a team as code owners April 17, 2026 18:37
@adeshkumar1 adeshkumar1 requested review from cataphract and Copilot and removed request for a team April 17, 2026 18:37
@adeshkumar1
Copy link
Copy Markdown
Contributor Author

@codex review

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the C binding to accept explicit wall-clock timestamps for span start/end, enabling FFI callers to avoid timing skew from crossing the boundary and to represent work that happened before span creation.

Changes:

  • Add start_time_ns to dd_span_options_t and a new dd_span_finish_with_time(span, end_time_ns) API (with 0 preserving existing “use now” behavior).
  • Implement wall-nanoseconds to internal dd::TimePoint conversion and clamp end tick to start tick to prevent negative durations from serializing as huge unsigned values.
  • Extend the Catch2 C-binding test to cover explicit start/end timestamps and the “end before start” clamp behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
binding/c/include/datadog/c/tracer.h Public C API updated with start_time_ns and dd_span_finish_with_time declaration.
binding/c/src/tracer.cpp Implements wall-ns conversion, new finish function, and clamps negative durations.
binding/c/test/test_c_binding.cpp Adds test coverage for explicit timestamps and end-before-start clamping.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread binding/c/src/tracer.cpp Outdated
Comment thread binding/c/include/datadog/c/tracer.h Outdated
Comment thread binding/c/src/tracer.cpp Outdated
Comment on lines +49 to +51
dd::TimePoint wall_ns_to_timepoint(int64_t wall_ns) {
const auto wall = std::chrono::system_clock::time_point(
std::chrono::duration_cast<std::chrono::system_clock::duration>(
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

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

wall_ns_to_timepoint converts the caller-provided nanoseconds to system_clock::duration via duration_cast, which will truncate on platforms where system_clock has coarser-than-nanosecond resolution. If the C API intends to promise nanosecond precision, consider documenting the effective precision (or rounding behavior) explicitly so callers don’t assume exact round-tripping.

Suggested change
dd::TimePoint wall_ns_to_timepoint(int64_t wall_ns) {
const auto wall = std::chrono::system_clock::time_point(
std::chrono::duration_cast<std::chrono::system_clock::duration>(
// The C API accepts nanoseconds, but system_clock may have coarser
// resolution on some platforms. Round to the nearest representable
// system_clock tick so the loss of precision is explicit and unbiased.
dd::TimePoint wall_ns_to_timepoint(int64_t wall_ns) {
const auto wall = std::chrono::system_clock::time_point(
std::chrono::round<std::chrono::system_clock::duration>(

Copilot uses AI. Check for mistakes.
Comment thread binding/c/test/test_c_binding.cpp Outdated
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: 2049e78cf1

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

Comment thread binding/c/src/tracer.cpp Outdated
@adeshkumar1 adeshkumar1 force-pushed the c-binding/explicit-timestamps branch from 2049e78 to ba2ee22 Compare April 17, 2026 18:54
@adeshkumar1
Copy link
Copy Markdown
Contributor Author

@codex review

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: ba2ee22e3b

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

Comment thread binding/c/src/tracer.cpp Outdated
@adeshkumar1
Copy link
Copy Markdown
Contributor Author

@codex review

@adeshkumar1 adeshkumar1 force-pushed the c-binding/explicit-timestamps branch from ba2ee22 to f2b0803 Compare April 17, 2026 19:09
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: f2b08038d9

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

Comment thread binding/c/src/tracer.cpp Outdated
@adeshkumar1 adeshkumar1 force-pushed the c-binding/explicit-timestamps branch 2 times, most recently from b7ebbe6 to f6c17d0 Compare April 20, 2026 17:19
@adeshkumar1 adeshkumar1 force-pushed the c-binding/explicit-timestamps branch from f6c17d0 to c12d8ee Compare April 20, 2026 17:29
@adeshkumar1 adeshkumar1 requested a review from dmehala April 20, 2026 17:33
Copy link
Copy Markdown
Collaborator

@xlamorlette-datadog xlamorlette-datadog left a comment

Choose a reason for hiding this comment

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

Please review my comments, and I think we're good to go.

Comment thread binding/c/include/datadog/c/tracer.h
Comment thread binding/c/include/datadog/c/tracer.h Outdated
Comment thread binding/c/src/tracer.cpp Outdated
Comment thread binding/c/src/tracer.cpp Outdated
Comment thread binding/c/include/datadog/c/tracer.h Outdated
Comment thread binding/c/include/datadog/c/tracer.h
@adeshkumar1 adeshkumar1 removed the request for review from cataphract April 21, 2026 15:12
Per review feedback from @dmehala:

1. Rename dd_span_finish_with_time → dd_span_set_end_time to match the
   C++ Span::set_end_time and the existing dd_span_set_* naming family.
2. Expose DD_TRACE_CURRENT_TIME (-1) as the "use current time" sentinel
   for start_time_ns, so 0 (1970-01-01) stays a valid timestamp.
3. Drop the sentinel branch in dd_span_set_end_time; callers wanting
   the current end time use dd_span_finish, and this also removes the
   implicit-path clamp that was only defending against a future-start
   caller bug.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

4 participants