Skip to content

Commit 19c3eac

Browse files
Kyle-Verhoogmajorgreys
authored andcommitted
fix(core): handle failed encoding (#1946)
Looks like there was a typo/oversight with the error handling for encoding in which we'd continue to try to send the trace after encoding failed. * add regression test * continue only when encoding is successful
1 parent 527fbc1 commit 19c3eac

File tree

2 files changed

+42
-24
lines changed

2 files changed

+42
-24
lines changed

ddtrace/internal/writer.py

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -256,31 +256,31 @@ def write(self, spans):
256256
try:
257257
encoded = self._encoder.encode_trace(spans)
258258
except Exception:
259-
log.warning("failed to encode trace with encoder %r", self._encoder, exc_info=True)
260-
261-
try:
262-
self._buffer.put(encoded)
263-
except BufferItemTooLarge:
264-
log.warning(
265-
"trace (%db) larger than payload limit (%db), dropping",
266-
len(encoded),
267-
self._max_payload_size,
268-
)
269-
self._metrics_dist("buffer.dropped.traces", 1, tags=["reason:t_too_big"])
270-
self._metrics_dist("buffer.dropped.bytes", len(encoded), tags=["reason:t_too_big"])
271-
except BufferFull:
272-
log.warning(
273-
"trace buffer (%s traces %db/%db) cannot fit trace of size %db, dropping",
274-
len(self._buffer),
275-
self._buffer.size,
276-
self._buffer.max_size,
277-
len(encoded),
278-
)
279-
self._metrics_dist("buffer.dropped.traces", 1, tags=["reason:full"])
280-
self._metrics_dist("buffer.dropped.bytes", len(encoded), tags=["reason:full"])
259+
log.error("failed to encode trace with encoder %r", self._encoder, exc_info=True)
281260
else:
282-
self._metrics_dist("buffer.accepted.traces", 1)
283-
self._metrics_dist("buffer.accepted.spans", len(spans))
261+
try:
262+
self._buffer.put(encoded)
263+
except BufferItemTooLarge:
264+
log.warning(
265+
"trace (%db) larger than payload limit (%db), dropping",
266+
len(encoded),
267+
self._max_payload_size,
268+
)
269+
self._metrics_dist("buffer.dropped.traces", 1, tags=["reason:t_too_big"])
270+
self._metrics_dist("buffer.dropped.bytes", len(encoded), tags=["reason:t_too_big"])
271+
except BufferFull:
272+
log.warning(
273+
"trace buffer (%s traces %db/%db) cannot fit trace of size %db, dropping",
274+
len(self._buffer),
275+
self._buffer.size,
276+
self._buffer.max_size,
277+
len(encoded),
278+
)
279+
self._metrics_dist("buffer.dropped.traces", 1, tags=["reason:full"])
280+
self._metrics_dist("buffer.dropped.bytes", len(encoded), tags=["reason:full"])
281+
else:
282+
self._metrics_dist("buffer.accepted.traces", 1)
283+
self._metrics_dist("buffer.accepted.spans", len(spans))
284284

285285
def flush_queue(self):
286286
enc_traces = self._buffer.get()

tests/integration/test_integration.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,24 @@ def join_encoded(self, traces):
341341
log.error.assert_has_calls(calls)
342342

343343

344+
def test_bad_encoder():
345+
t = Tracer()
346+
347+
class BadEncoder:
348+
def encode_trace(self, spans):
349+
raise Exception()
350+
351+
def join_encoded(self, traces):
352+
pass
353+
354+
t.writer._encoder = BadEncoder()
355+
with mock.patch("ddtrace.internal.writer.log") as log:
356+
t.trace("asdf").finish()
357+
t.shutdown()
358+
calls = [mock.call("failed to encode trace with encoder %r", t.writer._encoder, exc_info=True)]
359+
log.error.assert_has_calls(calls)
360+
361+
344362
@pytest.mark.skipif(AGENT_VERSION == "testagent", reason="Test agent doesn't support v0.3")
345363
def test_downgrade():
346364
t = Tracer()

0 commit comments

Comments
 (0)