Files
2020-04-08 10:39:44 -07:00

91 lines
2.7 KiB
Python

from .encoding import get_encoder
class PayloadFull(Exception):
"""The payload is full."""
pass
class Payload(object):
"""
Trace agent API payload buffer class
This class is used to encoded and store traces to build the payload we send to
the trace agent.
DEV: We encoded and buffer traces so that we can reliable determine the size of
the payload easily so we can flush based on the payload size.
"""
__slots__ = ('traces', 'size', 'encoder', 'max_payload_size')
# Trace agent limit payload size of 10 MB
# 5 MB should be a good average efficient size
DEFAULT_MAX_PAYLOAD_SIZE = 5 * 1000000
def __init__(self, encoder=None, max_payload_size=DEFAULT_MAX_PAYLOAD_SIZE):
"""
Constructor for Payload
:param encoder: The encoded to use, default is the default encoder
:type encoder: ``ddtrace.encoding.Encoder``
:param max_payload_size: The max number of bytes a payload should be before
being considered full (default: 5mb)
"""
self.max_payload_size = max_payload_size
self.encoder = encoder or get_encoder()
self.traces = []
self.size = 0
def add_trace(self, trace):
"""
Encode and append a trace to this payload
:param trace: A trace to append
:type trace: A list of :class:`ddtrace.span.Span`
"""
# No trace or empty trace was given, ignore
if not trace:
return
# Encode the trace, append, and add it's length to the size
encoded = self.encoder.encode_trace(trace)
if len(encoded) + self.size > self.max_payload_size:
raise PayloadFull()
self.traces.append(encoded)
self.size += len(encoded)
@property
def length(self):
"""
Get the number of traces in this payload
:returns: The number of traces in the payload
:rtype: int
"""
return len(self.traces)
@property
def empty(self):
"""
Whether this payload is empty or not
:returns: Whether this payload is empty or not
:rtype: bool
"""
return self.length == 0
def get_payload(self):
"""
Get the fully encoded payload
:returns: The fully encoded payload
:rtype: str | bytes
"""
# DEV: `self.traces` is an array of encoded traces, `join_encoded` joins them together
return self.encoder.join_encoded(self.traces)
def __repr__(self):
"""Get the string representation of this payload"""
return '{0}(length={1}, size={2} B, max_payload_size={3} B)'.format(
self.__class__.__name__, self.length, self.size, self.max_payload_size)