Exemple #1
0
def clean_thread_local():
    yield

    stack = ThreadLocalStack()
    while stack.pop():
        pass

    default_span_storage().clear()

    while get_default_tracer().pop_zipkin_attrs():
        pass
    get_default_tracer()._span_storage.clear()
Exemple #2
0
def test_memory_leak():
    # In py_zipkin >= 0.13.0 and <= 0.14.0 this test fails since the
    # span_storage contains 10 spans once you exit the for loop.
    mock_transport_handler, mock_logs = mock_logger()
    assert len(storage.default_span_storage()) == 0
    for _ in range(10):
        with zipkin.zipkin_client_span(
            service_name='test_service_name',
            span_name='test_span_name',
            transport_handler=mock_transport_handler,
            sample_rate=0.0,
            encoding=Encoding.V2_JSON,
        ):
            with zipkin.zipkin_span(
                service_name='inner_service_name',
                span_name='inner_span_name',
            ):
                pass

    assert len(mock_logs) == 0
    assert len(storage.default_span_storage()) == 0
  def __init__(self, run_tracker, settings, endpoint, trace_id, parent_id, sample_rate):
    """
    When trace_id and parent_id are set a Zipkin trace will be created with given trace_id
    and parent_id. If trace_id and parent_id are set to None, a trace_id will be randomly
    generated for a Zipkin trace. trace-id and parent-id must both either be set or not set.

    :param RunTracker run_tracker: Tracks and times the execution of a pants run.
    :param Settings settings: Generic reporting settings.
    :param string endpoint: The full HTTP URL of a zipkin server to which traces should be posted.
    :param string trace_id: The overall 64 or 128-bit ID of the trace. May be None.
    :param string parent_id: The 64-bit ID for a parent span that invokes Pants. May be None.
    :param float sample_rate: Rate at which to sample Zipkin traces. Value 0.0 - 100.0.
    """
    super(ZipkinReporter, self).__init__(run_tracker, settings)
    # We keep track of connection between workunits and spans
    self._workunits_to_spans = {}
    # Create a transport handler
    self.handler = HTTPTransportHandler(endpoint)
    self.trace_id = trace_id
    self.parent_id = parent_id
    self.sample_rate = float(sample_rate)
    self.endpoint = endpoint
    self.span_storage = storage.default_span_storage()
Exemple #4
0
    def __init__(self, run_tracker, settings, endpoint, trace_id, parent_id,
                 sample_rate):
        """
    When trace_id and parent_id are set a Zipkin trace will be created with given trace_id
    and parent_id. If trace_id and parent_id are set to None, a trace_id will be randomly
    generated for a Zipkin trace. trace-id and parent-id must both either be set or not set.

    :param RunTracker run_tracker: Tracks and times the execution of a pants run.
    :param Settings settings: Generic reporting settings.
    :param string endpoint: The full HTTP URL of a zipkin server to which traces should be posted.
    :param string trace_id: The overall 64 or 128-bit ID of the trace. May be None.
    :param string parent_id: The 64-bit ID for a parent span that invokes Pants. May be None.
    :param float sample_rate: Rate at which to sample Zipkin traces. Value 0.0 - 100.0.
    """
        super(ZipkinReporter, self).__init__(run_tracker, settings)
        # We keep track of connection between workunits and spans
        self._workunits_to_spans = {}
        # Create a transport handler
        self.handler = HTTPTransportHandler(endpoint)
        self.trace_id = trace_id
        self.parent_id = parent_id
        self.sample_rate = float(sample_rate)
        self.endpoint = endpoint
        self.span_storage = storage.default_span_storage()
def test_default_span_storage_warns():
    with mock.patch.object(storage.log, 'warning') as mock_log:
        storage.default_span_storage()
        assert mock_log.call_count == 1
Exemple #6
0
    def __init__(
        self,
        service_name,
        span_name='span',
        zipkin_attrs=None,
        transport_handler=None,
        max_span_batch_size=None,
        annotations=None,
        binary_annotations=None,
        port=0,
        sample_rate=None,
        include=None,
        add_logging_annotation=False,
        report_root_timestamp=False,
        use_128bit_trace_id=False,
        host=None,
        context_stack=None,
        span_storage=None,
        firehose_handler=None,
        kind=None,
        timestamp=None,
        duration=None,
        encoding=Encoding.V1_THRIFT,
    ):
        """Logs a zipkin span. If this is the root span, then a zipkin
        trace is started as well.

        :param service_name: The name of the called service
        :type service_name: string
        :param span_name: Optional name of span, defaults to 'span'
        :type span_name: string
        :param zipkin_attrs: Optional set of zipkin attributes to be used
        :type zipkin_attrs: ZipkinAttrs
        :param transport_handler: Callback function that takes a message parameter
            and handles logging it
        :type transport_handler: BaseTransportHandler
        :param max_span_batch_size: Spans in a trace are sent in batches,
            max_span_batch_size defines max size of one batch
        :type max_span_batch_size: int
        :param annotations: Optional dict of str -> timestamp annotations
        :type annotations: dict of str -> int
        :param binary_annotations: Optional dict of str -> str span attrs
        :type binary_annotations: dict of str -> str
        :param port: The port number of the service. Defaults to 0.
        :type port: int
        :param sample_rate: Rate at which to sample; 0.0 - 100.0. If passed-in
            zipkin_attrs have is_sampled=False and the sample_rate param is > 0,
            a new span will be generated at this rate. This means that if you
            propagate sampling decisions to downstream services, but still have
            sample_rate > 0 in those services, the actual rate of generated
            spans for those services will be > sampling_rate.
        :type sample_rate: float
        :param include: which annotations to include
            can be one of {'client', 'server'}
            corresponding to ('cs', 'cr') and ('ss', 'sr') respectively.
            DEPRECATED: use kind instead. `include` will be removed in 1.0.
        :type include: iterable
        :param add_logging_annotation: Whether to add a 'logging_end'
            annotation when py_zipkin finishes logging spans
        :type add_logging_annotation: boolean
        :param report_root_timestamp: Whether the span should report timestamp
            and duration. Only applies to "root" spans in this local context,
            so spans created inside other span contexts will always log
            timestamp/duration. Note that this is only an override for spans
            that have zipkin_attrs passed in. Spans that make their own
            sampling decisions (i.e. are the root spans of entire traces) will
            always report timestamp/duration.
        :type report_root_timestamp: boolean
        :param use_128bit_trace_id: If true, generate 128-bit trace_ids.
        :type use_128bit_trace_id: boolean
        :param host: Contains the ipv4 or ipv6 value of the host. The ip value
            isn't automatically determined in a docker environment.
        :type host: string
        :param context_stack: explicit context stack for storing
            zipkin attributes
        :type context_stack: object
        :param span_storage: explicit Span storage for storing zipkin spans
            before they're emitted.
        :type span_storage: py_zipkin.storage.SpanStorage
        :param firehose_handler: [EXPERIMENTAL] Similar to transport_handler,
            except that it will receive 100% of the spans regardless of trace
            sampling rate.
        :type firehose_handler: BaseTransportHandler
        :param kind: Span type (client, server, local, etc...).
        :type kind: Kind
        :param timestamp: Timestamp in seconds, defaults to `time.time()`.
            Set this if you want to use a custom timestamp.
        :type timestamp: float
        :param duration: Duration in seconds, defaults to the time spent in the
            context. Set this if you want to use a custom duration.
        :type duration: float
        :param encoding: Output encoding format, defaults to V1 thrift spans.
        :type encoding: Encoding
        """
        self.service_name = service_name
        self.span_name = span_name
        self.zipkin_attrs = zipkin_attrs
        self.transport_handler = transport_handler
        self.max_span_batch_size = max_span_batch_size
        self.annotations = annotations or {}
        self.binary_annotations = binary_annotations or {}
        self.port = port
        self.sample_rate = sample_rate
        self.add_logging_annotation = add_logging_annotation
        self.report_root_timestamp_override = report_root_timestamp
        self.use_128bit_trace_id = use_128bit_trace_id
        self.host = host
        self._context_stack = context_stack or ThreadLocalStack()
        if span_storage is not None:
            self._span_storage = span_storage
        else:
            self._span_storage = storage.default_span_storage()
        self.firehose_handler = firehose_handler
        self.kind = self._generate_kind(kind, include)
        self.timestamp = timestamp
        self.duration = duration
        self.encoding = encoding

        self._is_local_root_span = False
        self.logging_context = None
        self.do_pop_attrs = False
        # Spans that log a 'cs' timestamp can additionally record a
        # 'sa' binary annotation that shows where the request is going.
        self.sa_endpoint = None

        # It used to  be possible to override timestamp and duration by passing
        # in the cs/cr or sr/ss annotations. We want to keep backward compatibility
        # for now, so this logic overrides self.timestamp and self.duration in the
        # same way.
        # This doesn't fit well with v2 spans since those annotations are gone, so
        # we also log a deprecation warning.
        if 'sr' in self.annotations and 'ss' in self.annotations:
            self.duration = self.annotations['ss'] - self.annotations['sr']
            self.timestamp = self.annotations['sr']
            log.warning(
                "Manually setting 'sr'/'ss' annotations is deprecated. Please "
                "use the timestamp and duration parameters.")
        if 'cr' in self.annotations and 'cs' in self.annotations:
            self.duration = self.annotations['cr'] - self.annotations['cs']
            self.timestamp = self.annotations['cs']
            log.warning(
                "Manually setting 'cr'/'cs' annotations is deprecated. Please "
                "use the timestamp and duration parameters.")

        # Root spans have transport_handler and at least one of zipkin_attrs
        # or sample_rate.
        if self.zipkin_attrs or self.sample_rate is not None:
            # transport_handler is mandatory for root spans
            if self.transport_handler is None:
                raise ZipkinError(
                    'Root spans require a transport handler to be given')

            self._is_local_root_span = True

        # If firehose_handler than this is a local root span.
        if self.firehose_handler:
            self._is_local_root_span = True

        if self.sample_rate is not None and not (0.0 <= self.sample_rate <=
                                                 100.0):
            raise ZipkinError('Sample rate must be between 0.0 and 100.0')

        if not isinstance(self._span_storage, storage.SpanStorage):
            raise ZipkinError('span_storage should be an instance '
                              'of py_zipkin.storage.SpanStorage')