| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- # Copyright The OpenTracing Authors
- # Copyright Uber Technologies, Inc
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- from __future__ import absolute_import
- from . import logs
- from opentracing.ext import tags
- class SpanContext(object):
- """SpanContext represents :class:`Span` state that must propagate to
- descendant :class:`Span`\\ s and across process boundaries.
- SpanContext is logically divided into two pieces: the user-level "Baggage"
- (see :meth:`Span.set_baggage_item` and :meth:`Span.get_baggage_item`) that
- propagates across :class:`Span` boundaries and any
- tracer-implementation-specific fields that are needed to identify or
- otherwise contextualize the associated :class:`Span` (e.g., a ``(trace_id,
- span_id, sampled)`` tuple).
- """
- EMPTY_BAGGAGE = {} # TODO would be nice to make this immutable
- @property
- def baggage(self):
- """
- Return baggage associated with this :class:`SpanContext`.
- If no baggage has been added to the :class:`Span`, returns an empty
- dict.
- The caller must not modify the returned dictionary.
- See also: :meth:`Span.set_baggage_item()` /
- :meth:`Span.get_baggage_item()`
- :rtype: dict
- :return: baggage associated with this :class:`SpanContext` or ``{}``.
- """
- return SpanContext.EMPTY_BAGGAGE
- class Span(object):
- """
- Span represents a unit of work executed on behalf of a trace. Examples of
- spans include a remote procedure call, or a in-process method call to a
- sub-component. Every span in a trace may have zero or more causal parents,
- and these relationships transitively form a DAG. It is common for spans to
- have at most one parent, and thus most traces are merely tree structures.
- Span implements a context manager API that allows the following usage::
- with tracer.start_span(operation_name='go_fishing') as span:
- call_some_service()
- In the context manager syntax it's not necessary to call
- :meth:`Span.finish()`
- """
- def __init__(self, tracer, context):
- self._tracer = tracer
- self._context = context
- @property
- def context(self):
- """Provides access to the :class:`SpanContext` associated with this
- :class:`Span`.
- The :class:`SpanContext` contains state that propagates from
- :class:`Span` to :class:`Span` in a larger trace.
- :rtype: SpanContext
- :return: the :class:`SpanContext` associated with this :class:`Span`.
- """
- return self._context
- @property
- def tracer(self):
- """Provides access to the :class:`Tracer` that created this
- :class:`Span`.
- :rtype: Tracer
- :return: the :class:`Tracer` that created this :class:`Span`.
- """
- return self._tracer
- def set_operation_name(self, operation_name):
- """Changes the operation name.
- :param operation_name: the new operation name
- :type operation_name: str
- :rtype: Span
- :return: the :class:`Span` itself, for call chaining.
- """
- return self
- def finish(self, finish_time=None):
- """Indicates that the work represented by this :class:`Span` has completed or
- terminated.
- With the exception of the :attr:`Span.context` property, the semantics
- of all other :class:`Span` methods are undefined after
- :meth:`Span.finish()` has been invoked.
- :param finish_time: an explicit :class:`Span` finish timestamp as a
- unix timestamp per :meth:`time.time()`
- :type finish_time: float
- """
- pass
- def set_tag(self, key, value):
- """Attaches a key/value pair to the :class:`Span`.
- The value must be a string, a bool, or a numeric type.
- If the user calls set_tag multiple times for the same key,
- the behavior of the :class:`Tracer` is undefined, i.e. it is
- implementation specific whether the :class:`Tracer` will retain the
- first value, or the last value, or pick one randomly, or even keep all
- of them.
- :param key: key or name of the tag. Must be a string.
- :type key: str
- :param value: value of the tag.
- :type value: string or bool or int or float
- :rtype: Span
- :return: the :class:`Span` itself, for call chaining.
- """
- return self
- def log_kv(self, key_values, timestamp=None):
- """Adds a log record to the :class:`Span`.
- For example::
- span.log_kv({
- "event": "time to first byte",
- "packet.size": packet.size()})
- span.log_kv({"event": "two minutes ago"}, time.time() - 120)
- :param key_values: A dict of string keys and values of any type
- :type key_values: dict
- :param timestamp: A unix timestamp per :meth:`time.time()`; current
- time if ``None``
- :type timestamp: float
- :rtype: Span
- :return: the :class:`Span` itself, for call chaining.
- """
- return self
- def set_baggage_item(self, key, value):
- """Stores a Baggage item in the :class:`Span` as a key/value pair.
- Enables powerful distributed context propagation functionality where
- arbitrary application data can be carried along the full path of
- request execution throughout the system.
- Note 1: Baggage is only propagated to the future (recursive) children
- of this :class:`Span`.
- Note 2: Baggage is sent in-band with every subsequent local and remote
- calls, so this feature must be used with care.
- :param key: Baggage item key
- :type key: str
- :param value: Baggage item value
- :type value: str
- :rtype: Span
- :return: itself, for chaining the calls.
- """
- return self
- def get_baggage_item(self, key):
- """Retrieves value of the baggage item with the given key.
- :param key: key of the baggage item
- :type key: str
- :rtype: str
- :return: value of the baggage item with given key, or ``None``.
- """
- return None
- def __enter__(self):
- """Invoked when :class:`Span` is used as a context manager.
- :rtype: Span
- :return: the :class:`Span` itself
- """
- return self
- def __exit__(self, exc_type, exc_val, exc_tb):
- """Ends context manager and calls finish() on the :class:`Span`.
- If exception has occurred during execution, it is automatically logged
- and added as a tag. :attr:`~operation.ext.tags.ERROR` will also be set
- to `True`.
- """
- Span._on_error(self, exc_type, exc_val, exc_tb)
- self.finish()
- @staticmethod
- def _on_error(span, exc_type, exc_val, exc_tb):
- if not span or not exc_val:
- return
- span.set_tag(tags.ERROR, True)
- span.log_kv({
- logs.EVENT: tags.ERROR,
- logs.MESSAGE: str(exc_val),
- logs.ERROR_OBJECT: exc_val,
- logs.ERROR_KIND: exc_type,
- logs.STACK: exc_tb,
- })
- def log_event(self, event, payload=None):
- """DEPRECATED"""
- if payload is None:
- return self.log_kv({logs.EVENT: event})
- else:
- return self.log_kv({logs.EVENT: event, 'payload': payload})
- def log(self, **kwargs):
- """DEPRECATED"""
- key_values = {}
- if logs.EVENT in kwargs:
- key_values[logs.EVENT] = kwargs[logs.EVENT]
- if 'payload' in kwargs:
- key_values['payload'] = kwargs['payload']
- timestamp = None
- if 'timestamp' in kwargs:
- timestamp = kwargs['timestamp']
- return self.log_kv(key_values, timestamp)
|