Skip to content

ci: Introduce ast-grep, rule skill guidance, extern c panic rule - #2595

Open
colin-higgins wants to merge 5 commits into
mainfrom
colin.higgins/thematic-rule-skill
Open

colin-higgins wants to merge 5 commits into
mainfrom
colin.higgins/thematic-rule-skill

Conversation

@colin-higgins

@colin-higgins colin-higgins commented Sep 29, 2026 •

Copy link
Copy Markdown
Member

What does this PR do?

Adds a whole-repository ast-grep scan that reports exported FFI entry points whose bodies do not acknowledge panic containment. Matching is on the Rust AST. Both rules are severity: warning, so the existing hits are reported and do not fail the Lint job.

  • ffi-extern-c-panic-containment matches exported functions: pub, #[no_mangle], or #[export_name], with ABI extern "C", bare extern (C by default), or extern "system". Accepted containment is std::panic::catch_unwind, wrap_with_ffi_result!, wrap_with_void_ffi_result!, the *_no_catch! variants, and catch_panic!. // allow(ffi-panic-boundary): <justification> on a line directly above the function is accepted. An empty justification, or the same words only in a comment or string, is not.
  • ffi-macro-emits-extern-c matches a macro_rules template that emits those functions. ast-grep does not expand macros, so containment has to be in the template or in an allow comment above it.
  • ./scripts/run-ast-grep.sh is the local and CI command: rule tests, then a whole-repo scan. The Lint job and pre-commit use that script. The first run downloads a pinned ast-grep binary into ~/.cache.
  • Documents the convention in AGENTS.md and CONTRIBUTING.md, and adds an add-lint-rule skill that prefers ast-grep for new syntactic checks.

Motivation

A panic that crosses an extern "C" or extern "system" boundary aborts the host process. Clippy's panic and unwrap lints only see explicit panic constructs, not panics from callees, so reviews kept flagging new uncontained FFI entry points. There are too many existing sites to fix or allow-comment in this change, so the rules warn on the whole tree instead of failing the job or checking only the diff.

Additional Notes

No existing FFI function or runtime behavior changes. datadog-sidecar-ffi still uses panic=abort; do not add catch_unwind there. Private extern callbacks without pub, #[no_mangle], or #[export_name] are not entry points. extern "C-unwind" is not matched.

scripts/_add_ffi_panic_allows.py is a local one-shot for inserting allow comments later. CI does not run it.

How to test the change?

# Fixtures: wrappers, justified allows, comment-only text, empty allows,
# non-pub #[no_mangle], bare extern, extern "system", and macro templates.
./scripts/run-ast-grep.sh test

# Same command CI runs. Exits 0. The scan prints warnings for existing
# uncontained exports and does not fail on them.
./scripts/run-ast-grep.sh

@colin-higgins
colin-higgins requested review from a team as code owners September 29, 2026 19:37
@colin-higgins colin-higgins changed the title Introduce ast-grep, rule skill guidance, extern c panic rule ci: Introduce ast-grep, rule skill guidance, extern c panic rule Sep 29, 2026

@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: 9a03908415

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread scripts/run-ffi-panic-lint.sh Outdated
Comment thread scripts/run-ffi-panic-lint.sh Outdated
Comment thread .sg/rules/ffi-extern-c-panic-containment.yml
@datadog-prod-us1-6

datadog-prod-us1-6 Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Tests

