Repository: DataDog/dd-trace-js
Pull request #5392: Adds JSDoc types to much of the sampling code
Author: login: bm1549
Labels: name: semver-patch
Created: 2025-03-11T16:19:53Z | Merged: 2025-03-13T15:29:30Z

### What does this PR do?
<!-- A brief description of the change being made with this pull request. -->
Adds JSDoc types to the sampling code so that it's easier to work in

### Motivation
<!-- What inspired you to submit this pull request? -->
I was investigating how we could support Knuth-method sampling in #5386 and split this PR out from it

### Plugin Checklist
<!-- Fill this section if adding or updating a plugin. Remove otherwise. -->

- [ ] Unit tests.
- [ ] TypeScript [definitions][1].
- [ ] TypeScript [tests][2].
- [ ] API [documentation][3].
- [ ] CircleCI [jobs/workflows][4].
- [ ] Plugin is [exported][5].

[1]: https://github.com/DataDog/dd-trace-js/blob/master/index.d.ts
[2]: https://github.com/DataDog/dd-trace-js/blob/master/docs/test.ts
[3]: https://github.com/DataDog/documentation/blob/master/content/en/tracing/trace_collection/library_config/nodejs.md
[4]: https://github.com/DataDog/dd-trace-js/blob/master/.circleci/config.yml
[5]: https://github.com/DataDog/dd-trace-js/blob/master/packages/dd-trace/src/plugins/index.js

### Additional Notes
<!-- Anything else we should know when reviewing? -->





Diff:
diff --git a/packages/dd-trace/src/appsec/api_security_sampler.js b/packages/dd-trace/src/appsec/api_security_sampler.js
index 1e15b67a26..7da5f73f8b 100644
--- a/packages/dd-trace/src/appsec/api_security_sampler.js
+++ b/packages/dd-trace/src/appsec/api_security_sampler.js
@@ -8,12 +8,16 @@ const { AUTO_REJECT, USER_REJECT } = require('../../../../ext/priority')
 const MAX_SIZE = 4096
 
 let enabled
