feat(traces): introduce DD_TRACE_FILTERING_RULES - #19851
Conversation
Codeowners resolved asResolved from the full PR diff against |
Dependency direction analysis📈 Existing violations got worse31 pre-existing violation(s) increased in severity (e.g. their target became more depended-on, or got pulled into an import cycle), though the edge itself isn't new: Show violations that got worse (showing 5 of 31 highest severity)
|
Circular import analysis
|
|
2929906 to
cf6fa36
Compare
BenchmarksBenchmark execution time: 2026-08-27 16:12:44 Comparing candidate commit f47854f in PR branch Found 0 performance improvements and 6 performance regressions! Performance is the same for 580 metrics, 10 unstable metrics, 18 flaky benchmarks without significant changes.
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 01a70924b4
ℹ️ 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".
| rule_kwargs = dict(rule) | ||
| filter_rate = rule_kwargs.pop("filter_rate", 1.0) | ||
| filtering_rules.append(FilterRule(filter_rate=filter_rate, **rule_kwargs)) | ||
| except (JSONDecodeError, ValueError, TypeError): |
There was a problem hiding this comment.
Handle malformed rule fields without aborting startup
When DD_TRACE_FILTERING_RULES contains valid JSON but a field has the wrong shape—for example, [{"tags":["x"]}]—SamplingRule.__init__ calls tags.items() and raises AttributeError, which this handler does not catch. Since SpanAggregator.__init__ parses these rules while the global tracer is constructed, such a configuration prevents ddtrace.trace from importing instead of logging and disabling the invalid rules.
Useful? React with 👍 / 👎.
| """ | ||
| Definition of a filtering rule used to fully drop trace chunks matching a pattern. | ||
|
|
||
| Reuses :class:`SamplingRule`'s glob matching and probability handling. |
There was a problem hiding this comment.
Use plain prose in this private docstring
This module is private and is not rendered by Sphinx, but the new docstring uses the reStructuredText :class: role. The repository convention requires non-rendered private docstrings to use plain editor-readable prose without rST inline markup, so this should refer to SamplingRule directly.
AGENTS.md reference: AGENTS.md:L43-L50
Useful? React with 👍 / 👎.
| if not trace or not self.filtering_rules: | ||
| return trace | ||
| chunk_root = trace[0] | ||
| matched_rule = _get_highest_precedence_rule_matching(chunk_root._local_root, self.filtering_rules) |
There was a problem hiding this comment.
Prevent partial flushes from bypassing final-root filters
With partial flushing enabled by default, a trace can export one or more child-span chunks while its local root is still unfinished, so matching here observes incomplete root metadata. For example, Django assigns the request's resolved resource later in ddtrace/contrib/internal/django/utils.py:237-241; if 300 child spans finish first, a rule for that resource passes the early chunk and only drops the final root chunk. The resulting trace is therefore still partially sent to the Agent and included in metrics despite the documented full-drop behavior.
Useful? React with 👍 / 👎.
| # perf: Process spans outside of the span aggregator lock | ||
| spans = finished | ||
| for tp in chain( | ||
| [self.filtering_processor], |
There was a problem hiding this comment.
Route LLMObs events before discarding matching traces
When LLMObs is enabled and a filtering rule matches a trace containing an LLM span, this processor returns None and breaks the chain before self.llmobs_processor runs. LLMObsProcessor.process_trace in ddtrace/llmobs/_processor.py:47-97 is the sole owner that either leaves the event on a transmitted APM trace or enqueues it to the LLMObs writer; here the APM trace is discarded and the fallback enqueue never occurs, so the LLMObs event is lost entirely.
Useful? React with 👍 / 👎.
This works just like sampling rules, serving as a way to fully drop a trace, but does not sample it.
01a7092 to
f47854f
Compare
This works just like sampling rules, serving as a way to fully drop a trace, but does not sample it.