Source code for opencensus.trace.tracers.context_tracer
# Copyright 2017, OpenCensus Authors
#
# 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.
import logging
import threading
from opencensus.trace import execution_context
from opencensus.trace.span_context import SpanContext
from opencensus.trace import print_exporter
from opencensus.trace import span as trace_span
from opencensus.trace import span_data as span_data_module
from opencensus.trace.tracers import base
[docs]class ContextTracer(base.Tracer):
"""The interface for tracing a request context.
:type span_context: :class:`~opencensus.trace.span_context.SpanContext`
:param span_context: SpanContext encapsulates the current context within
the request's trace.
"""
def __init__(self, exporter=None, span_context=None):
if exporter is None:
exporter = print_exporter.PrintExporter()
if span_context is None:
span_context = SpanContext()
self.exporter = exporter
self.span_context = span_context
self.trace_id = span_context.trace_id
self.root_span_id = span_context.span_id
self._spans_list_condition = threading.Condition()
# List of spans to report
self._spans_list = []
[docs] def finish(self):
"""Finish all spans
:rtype: dict
:returns: JSON format trace.
"""
while self._spans_list:
self.end_span()
[docs] def span(self, name='span'):
"""Create a new span with the trace using the context information.
:type name: str
:param name: The name of the span.
:rtype: :class:`~opencensus.trace.span.Span`
:returns: The Span object.
"""
span = self.start_span(name=name)
return span
[docs] def start_span(self, name='span'):
"""Start a span.
:type name: str
:param name: The name of the span.
:rtype: :class:`~opencensus.trace.span.Span`
:returns: The Span object.
"""
parent_span = self.current_span()
# If a span has remote parent span, then the parent_span.span_id
# should be the span_id from the request header.
if parent_span is None:
parent_span = base.NullContextManager(
span_id=self.span_context.span_id)
span = trace_span.Span(
name,
parent_span=parent_span,
context_tracer=self)
with self._spans_list_condition:
self._spans_list.append(span)
self.span_context.span_id = span.span_id
execution_context.set_current_span(span)
span.start()
return span
[docs] def end_span(self, *args, **kwargs):
"""End a span. Update the span_id in SpanContext to the current span's
parent span id; Update the current span.
"""
cur_span = self.current_span()
if cur_span is None and self._spans_list:
cur_span = self._spans_list[-1]
if cur_span is None:
logging.warning('No active span, cannot do end_span.')
return
cur_span.finish()
self.span_context.span_id = cur_span.parent_span.span_id if \
cur_span.parent_span else None
if isinstance(cur_span.parent_span, trace_span.Span):
execution_context.set_current_span(cur_span.parent_span)
else:
execution_context.set_current_span(None)
with self._spans_list_condition:
if cur_span in self._spans_list:
span_datas = self.get_span_datas(cur_span)
self.exporter.export(span_datas)
self._spans_list.remove(cur_span)
return cur_span
[docs] def current_span(self):
"""Return the current span."""
current_span = execution_context.get_current_span()
return current_span
[docs] def list_collected_spans(self):
return self._spans_list
[docs] def add_attribute_to_current_span(self, attribute_key, attribute_value):
"""Add attribute to current span.
:type attribute_key: str
:param attribute_key: Attribute key.
:type attribute_value:str
:param attribute_value: Attribute value.
"""
current_span = self.current_span()
current_span.add_attribute(attribute_key, attribute_value)
[docs] def get_span_datas(self, span):
"""Extracts a list of SpanData tuples from a span
:rtype: list of opencensus.trace.span_data.SpanData
:return list of SpanData tuples
"""
span_datas = [
span_data_module.SpanData(
name=ss.name,
context=self.span_context,
span_id=ss.span_id,
parent_span_id=ss.parent_span.span_id if
ss.parent_span else None,
attributes=ss.attributes,
start_time=ss.start_time,
end_time=ss.end_time,
child_span_count=len(ss.children),
stack_trace=ss.stack_trace,
annotations=ss.annotations,
message_events=ss.message_events,
links=ss.links,
status=ss.status,
same_process_as_parent_span=ss.same_process_as_parent_span,
span_kind=ss.span_kind
)
for ss in span
]
return span_datas