2828from ._encoding import BufferFull
2929from ._encoding import BufferItemTooLarge
3030from .agent import get_connection
31- from .encoding import Encoder
3231from .encoding import JSONEncoderV2
32+ from .encoding import MSGPACK_ENCODERS
3333from .logger import get_logger
3434from .runtime import container
3535from .sma import SimpleMovingAverage
@@ -234,6 +234,7 @@ def __init__(
234234 dogstatsd = None , # type: Optional[DogStatsd]
235235 report_metrics = False , # type: bool
236236 sync_mode = False , # type: bool
237+ api_version = None , # type: Optional[str]
237238 ):
238239 # type: (...) -> None
239240 # Pre-conditions:
@@ -256,10 +257,18 @@ def __init__(
256257 }
257258 self ._timeout = timeout
258259
259- if priority_sampler is not None :
260- self ._endpoint = "v0.4/traces"
261- else :
262- self ._endpoint = "v0.3/traces"
260+ encoding_version = (
261+ api_version or os .getenv ("DD_TRACE_API_VERSION" ) or ("v0.4" if priority_sampler is not None else "v0.3" )
262+ )
263+ try :
264+ Encoder = MSGPACK_ENCODERS [encoding_version ]
265+ except KeyError :
266+ raise ValueError (
267+ "Unsupported encoding version: '%s'. The supported versions are: %r"
268+ % (encoding_version , ", " .join (sorted (MSGPACK_ENCODERS .keys ())))
269+ )
270+
271+ self ._endpoint = "%s/traces" % encoding_version
263272
264273 self ._container_info = container .get_container_info ()
265274 if self ._container_info and self ._container_info .container_id :
@@ -348,10 +357,27 @@ def _put(self, data, headers):
348357 conn .close ()
349358
350359 def _downgrade (self , payload , response ):
360+ if self ._endpoint == "v0.5/traces" :
361+ self ._endpoint = "v0.4/traces"
362+ self ._encoder = MSGPACK_ENCODERS ["v0.4" ](
363+ max_size = self ._buffer_size ,
364+ max_item_size = self ._max_payload_size ,
365+ )
366+ # Since we have to change the encoding in this case, the payload
367+ # would need to be converted to the downgraded encoding before
368+ # sending it, but we chuck it away instead.
369+ log .warning (
370+ "Dropping trace payload due to the downgrade to an incompatible API version (from v0.5 to v0.4). To "
371+ "avoid this from happening in the future, either ensure that the Datadog agent has a v0.5/traces "
372+ "endpoint available, or explicitly set the trace API version to, e.g., v0.4."
373+ )
374+ return None
351375 if self ._endpoint == "v0.4/traces" :
352376 self ._endpoint = "v0.3/traces"
377+ # These endpoints share the same encoding, so we can try sending the
378+ # same payload over the downgraded endpoint.
353379 return payload
354- raise ValueError
380+ raise ValueError ()
355381
356382 def _send_payload (self , payload , count ):
357383 headers = self ._headers .copy ()
@@ -378,7 +404,8 @@ def _send_payload(self, payload, count):
378404 self .agent_url ,
379405 )
380406 else :
381- return self ._send_payload (payload , count )
407+ if payload is not None :
408+ self ._send_payload (payload , count )
382409 elif response .status >= 400 :
383410 log .error (
384411 "failed to send traces to Datadog Agent at %s: HTTP error status %s, reason %s" ,
0 commit comments