Skip to content

Commit

Permalink
Merge branch 'christophe-papazian/APPSEC-53571_ATO_update_local_confi…
Browse files Browse the repository at this point in the history
…g' of ssh://github.com/DataDog/dd-trace-py into christophe-papazian/APPSEC-53571_ATO_update_local_config
  • Loading branch information
christophe-papazian committed Jun 19, 2024
2 parents 5938c0d + f6fc845 commit f982b2b
Show file tree
Hide file tree
Showing 24 changed files with 4,219 additions and 143 deletions.
7 changes: 6 additions & 1 deletion ddtrace/contrib/celery/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,12 @@ def trace_failure(*args, **kwargs):
if isinstance(original_exception, task.throws):
return

span.set_exc_info(ex.type, ex.exception, ex.tb)
# ensure we are getting the actual exception class which stores the exception message
exc = ex.exception
if hasattr(exc, "exc"):
exc = exc.exc

span.set_exc_info(ex.type, exc, ex.tb)


def trace_retry(*args, **kwargs):
Expand Down
14 changes: 0 additions & 14 deletions ddtrace/internal/sampling.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
from ddtrace.constants import _SINGLE_SPAN_SAMPLING_MECHANISM
from ddtrace.constants import _SINGLE_SPAN_SAMPLING_RATE
from ddtrace.constants import SAMPLING_AGENT_DECISION
from ddtrace.constants import SAMPLING_LIMIT_DECISION
from ddtrace.constants import SAMPLING_RULE_DECISION
from ddtrace.constants import USER_REJECT
from ddtrace.internal.constants import _CATEGORY_TO_PRIORITIES
from ddtrace.internal.constants import _KEEP_PRIORITY_INDEX
from ddtrace.internal.constants import _REJECT_PRIORITY_INDEX
Expand Down Expand Up @@ -306,18 +304,6 @@ def _set_sampling_tags(span, sampled, sample_rate, priority_category):
set_sampling_decision_maker(span.context, mechanism)


def _apply_rate_limit(span, sampled, limiter):
# type: (Span, bool, RateLimiter) -> bool
allowed = True
if sampled:
allowed = limiter.is_allowed()
if not allowed:
_set_priority(span, USER_REJECT)
if limiter._has_been_configured:
span.set_metric(SAMPLING_LIMIT_DECISION, limiter.effective_rate)
return allowed


def _set_priority(span, priority):
# type: (Span, int) -> None
span.context.sampling_priority = priority
Expand Down
14 changes: 11 additions & 3 deletions ddtrace/sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@
from typing import Optional # noqa:F401
from typing import Tuple # noqa:F401

from ddtrace.constants import SAMPLING_LIMIT_DECISION

from .constants import ENV_KEY
from .internal.constants import _PRIORITY_CATEGORY
from .internal.constants import DEFAULT_SAMPLING_RATE_LIMIT
from .internal.constants import MAX_UINT_64BITS as _MAX_UINT_64BITS
from .internal.logger import get_logger
from .internal.rate_limiter import RateLimiter
from .internal.sampling import _apply_rate_limit
from .internal.sampling import _get_highest_precedence_rule_matching
from .internal.sampling import _set_sampling_tags
from .sampling_rule import SamplingRule
Expand Down Expand Up @@ -318,16 +319,20 @@ def sample(self, span):
sampled, sampler = super(DatadogSampler, self)._make_sampling_decision(span)
if isinstance(sampler, RateSampler):
sample_rate = sampler.sample_rate
# Apply rate limit
if sampled:
sampled = self.limiter.is_allowed()
if self.limiter._has_been_configured:
span.set_metric(SAMPLING_LIMIT_DECISION, self.limiter.effective_rate)

_set_sampling_tags(
span,
sampled,
sample_rate,
self._choose_priority_category_with_rule(matched_rule, sampler),
)
cleared_rate_limit = _apply_rate_limit(span, sampled, self.limiter)

return cleared_rate_limit and sampled
return sampled

def _choose_priority_category_with_rule(self, rule, sampler):
# type: (Optional[SamplingRule], BaseSampler) -> str
Expand All @@ -340,5 +345,8 @@ def _choose_priority_category_with_rule(self, rule, sampler):
return _PRIORITY_CATEGORY.RULE_DEF

if self.limiter._has_been_configured:
# If the default rate limiter is NOT used to sample traces
# the sampling priority must be set to manual keep/drop.
# This will disable agent based sample rates.
return _PRIORITY_CATEGORY.USER
return super(DatadogSampler, self)._choose_priority_category(sampler)
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ services:
environment:
- LOG_LEVEL=WARNING
- SNAPSHOT_DIR=/snapshots
- SNAPSHOT_CI
- SNAPSHOT_CI=0
- DD_POOL_TRACE_CHECK_FAILURES=true
- DD_DISABLE_ERROR_RESPONSES=true
- ENABLED_CHECKS=trace_content_length,trace_stall,meta_tracer_version_header,trace_count_header,trace_peer_service,trace_dd_service
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
fixes:
- |
celery: changes ``error.message`` span tag to no longer include the traceback that is already included in the ``error.stack`` span tag.
4 changes: 2 additions & 2 deletions tests/contrib/celery/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ def fn_exception():
assert span.error == 1
assert span.get_tag("component") == "celery"
assert span.get_tag("span.kind") == "consumer"
assert "Task class is failing" in span.get_tag(ERROR_MSG)
assert span.get_tag(ERROR_MSG) == "Task class is failing"
assert "Traceback (most recent call last)" in span.get_tag("error.stack")
assert "Task class is failing" in span.get_tag("error.stack")

Expand Down Expand Up @@ -403,7 +403,7 @@ def run(self):
assert span.get_tag("celery.state") == "FAILURE"
assert span.error == 1
assert span.get_tag("component") == "celery"
assert "Task class is failing" in span.get_tag(ERROR_MSG)
assert span.get_tag(ERROR_MSG) == "Task class is failing"
assert "Traceback (most recent call last)" in span.get_tag("error.stack")
assert "Task class is failing" in span.get_tag("error.stack")
assert span.get_tag("span.kind") == "consumer"
Expand Down
26 changes: 7 additions & 19 deletions tests/integration/test_trace_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,10 @@


@pytest.fixture
def sample_rate():
# type: () -> Generator[float, None, None]
# Default the sample rate to 0 so no traces are sent for requests.
yield 0.0


@pytest.fixture
def stats_tracer(sample_rate):
def stats_tracer():
# type: (float) -> Generator[Tracer, None, None]
with override_global_config(dict(_trace_compute_stats=True)):
tracer = Tracer()
tracer.configure(
sampler=DatadogSampler(
default_sample_rate=sample_rate,
)
)
yield tracer
tracer.shutdown()

Expand Down Expand Up @@ -176,22 +164,22 @@ def test_sampling_rate(stats_tracer, sample_rate):


@pytest.mark.snapshot()
def test_stats_100(send_once_stats_tracer, sample_rate):
for _ in range(100):
def test_stats_30(send_once_stats_tracer):
for _ in range(30):
with send_once_stats_tracer.trace("name", service="abc", resource="/users/list"):
pass


@pytest.mark.snapshot()
def test_stats_errors(send_once_stats_tracer, sample_rate):
for i in range(100):
def test_stats_errors(send_once_stats_tracer):
for i in range(30):
with send_once_stats_tracer.trace("name", service="abc", resource="/users/list") as span:
if i % 2 == 0:
span.error = 1


@pytest.mark.snapshot()
def test_stats_aggrs(send_once_stats_tracer, sample_rate):
def test_stats_aggrs(send_once_stats_tracer):
"""
When different span properties are set
The stats are put into different aggregations
Expand Down Expand Up @@ -238,7 +226,7 @@ def test_measured_span(send_once_stats_tracer):

@pytest.mark.snapshot()
def test_top_level(send_once_stats_tracer):
for _ in range(100):
for _ in range(30):
with send_once_stats_tracer.trace("parent", service="svc-one"): # Should have stats
with send_once_stats_tracer.trace("child", service="svc-two"): # Should have stats
pass
Expand Down
Loading

0 comments on commit f982b2b

Please sign in to comment.