+
+/**
+ * @type {TTLCache}
+ */
 let sampledRequests
 
 class NoopTTLCache {
   clear () { }
-  set (key) { return undefined }
-  has (key) { return false }
+  set (_key, _value) { return undefined }
+  has (_key) { return false }
 }
 
 function configure ({ apiSecurity }) {
@@ -48,7 +52,7 @@ function sampleRequest (req, res, force = false) {
   }
 
   if (force) {
-    sampledRequests.set(key)
+    sampledRequests.set(key, undefined)
   }
 
   return true
diff --git a/packages/dd-trace/src/opentracing/span.js b/packages/dd-trace/src/opentracing/span.js
index 1d55bab2ae..6ab2c7416c 100644
--- a/packages/dd-trace/src/opentracing/span.js
+++ b/packages/dd-trace/src/opentracing/span.js
@@ -143,6 +143,9 @@ class DatadogSpan {
     return `Span${json}`
   }
 
+  /**
+   * @returns {DatadogSpanContext}
+   */
   context () {
     return this._spanContext
   }
diff --git a/packages/dd-trace/src/priority_sampler.js b/packages/dd-trace/src/priority_sampler.js
index 3345fd7d6a..99b6a41395 100644
--- a/packages/dd-trace/src/priority_sampler.js
+++ b/packages/dd-trace/src/priority_sampler.js
@@ -39,28 +39,54 @@ const DEFAULT_KEY = 'service:,env:'
 
 const defaultSampler = new Sampler(AUTO_KEEP)
 
+/**
+ * from config.js
+ * @typedef { sampleRate: number, provenance: string, rateLimit: number, rules: SamplingRule[] } SamplingConfig
+ *
+ * empirically defined
+ * @typedef {2|-1|1|0} SamplingPriority
+ */
 class PrioritySampler {
+  /**
+   * @param env {string}
+   * @param config {SamplingConfig}
+   */
   constructor (env, config) {
     this.configure(env, config)
     this.update({})
   }
 
+  /**
+   *
+   * @param env {string}
+   * @param opts {SamplingConfig}
+   */
   configure (env, opts = {}) {
     const { sampleRate, provenance = undefined, rateLimit = 100, rules = [] } = opts
     this._env = env
-    this._rules = this._normalizeRules(rules, sampleRate, rateLimit, provenance)
+    this._rules = this.#_normalizeRules(rules, sampleRate, rateLimit, provenance)
     this._limiter = new RateLimiter(rateLimit)
 
     log.trace(env, opts)
     setSamplingRules(this._rules)
   }
 
+  /**
+   * @param span {DatadogSpan}
+   * @returns {boolean}
+   */
   isSampled (span) {
     const priority = this._getPriorityFromAuto(span)
     log.trace(span)
     return priority === USER_KEEP || priority === AUTO_KEEP
   }
 
+  /**
+   *
+   * @param span {DatadogSpan}
+   * @param auto {boolean}
+   * @returns {void}
+   */
   sample (span, auto = true) {
     if (!span) return
 
@@ -84,17 +110,20 @@ class PrioritySampler {
       return
     }
 
-    this._addDecisionMaker(root)
+    this.#_addDecisionMaker(root)
   }
 
+  /**
+   *
+   * @param rates {Record<string, number>}
+   * @returns {void}
+   */
   update (rates) {
     const samplers = {}
 
     for (const key in rates) {
       const rate = rates[key]
-      const sampler = new Sampler(rate)
-
-      samplers[key] = sampler
+      samplers[key] = new Sampler(rate)
     }
 
     samplers[DEFAULT_KEY] = samplers[DEFAULT_KEY] || defaultSampler
@@ -104,6 +133,11 @@ class PrioritySampler {
     log.trace(rates)
   }
 
+  /**
+   *
+   * @param samplingPriority {SamplingPriority}
+   * @returns {boolean}
+   */
   validate (samplingPriority) {
     switch (samplingPriority) {
       case USER_REJECT:
@@ -116,6 +150,12 @@ class PrioritySampler {
     }
   }
 
+  /**
+   *
+   * @param span {DatadogSpan}
+   * @param samplingPriority {SamplingPriority}
+   * @param product {import('./standalone/product').PRODUCTS}
+   */
   setPriority (span, samplingPriority, product) {
     if (!span || !this.validate(samplingPriority)) return
 
@@ -134,23 +174,40 @@ class PrioritySampler {
 
     log.trace(span, samplingPriority, mechanism)
 
-    this._addDecisionMaker(root)
+    this.#_addDecisionMaker(root)
   }
 
+  /**
+   *
+   * @param span {DatadogSpan}
+   * @returns {DatadogSpanContext}
+   */
   _getContext (span) {
     return typeof span.context === 'function' ? span.context() : span
   }
 
+  /**
+   *
+   * @param span {DatadogSpan}
+   * @returns {SamplingPriority}
+   */
   _getPriorityFromAuto (span) {
     const context = this._getContext(span)
-    const rule = this._findRule(span)
+    const rule = this.#_findRule(span)
 
     return rule
-      ? this._getPriorityByRule(context, rule)
-      : this._getPriorityByAgent(context)
+      ? this.#_getPriorityByRule(context, rule)
+      : this.#_getPriorityByAgent(context)
   }
 
-  _getPriorityFromTags (tags) {
+  /**
+   *
+   * @param tags {Record<string, symbol | unknown>}
+   * Included for compatibility with {@link import('./standalone/tracesource_priority_sampler')._getPriorityFromTags}
+   * @param _context {DatadogSpanContext}
+   * @returns {SamplingPriority}
+   */
+  _getPriorityFromTags (tags, _context) {
     if (hasOwn(tags, MANUAL_KEEP) && tags[MANUAL_KEEP] !== false) {
       return USER_KEEP
     } else if (hasOwn(tags, MANUAL_DROP) && tags[MANUAL_DROP] !== false) {
@@ -166,7 +223,13 @@ class PrioritySampler {
     }
   }
 
-  _getPriorityByRule (context, rule) {
+  /**
+   *
+   * @param context {DatadogSpanContext}
+   * @param rule {SamplingRule}
+   * @returns {SamplingPriority}
+   */
+  #_getPriorityByRule (context, rule) {
     context._trace[SAMPLING_RULE_DECISION] = rule.sampleRate
     context._sampling.mechanism = SAMPLING_MECHANISM_RULE
     if (rule.provenance === 'customer') context._sampling.mechanism = SAMPLING_MECHANISM_REMOTE_USER
@@ -177,6 +240,12 @@ class PrioritySampler {
       : USER_REJECT
   }
 
+  /**
+   *
+   * @param context {DatadogSpanContext}
+   * @returns {boolean}
+   * @private
+   */
   _isSampledByRateLimit (context) {
     const allowed = this._limiter.isAllowed()
 
@@ -185,7 +254,13 @@ class PrioritySampler {
     return allowed
   }
 
-  _getPriorityByAgent (context) {
+  /**
+   *
+   * @param context {DatadogSpanContext}
+   * @returns {SamplingPriority}
+   * @private
+   */
+  #_getPriorityByAgent (context) {
     const key = `service:${context._tags[SERVICE_NAME]},env:${this._env}`
     const sampler = this._samplers[key] || this._samplers[DEFAULT_KEY]
 
@@ -200,7 +275,13 @@ class PrioritySampler {
     return sampler.isSampled(context) ? AUTO_KEEP : AUTO_REJECT
   }
 
-  _addDecisionMaker (span) {
+  /**
+   *
+   * @param span {DatadogSpan}
+   * @private
+   * @returns {void}
+   */
+  #_addDecisionMaker (span) {
     const context = span.context()
     const trace = context._trace
     const priority = context._sampling.priority
@@ -215,7 +296,16 @@ class PrioritySampler {
     }
   }
 
-  _normalizeRules (rules, sampleRate, rateLimit, provenance) {
+  /**
+   *
+   * @param rules {SamplingRule[]}
+   * @param sampleRate {number}
+   * @param rateLimit {number}
+   * @param provenance {string}
+   * @returns {SamplingRule[]}
+   * @private
+   */
+  #_normalizeRules (rules, sampleRate, rateLimit, provenance) {
     rules = [].concat(rules || [])
 
     return rules
@@ -225,12 +315,23 @@ class PrioritySampler {
       .map(SamplingRule.from)
   }
 
-  _findRule (span) {
+  /**
+   *
+   * @param span {DatadogSpan}
+   * @returns {SamplingRule}
+   * @private
+   */
+  #_findRule (span) {
     for (const rule of this._rules) {
       if (rule.match(span)) return rule
     }
   }
 
+  /**
+   *
+   * @param span {DatadogSpan}
+   * @param product {import('./standalone/product').PRODUCTS}
+   */
   static keepTrace (span, product) {
     span?._prioritySampler?.setPriority(span, USER_KEEP, product)
   }
diff --git a/packages/dd-trace/src/sampler.js b/packages/dd-trace/src/sampler.js
index 40fe6980d6..c7525f637a 100644
--- a/packages/dd-trace/src/sampler.js
+++ b/packages/dd-trace/src/sampler.js
@@ -1,14 +1,23 @@
 'use strict'
 
 class Sampler {
+  /**
+   * @param rate {number}
+   */
   constructor (rate) {
     this._rate = rate
   }
 
+  /**
+   * @returns {number}
+   */
   rate () {
     return this._rate
   }
 
+  /**
+   * @returns {boolean}
+   */
   isSampled () {
     return this._rate === 1 || Math.random() < this._rate
   }
diff --git a/packages/dd-trace/src/standalone/product.js b/packages/dd-trace/src/standalone/product.js
index 283cea8c2b..522057c855 100644
--- a/packages/dd-trace/src/standalone/product.js
+++ b/packages/dd-trace/src/standalone/product.js
@@ -13,12 +13,16 @@ function getProductRateLimiter (config) {
   return dropAll
 }
 
-module.exports = {
+const PRODUCTS = {
   APM: { id: 1 << 0 },
   ASM: { id: 1 << 1, mechanism: SAMPLING_MECHANISM_APPSEC },
   DSM: { id: 1 << 2 },
   DJM: { id: 1 << 3 },
-  DBM: { id: 1 << 4 },
+  DBM: { id: 1 << 4 }
+}
+
+module.exports = {
+  ...PRODUCTS,
 
   getProductRateLimiter
 }


Reviews:
user: login: bm1549
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-11T16:25:20Z
user: login: BridgeAR
body: LGTM

One suggestion: instead of directly writing JSDoc, we could also write TS documentation in a separate file for each class and then just mark the class that is implements the interface. That way we can be more specific about types than it's possible with JSDoc.
state: DISMISSED
author_association: MEMBER
submitted_at: 2025-03-12T14:17:06Z
user: login: bm1549
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T14:55:21Z
user: login: bm1549
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T14:56:44Z
user: login: bm1549
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T14:58:19Z
user: login: BridgeAR
body: LGTM! Just left a nit. Feel free to ignore it.
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-13T00:53:23Z
user: login: simon-id
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-13T14:22:59Z
user: login: rochdev
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-14T15:45:07Z

Review comments:
diff_hunk: @@ -48,7 +52,7 @@ function sampleRequest (req, res, force = false) {
   }
 
   if (force) {
-    sampledRequests.set(key)
+    sampledRequests.set(key, undefined)
path: packages/dd-trace/src/appsec/api_security_sampler.js
user: login: bm1549
body: The cache we use requires a key and value for `set` since the underlying data structure is a `Map`. Since the default param value is `undefined` this should be equivalent while also providing better type checks

[docs](https://github.com/isaacs/ttlcache?tab=readme-ov-file#cachesetkey-value--ttl-noupdatettl-nodisposeonset---)
created_at: 2025-03-11T16:24:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -13,12 +13,16 @@ function getProductRateLimiter (config) {
   return dropAll
 }
 
-module.exports = {
+const PRODUCTS = {
path: packages/dd-trace/src/standalone/product.js
user: login: bm1549
body: Updated the export so I could use this in typing above
created_at: 2025-03-11T16:25:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -39,12 +39,28 @@ const DEFAULT_KEY = 'service:,env:'
 
 const defaultSampler = new Sampler(AUTO_KEEP)
 
+/**
+ * from config.js
+ * @typedef { sampleRate: number, provenance: string, rateLimit: number, rules: SamplingRule[] } SamplingConfig
+ *
+ * empirically defined
+ * @typedef {2|-1|1|0} SamplingPriority
+ */
 class PrioritySampler {
+  /**
+   * @param env {string}
path: packages/dd-trace/src/priority_sampler.js
user: login: BridgeAR
body: Nit: Would you mind renaming this to `environment`? I feel we could generally use less short versions to make things more explicit :)
created_at: 2025-03-12T14:10:11Z
author_association: MEMBER
diff_hunk: @@ -150,7 +202,15 @@ class PrioritySampler {
       : this._getPriorityByAgent(context)
   }
 
-  _getPriorityFromTags (tags) {
+  /**
+   *
+   * @param tags {Map<string, Object>}
path: packages/dd-trace/src/priority_sampler.js
user: login: BridgeAR
body: I don't know exactly what JSDoc refers to when it being an Object but at least in TS it's not ideal to use. Should we use something like `Record<string | symbol, unknown>`?
created_at: 2025-03-12T14:12:56Z
author_association: MEMBER
diff_hunk: @@ -166,6 +226,13 @@ class PrioritySampler {
     }
   }
 
+  /**
+   *
+   * @param context {DatadogSpanContext}
+   * @param rule {SamplingRule}
+   * @returns {SamplingPriority}
+   * @private
path: packages/dd-trace/src/priority_sampler.js
user: login: BridgeAR
body: Instead of marking something as private, should we not just use a proper private JS property (`#privateProperty`), if it is not currently somewhere "misused" internally? :)
created_at: 2025-03-12T14:14:19Z
author_association: MEMBER
diff_hunk: @@ -39,12 +39,28 @@ const DEFAULT_KEY = 'service:,env:'
 
 const defaultSampler = new Sampler(AUTO_KEEP)
 
+/**
+ * from config.js
+ * @typedef { sampleRate: number, provenance: string, rateLimit: number, rules: SamplingRule[] } SamplingConfig
+ *
+ * empirically defined
+ * @typedef {2|-1|1|0} SamplingPriority
+ */
 class PrioritySampler {
+  /**
+   * @param env {string}
path: packages/dd-trace/src/priority_sampler.js
user: login: bm1549
body: Usually I'd agree, but `env` is a standard across all of Datadog ([src](https://docs.datadoghq.com/getting_started/tagging/unified_service_tagging/?tab=kubernetes)) so it's more understandable in its short-form
created_at: 2025-03-12T14:55:21Z
author_association: CONTRIBUTOR
diff_hunk: @@ -150,7 +202,15 @@ class PrioritySampler {
       : this._getPriorityByAgent(context)
   }
 
-  _getPriorityFromTags (tags) {
+  /**
+   *
+   * @param tags {Map<string, Object>}
path: packages/dd-trace/src/priority_sampler.js
user: login: bm1549
body: `Object` means it could be anything - I'll switch to your suggestion
created_at: 2025-03-12T14:56:44Z
author_association: CONTRIBUTOR
diff_hunk: @@ -166,6 +226,13 @@ class PrioritySampler {
     }
   }
 
+  /**
+   *
+   * @param context {DatadogSpanContext}
+   * @param rule {SamplingRule}
+   * @returns {SamplingPriority}
+   * @private
path: packages/dd-trace/src/priority_sampler.js
user: login: bm1549
body: Unfortunately we've already broken this by calling it [here](https://github.com/DataDog/dd-trace-js/blob/d88b6625a6ada85334b8585d302083084dabecf6/packages/dd-trace/test/standalone/tracesource_priority_sampler.spec.js#L51)

I can remove the `@private` declaration
created_at: 2025-03-12T14:58:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -166,7 +223,13 @@ class PrioritySampler {
     }
   }
 
-  _getPriorityByRule (context, rule) {
+  /**
+   *
+   * @param context {DatadogSpanContext}
+   * @param rule {SamplingRule}
+   * @returns {SamplingPriority}
+   */
+  #_getPriorityByRule (context, rule) {
path: packages/dd-trace/src/priority_sampler.js
user: login: BridgeAR
body: ```suggestion
  #getPriorityByRule (context, rule) {
```
created_at: 2025-03-13T00:48:20Z
author_association: MEMBER
diff_hunk: @@ -185,7 +254,13 @@ class PrioritySampler {
     return allowed
   }
 
-  _getPriorityByAgent (context) {
+  /**
+   *
+   * @param context {DatadogSpanContext}
+   * @returns {SamplingPriority}
+   * @private
+   */
+  #_getPriorityByAgent (context) {
path: packages/dd-trace/src/priority_sampler.js
user: login: BridgeAR
body: ```suggestion
  #getPriorityByAgent (context) {
```

And also the other entries :)

The underscore is a legacy way where private properties didn't exist to "mark" something as "internal".
created_at: 2025-03-13T00:48:34Z
author_association: MEMBER
path: packages/dd-trace/src/priority_sampler.js
user: login: simon-id
body: not a hard blocker, but it would be interesting to ask roch or bryan, in case some people already use our private fields in the wild, and if this is going to break them. I know it's not a breaking change since it's not part of the public API, but you never know
created_at: 2025-03-13T14:22:59Z
author_association: MEMBER
path: packages/dd-trace/src/priority_sampler.js
user: login: rochdev
body: I'm not too worried about the sampler internal APIs being used in the wild. Most usage I've seen of private properties is on `span.context()`.
created_at: 2025-03-14T15:45:07Z
author_association: MEMBER

PR comments:
user: login: github-actions[bot]
created_at: 2025-03-11T16:20:59Z
body: 
# Overall package size

Self size: 8.96 MB
Deduped: 101.49 MB
No deduping: 102.01 MB

<details><summary>Dependency sizes</summary>
| name | version | self size | total size |
|------|---------|-----------|------------|
| @datadog/libdatadog | 0.5.0 | 29.83 MB | 29.83 MB |
| @datadog/native-appsec | 8.5.0 | 19.26 MB | 19.26 MB |
| @datadog/native-iast-taint-tracking | 3.3.0 | 13.77 MB | 13.78 MB |
| @datadog/pprof | 5.5.1 | 9.79 MB | 10.17 MB |
| @opentelemetry/core | 1.30.1 | 908.66 kB | 7.16 MB |
| protobufjs | 7.4.0 | 2.77 MB | 5.42 MB |
| @datadog/native-iast-rewriter | 2.8.0 | 2.6 MB | 2.74 MB |
| @datadog/native-metrics | 3.1.0 | 1.06 MB | 1.46 MB |
| @opentelemetry/api | 1.8.0 | 1.21 MB | 1.21 MB |
| import-in-the-middle | 1.13.1 | 117.64 kB | 839.26 kB |
| source-map | 0.7.4 | 226 kB | 226 kB |
| opentracing | 0.14.7 | 194.81 kB | 194.81 kB |
| lru-cache | 7.18.3 | 133.92 kB | 133.92 kB |
| pprof-format | 2.1.0 | 111.69 kB | 111.69 kB |
| @datadog/sketches-js | 2.1.1 | 109.9 kB | 109.9 kB |
| lodash.sortby | 4.7.0 | 75.76 kB | 75.76 kB |
| ignore | 5.3.2 | 53.63 kB | 53.63 kB |
| istanbul-lib-coverage | 3.2.0 | 29.34 kB | 29.34 kB |
| rfdc | 1.4.1 | 27.15 kB | 27.15 kB |
| @isaacs/ttlcache | 1.4.1 | 25.2 kB | 25.2 kB |
| tlhunter-sorted-set | 0.1.0 | 24.94 kB | 24.94 kB |
| dc-polyfill | 0.1.6 | 24.56 kB | 24.56 kB |
| shell-quote | 1.8.2 | 23.54 kB | 23.54 kB |
| limiter | 1.1.5 | 23.17 kB | 23.17 kB |
| retry | 0.13.1 | 18.85 kB | 18.85 kB |
| semifies | 1.0.0 | 15.84 kB | 15.84 kB |
| jest-docblock | 29.7.0 | 8.99 kB | 12.76 kB |
| crypto-randomuuid | 1.0.0 | 11.18 kB | 11.18 kB |
| ttl-set | 1.0.0 | 4.61 kB | 9.69 kB |
| path-to-regexp | 0.1.12 | 6.6 kB | 6.6 kB |
| koalas | 1.0.2 | 6.47 kB | 6.47 kB |
| module-details-from-path | 1.0.3 | 4.47 kB | 4.47 kB |


</details>



<sub>🤖 This report was automatically generated by [heaviest-objects-in-the-universe](https://github.com/qard/heaviest-objects-in-the-universe/)<sub>
author_association: CONTRIBUTOR
user: login: codecov[bot]
created_at: 2025-03-11T16:21:36Z
body: ## [Codecov](https://app.codecov.io/gh/DataDog/dd-trace-js/pull/5392?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=DataDog) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 80.70%. Comparing base [(`1206bdc`)](https://app.codecov.io/gh/DataDog/dd-trace-js/commit/1206bdc9837ce1a4f2b38cde99df91f123959825?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=DataDog) to head [(`f924918`)](https://app.codecov.io/gh/DataDog/dd-trace-js/commit/f9249189ad3ba19b80ac0c0ff435646738f513b6?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=DataDog).
> Report is 1 commits behind head on master.

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##           master    #5392   +/-   ##
=======================================
  Coverage   80.70%   80.70%           
=======================================
  Files         493      493           
  Lines       22125    22125           
=======================================
  Hits        17857    17857           
  Misses       4268     4268           
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/DataDog/dd-trace-js/pull/5392?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=DataDog).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=DataDog).

<details><summary>🚀 New features to boost your workflow: </summary>

- ❄ [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- 📦 [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: datadog-datadog-prod-us1[bot]
created_at: 2025-03-11T16:28:06Z
body: 
## Datadog Report

Branch report: [`brian.marks/js-docs`](https://app.datadoghq.com/ci/test-branch/github.com%2FDataDog%2Fdd-trace-js/dd-trace-js-integration-tests/brian.marks%2Fjs-docs?env=none&index=citest&_user_click_origin_=github)
Commit report: [`8aa0239`](https://app.datadoghq.com/ci/test-commit/github.com%2FDataDog%2Fdd-trace-js/dd-trace-js-integration-tests/brian.marks%2Fjs-docs/8aa0239cd17e28b4a165ce100ba1d0a7db234d06?env=none&index=citest&_user_click_origin_=github)
Test service: `dd-trace-js-integration-tests`

:white_check_mark: 0 Failed, 804 Passed, 0 Skipped, 17m 9.54s Total Time




author_association: NONE
user: login: pr-commenter[bot]
created_at: 2025-03-11T16:30:18Z
body: ## Benchmarks

Benchmark execution time: 2025-03-13 15:25:31

Comparing candidate commit f9249189ad3ba19b80ac0c0ff435646738f513b6 in PR branch `brian.marks/js-docs` with baseline commit 1206bdc9837ce1a4f2b38cde99df91f123959825 in branch `master`.

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


author_association: NONE