✅ All CI checks and tests passed.

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
• Patch Coverage: 100.00%
• Overall Coverage: 82.02% (+3.04%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 3f70e94 | Docs | View more details | Give us feedback!

@dd-octo-sts

dd-octo-sts Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Artifact Size Benchmark Report

aarch64-alpine-linux-musl
Artifact Baseline Commit Change
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 9.08 MB 9.08 MB 0% (0 B) 👌
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.a 96.32 MB 96.32 MB 0% (0 B) 👌
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 12.26 MB 12.26 MB 0% (0 B) 👌
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 107.70 MB 107.70 MB 0% (0 B) 👌
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 29.15 MB 29.15 MB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 97.94 KB 97.94 KB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 191.91 MB 191.91 MB +0% (+8.00 KB) 👌
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 817.64 MB 817.64 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 9.75 MB 9.75 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 97.94 KB 97.94 KB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 27.61 MB 27.61 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 55.79 MB 55.79 MB 0% (0 B) 👌
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 25.48 MB 25.48 MB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 99.47 KB 99.47 KB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 197.18 MB 197.22 MB +.01% (+40.00 KB) 🔍
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 804.50 MB 804.50 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 7.56 MB 7.56 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 99.47 KB 99.47 KB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 29.73 MB 29.73 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 52.72 MB 52.72 MB 0% (0 B) 👌
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 86.30 MB 86.30 MB 0% (0 B) 👌
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 10.08 MB 10.08 MB 0% (0 B) 👌
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 102.14 MB 102.14 MB 0% (0 B) 👌
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 12.32 MB 12.32 MB 0% (0 B) 👌

@pr-commenter

pr-commenter Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Benchmarks

Comparison

Benchmark execution time: 2026-10-14 03:02:25

Comparing candidate commit 3f70e94 in PR branch colin.higgins/thematic-rule-skill with baseline commit 2d7e649 in branch main.

📊 Benchmarking dashboard

Found 28 performance improvements and 40 performance regressions! Performance is the same for 109 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 ----------------------------------'

scenario:agentless_encoding/common_http/20x5

  • 🟩 execution_time [-13.604µs; -13.514µs] or [-11.720%; -11.643%]
  • 🟩 throughput [+113584.818op/s; +114332.045op/s] or [+13.184%; +13.270%]

scenario:agentless_encoding/http_with_span_links/20x5

  • 🟩 execution_time [-15.209µs; -15.089µs] or [-11.521%; -11.430%]
  • 🟩 throughput [+97820.919op/s; +98559.754op/s] or [+12.914%; +13.011%]

scenario:ddsketch_add/add_with_count/clustered_near_zero

  • 🟥 execution_time [+10.260µs; +10.940µs] or [+8.431%; +8.990%]
  • 🟥 throughput [-2784799.309op/s; -2605611.805op/s] or [-8.272%; -7.740%]

scenario:ddsketch_add/add_with_count/large_values

  • 🟥 execution_time [+11.095µs; +11.638µs] or [+9.156%; +9.604%]
  • 🟥 throughput [-2961529.107op/s; -2822385.427op/s] or [-8.761%; -8.349%]

scenario:ddsketch_add/add_with_count/mixed

  • 🟥 execution_time [+9.939µs; +10.509µs] or [+8.114%; +8.579%]
  • 🟥 throughput [-2641450.123op/s; -2495220.713op/s] or [-7.900%; -7.462%]

scenario:ddsketch_encode/encode_to_vec/clustered_near_zero

  • 🟥 execution_time [+52.811ns; +57.625ns] or [+7.611%; +8.305%]

scenario:ddsketch_encode/encode_to_vec/large_values

  • 🟥 execution_time [+66.172ns; +71.085ns] or [+7.879%; +8.464%]

scenario:ddsketch_encode/encode_to_vec/mixed

  • 🟥 execution_time [+74.266ns; +79.353ns] or [+6.041%; +6.455%]

scenario:ddsketch_read/ordered_bins/clustered_near_zero

  • 🟩 execution_time [-280.106ns; -277.263ns] or [-4.884%; -4.835%]

scenario:ddsketch_read/ordered_bins/collapsing

  • 🟩 execution_time [-1.486µs; -1.475µs] or [-5.812%; -5.771%]

scenario:ddsketch_read/ordered_bins/large_values

  • 🟩 execution_time [-414.287ns; -410.192ns] or [-5.622%; -5.567%]

scenario:ddsketch_read/ordered_bins/mixed

  • 🟩 execution_time [-633.201ns; -628.084ns] or [-5.618%; -5.572%]

scenario:msgpack_decoder::v05/low_sharing/2000

  • 🟩 execution_time [-159.252µs; -155.976µs] or [-4.393%; -4.302%]
  • 🟩 throughput [+24814.602op/s; +25340.239op/s] or [+4.498%; +4.594%]

scenario:profile_serialize_compressed_pprof_timestamped_x1000

  • 🟩 execution_time [-53.308µs; -52.374µs] or [-5.401%; -5.306%]

scenario:vec_map/as_deduped_map/already_deduped/16

  • 🟥 execution_time [+1.189ns; +1.236ns] or [+5.189%; +5.393%]

scenario:vec_map/as_deduped_map/already_deduped/8

  • 🟥 execution_time [+1.113ns; +1.156ns] or [+8.346%; +8.666%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_10/128

  • 🟥 execution_time [+3.091µs; +3.093µs] or [+128.693%; +128.769%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_10/16

  • 🟥 execution_time [+391.986ns; +392.315ns] or [+118.489%; +118.588%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_10/64

  • 🟥 execution_time [+1.557µs; +1.559µs] or [+120.699%; +120.814%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_10/8

  • 🟥 execution_time [+171.494ns; +171.618ns] or [+94.489%; +94.557%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_2/128

  • 🟥 execution_time [+4.229µs; +4.232µs] or [+135.791%; +135.876%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_2/16

  • 🟥 execution_time [+515.066ns; +515.407ns] or [+121.010%; +121.091%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_2/64

  • 🟥 execution_time [+2.102µs; +2.104µs] or [+129.470%; +129.578%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_2/8

  • 🟥 execution_time [+238.291ns; +238.473ns] or [+103.805%; +103.884%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_4/128

  • 🟥 execution_time [+3.515µs; +3.517µs] or [+133.746%; +133.826%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_4/16

  • 🟥 execution_time [+429.863ns; +430.185ns] or [+119.820%; +119.910%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_4/64

  • 🟥 execution_time [+1.761µs; +1.762µs] or [+130.194%; +130.301%]

scenario:vec_map/as_deduped_map/needs_dedup_1_in_4/8

  • 🟥 execution_time [+196.299ns; +196.476ns] or [+100.280%; +100.370%]

scenario:vec_map/contains_key/8

  • 🟩 execution_time [-6.970ns; -6.581ns] or [-8.575%; -8.096%]
  • 🟩 throughput [+8681142.491op/s; +9162342.982op/s] or [+8.818%; +9.307%]

scenario:vec_map/dedup/dup_1_in_10/128

  • 🟥 execution_time [+3.312µs; +3.360µs] or [+128.808%; +130.681%]

scenario:vec_map/dedup/dup_1_in_10/16

  • 🟥 execution_time [+238.285ns; +248.787ns] or [+43.745%; +45.673%]

scenario:vec_map/dedup/dup_1_in_10/64

  • 🟥 execution_time [+1.624µs; +1.650µs] or [+115.182%; +117.022%]

scenario:vec_map/dedup/dup_1_in_10/8

  • 🟥 execution_time [+130.303ns; +137.147ns] or [+50.588%; +53.245%]

scenario:vec_map/dedup/dup_1_in_2/128

  • 🟥 execution_time [+4.339µs; +4.391µs] or [+104.614%; +105.873%]

scenario:vec_map/dedup/dup_1_in_2/16

  • 🟥 execution_time [+397.922ns; +410.595ns] or [+56.823%; +58.632%]

scenario:vec_map/dedup/dup_1_in_2/64

  • 🟥 execution_time [+2.108µs; +2.141µs] or [+95.827%; +97.357%]

scenario:vec_map/dedup/dup_1_in_2/8

  • 🟥 execution_time [+195.336ns; +201.508ns] or [+55.373%; +57.123%]

scenario:vec_map/dedup/dup_1_in_4/128

  • 🟥 execution_time [+3.662µs; +3.715µs] or [+114.658%; +116.341%]

scenario:vec_map/dedup/dup_1_in_4/16

  • 🟥 execution_time [+272.982ns; +283.576ns] or [+43.842%; +45.544%]

scenario:vec_map/dedup/dup_1_in_4/64

  • 🟥 execution_time [+1.804µs; +1.833µs] or [+104.646%; +106.329%]

scenario:vec_map/dedup/dup_1_in_4/8

  • 🟥 execution_time [+149.056ns; +154.630ns] or [+49.640%; +51.496%]

scenario:vec_map/dedup/no_duplicates/128

  • 🟥 execution_time [+2.855µs; +2.907µs] or [+134.830%; +137.256%]

scenario:vec_map/dedup/no_duplicates/16

  • 🟥 execution_time [+197.216ns; +204.876ns] or [+41.190%; +42.789%]

scenario:vec_map/dedup/no_duplicates/64

  • 🟥 execution_time [+1.369µs; +1.401µs] or [+116.303%; +119.035%]

scenario:vec_map/dedup/no_duplicates/8

  • 🟥 execution_time [+130.048ns; +134.903ns] or [+59.300%; +61.514%]

scenario:vec_map/get_hit/128

  • 🟩 execution_time [-2.871µs; -2.863µs] or [-17.356%; -17.310%]
  • 🟩 throughput [+1620547.290op/s; +1624912.457op/s] or [+20.939%; +20.996%]

scenario:vec_map/get_hit/16

  • 🟩 execution_time [-14.605ns; -14.291ns] or [-5.839%; -5.713%]
  • 🟩 throughput [+3878338.184op/s; +3966107.434op/s] or [+6.063%; +6.200%]

scenario:vec_map/get_hit/64

  • 🟩 execution_time [-647.350ns; -642.578ns] or [-14.810%; -14.701%]
  • 🟩 throughput [+2524752.824op/s; +2544296.945op/s] or [+17.243%; +17.377%]

scenario:vec_map/get_miss/128

  • 🟥 execution_time [+4.097ns; +4.421ns] or [+5.342%; +5.766%]

scenario:vec_map/get_miss/16

  • 🟩 execution_time [-18.175ns; -17.890ns] or [-66.302%; -65.261%]

scenario:vec_map/get_miss/64

  • 🟩 execution_time [-22.355ns; -22.293ns] or [-43.857%; -43.736%]

scenario:vec_map/get_miss/8

  • 🟩 execution_time [-10.660ns; -10.468ns] or [-58.996%; -57.934%]

scenario:vec_map/get_mut/128

  • 🟩 execution_time [-2.136µs; -2.035µs] or [-13.447%; -12.813%]
  • 🟩 throughput [+1188934.166op/s; +1248803.894op/s] or [+14.749%; +15.491%]

scenario:vec_map/get_mut/16

  • 🟩 execution_time [-31.818ns; -22.260ns] or [-10.498%; -7.345%]
  • 🟩 throughput [+4319656.675op/s; +6318739.264op/s] or [+8.129%; +11.891%]

scenario:vec_map/get_mut/64

  • 🟩 execution_time [-504.029ns; -464.456ns] or [-11.591%; -10.681%]
  • 🟩 throughput [+1771538.443op/s; +1926831.673op/s] or [+12.031%; +13.085%]

Benchmark execution time: 2026-10-14 02:57:27

Comparing candidate commit 3f70e94 in PR branch colin.higgins/thematic-rule-skill with baseline commit 2d7e649 in branch main.

📊 Benchmarking dashboard

Found 24 performance improvements and 36 performance regressions! Performance is the same for 92 metrics, 24 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 ----------------------------------'

scenario:credit_card/is_card_number/ 378282246310005

  • 🟥 execution_time [+5.102µs; +5.186µs] or [+7.496%; +7.619%]
  • 🟥 throughput [-1040025.483op/s; -1024188.566op/s] or [-7.079%; -6.971%]

scenario:credit_card/is_card_number/378282246310005

  • 🟥 execution_time [+5.288µs; +5.351µs] or [+8.157%; +8.254%]
  • 🟥 throughput [-1176120.164op/s; -1163113.692op/s] or [-7.625%; -7.541%]

scenario:credit_card/is_card_number/37828224631000521389798

  • 🟥 execution_time [+7.054µs; +7.123µs] or [+15.689%; +15.841%]
  • 🟥 throughput [-3046074.146op/s; -3012651.291op/s] or [-13.696%; -13.546%]

scenario:credit_card/is_card_number/x371413321323331

  • 🟩 execution_time [-298.627ns; -281.881ns] or [-4.937%; -4.661%]
  • 🟩 throughput [+8103347.740op/s; +8602477.146op/s] or [+4.901%; +5.203%]

scenario:credit_card/is_card_number_no_luhn/ 378282246310005

  • 🟥 execution_time [+4.472µs; +4.507µs] or [+8.412%; +8.479%]
  • 🟥 throughput [-1470580.395op/s; -1459480.741op/s] or [-7.817%; -7.758%]

scenario:credit_card/is_card_number_no_luhn/378282246310005

  • 🟥 execution_time [+4.883µs; +4.917µs] or [+9.780%; +9.848%]
  • 🟥 throughput [-1795544.095op/s; -1783878.713op/s] or [-8.966%; -8.907%]

scenario:credit_card/is_card_number_no_luhn/37828224631000521389798

  • 🟥 execution_time [+6.921µs; +6.989µs] or [+15.352%; +15.503%]
  • 🟥 throughput [-2981808.933op/s; -2948794.353op/s] or [-13.442%; -13.293%]

scenario:credit_card/is_card_number_no_luhn/x371413321323331

  • 🟩 execution_time [-306.109ns; -290.389ns] or [-5.059%; -4.799%]
  • 🟩 throughput [+8350027.420op/s; +8818606.131op/s] or [+5.053%; +5.336%]

scenario:datadog_sample_span/complex_rule_matching/wall_time

  • 🟥 execution_time [+306.044ns; +306.299ns] or [+107.878%; +107.968%]

scenario:datadog_sample_span/complex_rule_partial_match/wall_time

  • 🟥 execution_time [+22.591ns; +22.720ns] or [+10.640%; +10.701%]

scenario:datadog_sample_span/many_attributes_tag_rule/wall_time

  • 🟥 execution_time [+156.159ns; +156.374ns] or [+82.079%; +82.192%]

scenario:datadog_sample_span/multiple_rules_first_match/wall_time

  • 🟥 execution_time [+80.765ns; +80.860ns] or [+101.359%; +101.478%]

scenario:datadog_sample_span/multiple_rules_last_match/wall_time

  • 🟥 execution_time [+28.773ns; +28.877ns] or [+17.173%; +17.235%]

scenario:datadog_sample_span/name_pattern_rule_matching/wall_time

  • 🟥 execution_time [+78.778ns; +78.869ns] or [+44.471%; +44.522%]

scenario:datadog_sample_span/name_pattern_rule_not_matching/wall_time

  • 🟥 execution_time [+25.485ns; +25.584ns] or [+19.241%; +19.316%]

scenario:datadog_sample_span/parent_not_sampled_short_circuit/wall_time

  • 🟥 execution_time [+0.395ns; +0.404ns] or [+4.462%; +4.563%]

scenario:datadog_sample_span/parent_sampled_short_circuit/wall_time

  • 🟥 execution_time [+0.400ns; +0.406ns] or [+4.512%; +4.581%]

scenario:datadog_sample_span/resource_pattern_rule_matching/wall_time

  • 🟥 execution_time [+82.075ns; +82.166ns] or [+46.021%; +46.073%]

scenario:datadog_sample_span/resource_pattern_rule_not_matching/wall_time

  • 🟥 execution_time [+24.945ns; +25.059ns] or [+18.620%; +18.705%]

scenario:datadog_sample_span/root_span_no_rules/wall_time

  • 🟥 execution_time [+27.078ns; +27.169ns] or [+28.143%; +28.237%]

scenario:datadog_sample_span/service_rule_matching/wall_time

  • 🟥 execution_time [+77.489ns; +77.599ns] or [+46.176%; +46.241%]

scenario:datadog_sample_span/service_rule_not_matching/wall_time

  • 🟥 execution_time [+20.500ns; +20.587ns] or [+18.316%; +18.394%]

scenario:datadog_sample_span/tag_rule_matching/wall_time

  • 🟥 execution_time [+159.725ns; +159.951ns] or [+92.000%; +92.131%]

scenario:datadog_sample_span/tag_rule_not_matching/wall_time

  • 🟥 execution_time [+25.856ns; +25.939ns] or [+22.671%; +22.743%]

scenario:datadog_sample_span/unicode_uppercase_service_rule/allocated_bytes

  • 🟥 execution_time [+14.000ns; +14.000ns] or [+107.692%; +107.693%]

scenario:datadog_sample_span/unicode_uppercase_service_rule/wall_time

  • 🟥 execution_time [+75.943ns; +76.138ns] or [+28.829%; +28.903%]

scenario:flagevaluation_evp/coalescer/scale/2500flags_500users_20fields

  • 🟩 execution_time [-25.512ms; -25.483ms] or [-82.586%; -82.494%]
  • 🟩 throughput [+382445.476op/s; +382732.415op/s] or [+472.561%; +472.915%]

scenario:flagevaluation_evp/coalescer/stress/10flags_1000users_250fields

  • 🟩 execution_time [-180.817ms; -180.382ms] or [-95.898%; -95.667%]
  • 🟩 throughput [+120392.890op/s; +120482.534op/s] or [+2269.883%; +2271.573%]

scenario:flagevaluation_evp/coalescer/typical/100flags_50users_10fields

  • 🟩 execution_time [-501.322µs; -500.897µs] or [-73.112%; -73.050%]
  • 🟩 throughput [+395627.752op/s; +396222.133op/s] or [+271.279%; +271.687%]

scenario:flagevaluation_evp/payloads/scale/2500flags_500users_20fields

  • 🟩 execution_time [-11.793ms; -11.756ms] or [-34.643%; -34.533%]
  • 🟩 throughput [+38774.787op/s; +38890.891op/s] or [+52.798%; +52.956%]

scenario:flagevaluation_evp/payloads/stress/10flags_1000users_250fields

  • 🟩 execution_time [-74.178ms; -73.991ms] or [-41.090%; -40.987%]
  • 🟩 throughput [+3848.797op/s; +3862.721op/s] or [+69.480%; +69.731%]

scenario:flagevaluation_evp/payloads/typical/100flags_50users_10fields

  • 🟩 execution_time [-221.585µs; -221.273µs] or [-26.762%; -26.724%]
  • 🟩 throughput [+44057.676op/s; +44122.083op/s] or [+36.479%; +36.533%]

scenario:glob_matcher/ascii_case_insensitive_match/wall_time

  • 🟩 execution_time [-1.440ns; -1.400ns] or [-4.773%; -4.640%]

scenario:glob_matcher/ascii_exact_match/wall_time

  • 🟩 execution_time [-1.449ns; -1.382ns] or [-4.803%; -4.579%]

scenario:glob_matcher/ascii_exact_miss/wall_time

  • 🟩 execution_time [-1.692ns; -1.645ns] or [-11.249%; -10.933%]

scenario:glob_matcher/unicode_pattern_ascii_subject/wall_time

  • 🟩 execution_time [-6.435ns; -6.379ns] or [-6.623%; -6.565%]

scenario:sql/obfuscate_sql_string

  • 🟩 execution_time [-23.753µs; -23.217µs] or [-7.569%; -7.398%]

scenario:thread_cpu/alloc_free/system/16

  • 🟩 execution_time [-0.708ns; -0.645ns] or [-4.551%; -4.144%]

scenario:thread_cpu/alloc_free/system/64

  • 🟩 execution_time [-0.742ns; -0.670ns] or [-4.755%; -4.289%]

scenario:thread_cpu/profiler_attached/fast_path_system/4096

  • 🟩 execution_time [-13.615ns; -13.487ns] or [-12.851%; -12.729%]

scenario:trace_buffer/1_senders/no_delay

  • 🟥 execution_time [+103.109µs; +103.487µs] or [+43.630%; +43.790%]
  • 🟥 throughput [-1160901.137op/s; -1155867.210op/s] or [-30.483%; -30.351%]

scenario:trace_buffer/4_senders/no_delay

  • 🟥 execution_time [+456.730µs; +466.341µs] or [+14.536%; +14.842%]
  • 🟥 throughput [-148411.233op/s; -145194.636op/s] or [-12.952%; -12.671%]

scenario:trace_buffer/8_senders/no_delay

  • 🟥 execution_time [+1.372ms; +1.386ms] or [+24.406%; +24.640%]
  • 🟥 throughput [-253467.223op/s; -250901.727op/s] or [-19.795%; -19.595%]

Unstable benchmarks

These benchmarks have a confidence interval too wide to call a change; treat them as noise rather than signal.

scenario:datadog_sample_span/complex_rule_matching/allocated_bytes

  • unstable execution_time [+330.000ns; +330.000ns] or [-3220085054.665%; -3220086834.765%]

scenario:datadog_sample_span/complex_rule_partial_match/allocated_bytes

  • unstable execution_time [+26.000ns; +26.000ns] or [-346325157.735%; -346326327.592%]

scenario:datadog_sample_span/many_attributes_tag_rule/allocated_bytes

  • unstable execution_time [+295.000ns; +295.000ns] or [-4386378946.011%; -4386380572.118%]

scenario:datadog_sample_span/multiple_rules_first_match/allocated_bytes

  • unstable execution_time [+18.000ns; +18.000ns] or [-638440312.320%; -638442088.394%]

scenario:datadog_sample_span/multiple_rules_last_match/allocated_bytes

  • unstable execution_time [+7.000ns; +7.000ns] or [-110588220.845%; -110589387.336%]

scenario:datadog_sample_span/name_pattern_rule_matching/allocated_bytes

  • unstable execution_time [+13.000ns; +13.000ns] or [-207392009.927%; -207393394.708%]

scenario:datadog_sample_span/name_pattern_rule_not_matching/allocated_bytes

  • unstable execution_time [+26.000ns; +26.000ns] or [-551704339.672%; -551705574.826%]

scenario:datadog_sample_span/parent_not_sampled_short_circuit/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+572.437%; -563.666%]

scenario:datadog_sample_span/parent_sampled_short_circuit/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+573.398%; -564.126%]

scenario:datadog_sample_span/resource_pattern_rule_matching/allocated_bytes

  • unstable execution_time [+13.000ns; +13.000ns] or [-205378502.481%; -205379865.322%]

scenario:datadog_sample_span/resource_pattern_rule_not_matching/allocated_bytes

  • unstable execution_time [+26.000ns; +26.000ns] or [-547677303.838%; -547678527.264%]

scenario:datadog_sample_span/root_span_no_rules/allocated_bytes

  • unstable execution_time [+26.000ns; +26.000ns] or [-769164657.079%; -769165951.222%]

scenario:datadog_sample_span/service_rule_matching/allocated_bytes

  • unstable execution_time [+17.000ns; +17.000ns] or [-287003555.486%; -287004954.713%]

scenario:datadog_sample_span/service_rule_not_matching/allocated_bytes

  • unstable execution_time [+26.000ns; +26.000ns] or [-688623805.157%; -688625067.773%]

scenario:datadog_sample_span/tag_rule_matching/allocated_bytes

  • unstable execution_time [+304.000ns; +304.000ns] or [-4991054985.207%; -4991056691.662%]

scenario:datadog_sample_span/tag_rule_not_matching/allocated_bytes

  • unstable execution_time [+26.000ns; +26.000ns] or [-644326335.933%; -644327582.265%]

scenario:glob_matcher/ascii_case_insensitive_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+542.120%; -549.375%]

scenario:glob_matcher/ascii_exact_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+539.771%; -548.289%]

scenario:glob_matcher/ascii_exact_miss/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+526.733%; -542.315%]

scenario:glob_matcher/ascii_wildcard_backtrack_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+556.511%; -556.100%]

scenario:glob_matcher/ascii_wildcard_heavy_backtrack/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+556.598%; -556.141%]

scenario:glob_matcher/ascii_wildcard_question_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+557.294%; -556.469%]

scenario:glob_matcher/ascii_wildcard_star_match/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+558.084%; -556.842%]

scenario:glob_matcher/star_short_circuit/allocated_bytes

  • unstable execution_time [-0.000ns; +0.000ns] or [+558.753%; -557.158%]

Candidate

Omitted due to size.

Baseline

Omitted due to size.

ast-grep cannot expand macros, so a new c_setters! path produced an
uncontained export with no matching function_item. Also propagate
filtered scan failures and diff github.event.before on push so
origin/main being HEAD does not empty the range.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread .claude/skills/add-lint-rule/SKILL.md Outdated
Comment on lines +142 to +144
If a correct rule would fail on a large, intentional legacy set, do
**not** rewrite the repo and do **not** fall back to regex. Copy the
FFI panic rule:

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.

I disagree with this. If we decide a pattern is harmful and lint against it, we should lint the whole codebase.
It is fine to have escape hatches in the codebase, adding local lint skips in comments but we should not have code that causes lint violations go unnoticed until someone decides to touch it for whatever reason.

I think the pattern for adding lints should probably be stacked PR:

  • One adding skips for parts of the code that would fails
  • A stacked PR on top of this adding the lint in the CI

This ways it's easy to know what code is non compliant, and if the lint actually makes sense to apply to the whole codebase

Comment thread .claude/skills/add-lint-rule/SKILL.md Outdated
Comment on lines +204 to +216
# Format / Clippy (touched crate)
cargo +nightly-2026-07-26 fmt --all -- --check
cargo +stable clippy -p <crate> --all-targets -- -D warnings

# Workspace dependency declarations
(cd .github/actions && cargo run -p workspace-deps-lint)

# Deps / licenses
cargo deny check
cargo machete --with-metadata --skip-target-dir

# Crypto graph
./scripts/check_crypto_providers.sh

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.

these should already be in AGENTS.md so prefer referring to it in the skill. This way we have only one place to maintain

Comment thread scripts/run-ffi-panic-lint.sh Outdated
Comment on lines +220 to +226
alt = "|".join(re.escape(name) for name in sorted(macro_names))
rule = f"""
id: ffi-macro-invocation-emits-extern-c
language: rust
rule:
kind: macro_invocation
regex: "(^|::)({alt})!"

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.

A bash script that contains inline python that contains inline ast-grep rules?? Seems a bit too.. sloppy honestly

Comment thread scripts/run-ffi-panic-lint.sh Outdated
Comment thread .sg/rules/ffi-extern-c-panic-containment.yml Outdated
Comment on lines +21 to +24
ignores:
- "**/tests/**"
- "**/examples/**"
- "symbolizer-ffi/**"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we add datadog-sidecar-ffi/** to ignores? AGENTS.md rules out catch_unwind there, so otherwise it'd need ~140 allow comments.

rule:
all:
- kind: function_item
# `pub(crate)` is not an export. `#[no_mangle]` / `#[export_name]` are,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We've updated to edition 2024 which turned many #[no_mangle] to #[unsafe(no_mangle)]. Does this need to be updated?

@@ -0,0 +1,88 @@
#!/usr/bin/env python3

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What is the intended use of this script? I feel like if we have to add many allow by hand in bulk, something is wrong. Either:

  • we should filter out the file in the job
  • the lint is questionable, because they are many offenders

Ideally exceptions would be rare and should be added manually so that it's conscious.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

A few ways to tackle this, if we decide a rule is worthwhile and want to start enforcing it:

  • Start with warnings and tackle them bit by bit
  • Fix all of them in the PR which introduces the rule
  • Add exceptions, and use that as the TODO list

I'm okay with any of them, but I think picking one as a policy is important.

This branch has not been deployed

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants