Skip to content

Commit ded53fa

Browse files
feat(tracing): spans not sent to agent after tracer shut down (#3483) (#3518)
Warns users when Tracer.trace() or Tracer.start_span() is called after a tracer is shutdown. Co-authored-by: Munir Abdinur <[email protected]>
1 parent cd1693c commit ded53fa

File tree

4 files changed

+42
-5
lines changed

4 files changed

+42
-5
lines changed

ddtrace/tracer.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
from .internal import debug
3636
from .internal import forksafe
3737
from .internal import hostname
38-
from .internal import service
3938
from .internal.dogstatsd import get_dogstatsd_client
4039
from .internal.logger import get_logger
4140
from .internal.logger import hasHandlers
@@ -46,6 +45,7 @@
4645
from .internal.processor.trace import TraceTagsProcessor
4746
from .internal.processor.trace import TraceTopLevelSpanProcessor
4847
from .internal.runtime import get_runtime_id
48+
from .internal.service import ServiceStatusError
4949
from .internal.utils.formats import asbool
5050
from .internal.writer import AgentWriter
5151
from .internal.writer import LogWriter
@@ -332,8 +332,8 @@ def configure(
332332

333333
try:
334334
self._writer.stop()
335-
except service.ServiceStatusError:
336-
# It's possible the writer never got started in the first place :(
335+
except ServiceStatusError:
336+
# It's possible the writer never got started
337337
pass
338338

339339
if writer is not None:
@@ -394,7 +394,20 @@ def _child_after_fork(self):
394394

395395
self._new_process = True
396396

397-
def start_span(
397+
def _start_span_after_shutdown(
398+
self,
399+
name, # type: str
400+
child_of=None, # type: Optional[Union[Span, Context]]
401+
service=None, # type: Optional[str]
402+
resource=None, # type: Optional[str]
403+
span_type=None, # type: Optional[str]
404+
activate=False, # type: bool
405+
):
406+
# type: (...) -> Span
407+
log.warning("Spans started after the tracer has been shut down will not be sent to the Datadog Agent.")
408+
return self._start_span(name, child_of, service, resource, span_type, activate)
409+
410+
def _start_span(
398411
self,
399412
name, # type: str
400413
child_of=None, # type: Optional[Union[Span, Context]]
@@ -589,6 +602,8 @@ def start_span(
589602
self._hooks.emit(self.__class__.start_span, span)
590603
return span
591604

605+
start_span = _start_span
606+
592607
def _on_span_finish(self, span):
593608
# type: (Span) -> None
594609
active = self.current_span()
@@ -878,6 +893,8 @@ def shutdown(self, timeout=None):
878893
atexit.unregister(self._atexit)
879894
forksafe.unregister(self._child_after_fork)
880895

896+
self.start_span = self._start_span_after_shutdown # type: ignore[assignment]
897+
881898
@staticmethod
882899
def _use_log_writer():
883900
# type: () -> bool
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
upgrade:
3+
- |
4+
Spans started after the tracer has been shut down will no longer be sent to the Datadog Agent.

tests/contrib/gevent/test_monkeypatch.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ def test_gevent_warning(monkeypatch):
2424
def test_gevent_auto_patching():
2525
import ddtrace
2626

27-
ddtrace.patch_all()
27+
# Disable tracing sqlite3 as it is used by coverage
28+
ddtrace.patch_all(sqlite3=False)
2829
# Patch on import
2930
import gevent # noqa
3031

tests/tracer/test_tracer.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,21 @@ def test_tracer_shutdown():
571571
mock_write.assert_not_called()
572572

573573

574+
def test_tracer_shutdown_warning():
575+
t = ddtrace.Tracer()
576+
t.shutdown()
577+
578+
with mock.patch.object(logging.Logger, "warning") as mock_logger:
579+
with t.trace("something"):
580+
pass
581+
582+
mock_logger.assert_has_calls(
583+
[
584+
mock.call("Spans started after the tracer has been shut down will not be sent to the Datadog Agent."),
585+
]
586+
)
587+
588+
574589
def test_tracer_dogstatsd_url():
575590
t = ddtrace.Tracer()
576591
assert t._writer.dogstatsd.host == "localhost"

0 commit comments

Comments
 (0)