def log_kv(self, key_values: Attributes, timestamp: float = None) -> "SpanShim": """Logs an event for the wrapped OpenTelemetry span. Note: The OpenTracing API defines the values of *key_values* to be of any type. However, the OpenTelemetry API requires that the values be any one of the types defined in ``opentelemetry.trace.util.Attributes`` therefore, only these types are supported as values. Args: key_values: A dictionary as specified in ``opentelemetry.trace.util.Attributes``. timestamp: Timestamp of the OpenTelemetry event, will be generated automatically if omitted. Returns: Returns this :class:`SpanShim` instance to allow call chaining. """ if timestamp is not None: event_timestamp = util.time_seconds_to_ns(timestamp) else: event_timestamp = None event_name = util.event_name_from_kv(key_values) self._otel_span.add_event(event_name, key_values, event_timestamp) return self
def test_time_conversion_precision(self): """Verify time conversion from seconds to nanoseconds and vice versa is accurate enough. """ time_seconds = 1570484241.9501917 time_nanoseconds = util.time_seconds_to_ns(time_seconds) result = util.time_seconds_from_ns(time_nanoseconds) # Tolerate inaccuracies of less than a microsecond. # TODO: Put a link to an explanation in the docs. # TODO: This seems to work consistently, but we should find out the # biggest possible loss of precision. self.assertAlmostEqual(result, time_seconds, places=6)
def finish(self, finish_time: float = None): """Ends the OpenTelemetry span wrapped by this :class:`SpanShim`. If *finish_time* is provided, the time value is converted to the OpenTelemetry time format (number of nanoseconds since the epoch, expressed as an integer) and passed on to the OpenTelemetry tracer when ending the OpenTelemetry span. If *finish_time* isn't provided, it is up to the OpenTelemetry tracer implementation to generate a timestamp when ending the span. Args: finish_time: A value that represents the finish time expressed as the number of seconds since the epoch as returned by :func:`time.time()`. """ end_time = finish_time if end_time is not None: end_time = util.time_seconds_to_ns(finish_time) self._otel_span.end(end_time=end_time)
def start_span( self, operation_name: str = None, child_of: Union[SpanShim, SpanContextShim] = None, references: list = None, tags: Attributes = None, start_time: float = None, ignore_active_span: bool = False, ) -> SpanShim: """Implements the ``start_span()`` method from the base class. Starts a span. In terms of functionality, this method behaves exactly like the same method on a "regular" OpenTracing tracer. See :meth:`opentracing.Tracer.start_span` for more details. Args: operation_name: Name of the operation represented by the new span from the perspective of the current service. child_of: A :class:`SpanShim` or :class:`SpanContextShim` representing the parent in a "child of" reference. If specified, the *references* parameter must be omitted. references: A list of :class:`opentracing.Reference` objects that identify one or more parents of type :class:`SpanContextShim`. tags: A dictionary of tags. start_time: An explicit start time expressed as the number of seconds since the epoch as returned by :func:`time.time()`. ignore_active_span: Ignore the currently-active span in the OpenTelemetry tracer and make the created span the root span of a new trace. Returns: An already-started :class:`SpanShim` instance. """ # Use active span as parent when no explicit parent is specified. if not ignore_active_span and not child_of: child_of = self.active_span # Use the specified parent or the active span if possible. Otherwise, # use a `None` parent, which triggers the creation of a new trace. parent = child_of.unwrap() if child_of else None if isinstance(parent, OtelSpanContext): parent = NonRecordingSpan(parent) parent_span_context = set_span_in_context(parent) links = [] if references: for ref in references: links.append(Link(ref.referenced_context.unwrap())) # The OpenTracing API expects time values to be `float` values which # represent the number of seconds since the epoch. OpenTelemetry # represents time values as nanoseconds since the epoch. start_time_ns = start_time if start_time_ns is not None: start_time_ns = util.time_seconds_to_ns(start_time) span = self._otel_tracer.start_span( operation_name, context=parent_span_context, links=links, attributes=tags, start_time=start_time_ns, ) context = SpanContextShim(span.get_span_context()) return SpanShim(self, context, span)
def test_time_seconds_to_ns(self): time_seconds = time.time() result = util.time_seconds_to_ns(time_seconds) self.assertEqual(result, int(time_seconds * 1e9))