From 8112754f5170333d77844d8b608ec0c5a22679c9 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Mon, 1 Feb 2021 14:40:15 -0800 Subject: [PATCH 01/18] adding readable span --- .../exporter/jaeger/translate/protobuf.py | 16 +- .../exporter/jaeger/translate/thrift.py | 12 +- .../opencensus/trace_exporter/__init__.py | 6 +- .../exporter/otlp/trace_exporter/__init__.py | 32 ++-- .../src/opentelemetry/sdk/trace/__init__.py | 148 +++++++++++------- .../sdk/trace/export/__init__.py | 18 ++- .../trace/export/in_memory_span_exporter.py | 4 +- opentelemetry-sdk/tests/trace/test_trace.py | 6 +- 8 files changed, 148 insertions(+), 94 deletions(-) diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/protobuf.py b/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/protobuf.py index cc7354217a9..f97977516db 100644 --- a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/protobuf.py +++ b/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/protobuf.py @@ -24,7 +24,7 @@ VERSION_KEY, Translator, ) -from opentelemetry.sdk.trace import Span, StatusCode +from opentelemetry.sdk.trace import ReadableSpan, StatusCode from opentelemetry.util import types # pylint: disable=no-member,too-many-locals,no-self-use @@ -93,7 +93,7 @@ def _translate_attribute( return translated -def _extract_resource_tags(span: Span) -> Sequence[model_pb2.KeyValue]: +def _extract_resource_tags(span: ReadableSpan) -> Sequence[model_pb2.KeyValue]: """Extracts resource attributes from span and returns list of jaeger keyvalues. @@ -143,7 +143,7 @@ class ProtobufTranslator(Translator): def __init__(self, svc_name): self.svc_name = svc_name - def _translate_span(self, span: Span) -> model_pb2.Span: + def _translate_span(self, span: ReadableSpan) -> model_pb2.Span: ctx = span.get_span_context() # pb2 span expects in byte format @@ -177,7 +177,9 @@ def _translate_span(self, span: Span) -> model_pb2.Span: ) return jaeger_span - def _extract_tags(self, span: Span) -> Sequence[model_pb2.KeyValue]: + def _extract_tags( + self, span: ReadableSpan + ) -> Sequence[model_pb2.KeyValue]: translated = [] if span.attributes: for key, value in span.attributes.items(): @@ -226,7 +228,7 @@ def _extract_tags(self, span: Span) -> Sequence[model_pb2.KeyValue]: return translated def _extract_refs( - self, span: Span + self, span: ReadableSpan ) -> Optional[Sequence[model_pb2.SpanRef]]: if not span.links: return None @@ -244,7 +246,9 @@ def _extract_refs( ) return refs - def _extract_logs(self, span: Span) -> Optional[Sequence[model_pb2.Log]]: + def _extract_logs( + self, span: ReadableSpan + ) -> Optional[Sequence[model_pb2.Log]]: if not span.events: return None diff --git a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/thrift.py b/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/thrift.py index 8ca371c1b5b..9df9c716882 100644 --- a/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/thrift.py +++ b/exporter/opentelemetry-exporter-jaeger/src/opentelemetry/exporter/jaeger/translate/thrift.py @@ -23,7 +23,7 @@ _convert_int_to_i64, _nsec_to_usec_round, ) -from opentelemetry.sdk.trace import Span, StatusCode +from opentelemetry.sdk.trace import ReadableSpan, StatusCode from opentelemetry.util import types @@ -75,7 +75,7 @@ def _translate_attribute( class ThriftTranslator(Translator): - def _translate_span(self, span: Span) -> TCollector.Span: + def _translate_span(self, span: ReadableSpan) -> TCollector.Span: ctx = span.get_span_context() trace_id = ctx.trace_id span_id = ctx.span_id @@ -106,7 +106,7 @@ def _translate_span(self, span: Span) -> TCollector.Span: ) return jaeger_span - def _extract_tags(self, span: Span) -> Sequence[TCollector.Tag]: + def _extract_tags(self, span: ReadableSpan) -> Sequence[TCollector.Tag]: translated = [] if span.attributes: @@ -151,7 +151,7 @@ def _extract_tags(self, span: Span) -> Sequence[TCollector.Tag]: return translated def _extract_refs( - self, span: Span + self, span: ReadableSpan ) -> Optional[Sequence[TCollector.SpanRef]]: if not span.links: return None @@ -170,7 +170,9 @@ def _extract_refs( ) return refs - def _extract_logs(self, span: Span) -> Optional[Sequence[TCollector.Log]]: + def _extract_logs( + self, span: ReadableSpan + ) -> Optional[Sequence[TCollector.Log]]: """Returns jaeger logs if events exists, otherwise None. Args: diff --git a/exporter/opentelemetry-exporter-opencensus/src/opentelemetry/exporter/opencensus/trace_exporter/__init__.py b/exporter/opentelemetry-exporter-opencensus/src/opentelemetry/exporter/opencensus/trace_exporter/__init__.py index 613ee6482ba..6a779c09fec 100644 --- a/exporter/opentelemetry-exporter-opencensus/src/opentelemetry/exporter/opencensus/trace_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-opencensus/src/opentelemetry/exporter/opencensus/trace_exporter/__init__.py @@ -25,7 +25,7 @@ from opencensus.proto.trace.v1 import trace_pb2 import opentelemetry.exporter.opencensus.util as utils -from opentelemetry.sdk.trace import Span +from opentelemetry.sdk.trace import ReadableSpan from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult DEFAULT_ENDPOINT = "localhost:55678" @@ -62,7 +62,7 @@ def __init__( self.node = utils.get_node(service_name, host_name) - def export(self, spans: Sequence[Span]) -> SpanExportResult: + def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult: try: responses = self.client.Export(self.generate_span_requests(spans)) @@ -87,7 +87,7 @@ def generate_span_requests(self, spans): # pylint: disable=too-many-branches -def translate_to_collector(spans: Sequence[Span]): +def translate_to_collector(spans: Sequence[ReadableSpan]): collector_spans = [] for span in spans: status = None diff --git a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py index b872b624a1a..cc4961162a8 100644 --- a/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py +++ b/exporter/opentelemetry-exporter-otlp/src/opentelemetry/exporter/otlp/trace_exporter/__init__.py @@ -38,7 +38,7 @@ ) from opentelemetry.proto.trace.v1.trace_pb2 import Span as CollectorSpan from opentelemetry.proto.trace.v1.trace_pb2 import Status -from opentelemetry.sdk.trace import Span as SDKSpan +from opentelemetry.sdk.trace import ReadableSpan from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult from opentelemetry.trace.status import StatusCode @@ -48,7 +48,9 @@ # pylint: disable=no-member class OTLPSpanExporter( SpanExporter, - OTLPExporterMixin[SDKSpan, ExportTraceServiceRequest, SpanExportResult], + OTLPExporterMixin[ + ReadableSpan, ExportTraceServiceRequest, SpanExportResult + ], ): # pylint: disable=unsubscriptable-object """OTLP span exporter @@ -96,34 +98,34 @@ def __init__( } ) - def _translate_name(self, sdk_span: SDKSpan) -> None: + def _translate_name(self, sdk_span: ReadableSpan) -> None: self._collector_span_kwargs["name"] = sdk_span.name - def _translate_start_time(self, sdk_span: SDKSpan) -> None: + def _translate_start_time(self, sdk_span: ReadableSpan) -> None: self._collector_span_kwargs[ "start_time_unix_nano" ] = sdk_span.start_time - def _translate_end_time(self, sdk_span: SDKSpan) -> None: + def _translate_end_time(self, sdk_span: ReadableSpan) -> None: self._collector_span_kwargs["end_time_unix_nano"] = sdk_span.end_time - def _translate_span_id(self, sdk_span: SDKSpan) -> None: + def _translate_span_id(self, sdk_span: ReadableSpan) -> None: self._collector_span_kwargs[ "span_id" ] = sdk_span.context.span_id.to_bytes(8, "big") - def _translate_trace_id(self, sdk_span: SDKSpan) -> None: + def _translate_trace_id(self, sdk_span: ReadableSpan) -> None: self._collector_span_kwargs[ "trace_id" ] = sdk_span.context.trace_id.to_bytes(16, "big") - def _translate_parent(self, sdk_span: SDKSpan) -> None: + def _translate_parent(self, sdk_span: ReadableSpan) -> None: if sdk_span.parent is not None: self._collector_span_kwargs[ "parent_span_id" ] = sdk_span.parent.span_id.to_bytes(8, "big") - def _translate_context_trace_state(self, sdk_span: SDKSpan) -> None: + def _translate_context_trace_state(self, sdk_span: ReadableSpan) -> None: if sdk_span.context.trace_state is not None: self._collector_span_kwargs["trace_state"] = ",".join( [ @@ -132,7 +134,7 @@ def _translate_context_trace_state(self, sdk_span: SDKSpan) -> None: ] ) - def _translate_attributes(self, sdk_span: SDKSpan) -> None: + def _translate_attributes(self, sdk_span: ReadableSpan) -> None: if sdk_span.attributes: self._collector_span_kwargs["attributes"] = [] @@ -146,7 +148,7 @@ def _translate_attributes(self, sdk_span: SDKSpan) -> None: except Exception as error: # pylint: disable=broad-except logger.exception(error) - def _translate_events(self, sdk_span: SDKSpan) -> None: + def _translate_events(self, sdk_span: ReadableSpan) -> None: if sdk_span.events: self._collector_span_kwargs["events"] = [] @@ -170,7 +172,7 @@ def _translate_events(self, sdk_span: SDKSpan) -> None: collector_span_event ) - def _translate_links(self, sdk_span: SDKSpan) -> None: + def _translate_links(self, sdk_span: ReadableSpan) -> None: if sdk_span.links: self._collector_span_kwargs["links"] = [] @@ -196,7 +198,7 @@ def _translate_links(self, sdk_span: SDKSpan) -> None: collector_span_link ) - def _translate_status(self, sdk_span: SDKSpan) -> None: + def _translate_status(self, sdk_span: ReadableSpan) -> None: # pylint: disable=no-member if sdk_span.status is not None: deprecated_code = Status.DEPRECATED_STATUS_CODE_OK @@ -209,7 +211,7 @@ def _translate_status(self, sdk_span: SDKSpan) -> None: ) def _translate_data( - self, data: Sequence[SDKSpan] + self, data: Sequence[ReadableSpan] ) -> ExportTraceServiceRequest: # pylint: disable=attribute-defined-outside-init @@ -268,5 +270,5 @@ def _translate_data( ) ) - def export(self, spans: Sequence[SDKSpan]) -> SpanExportResult: + def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult: return self._export(spans) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index adafedb3da0..66e04482d50 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -89,7 +89,7 @@ def on_start( parent_context: The parent context of the span that just started. """ - def on_end(self, span: "Span") -> None: + def on_end(self, span: "ReadableSpan") -> None: """Called when a :class:`opentelemetry.trace.Span` is ended. This method is called synchronously on the thread that ends the @@ -100,8 +100,7 @@ def on_end(self, span: "Span") -> None: """ def shutdown(self) -> None: - """Called when a :class:`opentelemetry.sdk.trace.Tracer` is shutdown. - """ + """Called when a :class:`opentelemetry.sdk.trace.Tracer` is shutdown.""" def force_flush(self, timeout_millis: int = 30000) -> bool: """Export all ended spans to the configured Exporter that have not yet @@ -143,7 +142,7 @@ def on_start( for sp in self._span_processors: sp.on_start(span, parent_context=parent_context) - def on_end(self, span: "Span") -> None: + def on_end(self, span: "ReadableSpan") -> None: for sp in self._span_processors: sp.on_end(span) @@ -228,7 +227,7 @@ def on_start( lambda sp: sp.on_start, span, parent_context=parent_context ) - def on_end(self, span: "Span") -> None: + def on_end(self, span: "ReadableSpan") -> None: self._submit_and_await(lambda sp: sp.on_end, span) def shutdown(self) -> None: @@ -381,7 +380,7 @@ def _check_span_ended(func): def wrapper(self, *args, **kwargs): already_ended = False with self._lock: # pylint: disable=protected-access - if self.end_time is None: + if self._end_time is None: func(self, *args, **kwargs) else: already_ended = True @@ -392,7 +391,58 @@ def wrapper(self, *args, **kwargs): return wrapper -class Span(trace_api.Span): +class ReadableSpan: + """Provides read-only access to span attributes""" + + _name + _context + + @property + def name(self): + return self._name + + @property + def context(self): + return self._context + + @property + def kind(self): + return self._kind + + @property + def parent_id(self): + return self._parent_id + + @property + def start_time(self): + return self._start_time + + @property + def end_time(self): + return self._end_time + + @property + def status(self): + return self._status + + @property + def attributes(self): + return self._attributes + + @property + def events(self): + return self._events + + @property + def links(self): + return self._links + + @property + def resource(self): + return self._resource + + +class Span(trace_api.Span, ReadableSpan): """See `opentelemetry.trace.Span`. Users should create `Span` objects via the `Tracer` instead of this @@ -437,29 +487,29 @@ def __init__( set_status_on_exception: bool = True, ) -> None: - self.name = name - self.context = context + self._name = name + self._context = context self.parent = parent self.sampler = sampler self.trace_config = trace_config - self.resource = resource - self.kind = kind + self._resource = resource + self._kind = kind self._record_exception = record_exception self._set_status_on_exception = set_status_on_exception self.span_processor = span_processor - self.status = Status(StatusCode.UNSET) + self._status = Status(StatusCode.UNSET) self._lock = threading.Lock() _filter_attribute_values(attributes) if not attributes: - self.attributes = self._new_attributes() + self._attributes = self._new_attributes() else: - self.attributes = BoundedDict.from_map( + self._attributes = BoundedDict.from_map( SPAN_ATTRIBUTE_COUNT_LIMIT, attributes ) - self.events = self._new_events() + self._events = self._new_events() if events: for event in events: _filter_attribute_values(event.attributes) @@ -467,28 +517,20 @@ def __init__( event._attributes = _create_immutable_attributes( event.attributes ) - self.events.append(event) + self._events.append(event) if links is None: - self.links = self._new_links() + self._links = self._new_links() else: - self.links = BoundedList.from_seq(SPAN_LINK_COUNT_LIMIT, links) + self._links = BoundedList.from_seq(SPAN_LINK_COUNT_LIMIT, links) self._end_time = None # type: Optional[int] self._start_time = None # type: Optional[int] self.instrumentation_info = instrumentation_info - @property - def start_time(self): - return self._start_time - - @property - def end_time(self): - return self._end_time - def __repr__(self): return '{}(name="{}", context={})'.format( - type(self).__name__, self.name, self.context + type(self).__name__, self._name, self._context ) @staticmethod @@ -550,44 +592,44 @@ def to_json(self, indent=4): parent_id = trace_api.format_span_id(self.parent.span_id) start_time = None - if self.start_time: - start_time = util.ns_to_iso_str(self.start_time) + if self._start_time: + start_time = util.ns_to_iso_str(self._start_time) end_time = None - if self.end_time: - end_time = util.ns_to_iso_str(self.end_time) + if self._end_time: + end_time = util.ns_to_iso_str(self._end_time) - if self.status is not None: + if self._status is not None: status = OrderedDict() - status["status_code"] = str(self.status.status_code.name) - if self.status.description: - status["description"] = self.status.description + status["status_code"] = str(self._status.status_code.name) + if self._status.description: + status["description"] = self._status.description f_span = OrderedDict() - f_span["name"] = self.name - f_span["context"] = self._format_context(self.context) + f_span["name"] = self._name + f_span["context"] = self._format_context(self._context) f_span["kind"] = str(self.kind) f_span["parent_id"] = parent_id f_span["start_time"] = start_time f_span["end_time"] = end_time - if self.status is not None: + if self._status is not None: f_span["status"] = status - f_span["attributes"] = self._format_attributes(self.attributes) - f_span["events"] = self._format_events(self.events) - f_span["links"] = self._format_links(self.links) - f_span["resource"] = self.resource.attributes + f_span["attributes"] = self._format_attributes(self._attributes) + f_span["events"] = self._format_events(self._events) + f_span["links"] = self._format_links(self._links) + f_span["resource"] = self._resource.attributes return json.dumps(f_span, indent=indent) def get_span_context(self): - return self.context + return self._context def set_attributes( self, attributes: Dict[str, types.AttributeValue] ) -> None: with self._lock: - if self.end_time is not None: + if self._end_time is not None: logger.warning("Setting attribute on ended span.") return @@ -608,14 +650,14 @@ def set_attributes( except ValueError: logger.warning("Byte attribute could not be decoded.") return - self.attributes[key] = value + self._attributes[key] = value def set_attribute(self, key: str, value: types.AttributeValue) -> None: return self.set_attributes({key: value}) @_check_span_ended def _add_event(self, event: EventBase) -> None: - self.events.append(event) + self._events.append(event) def add_event( self, @@ -639,7 +681,7 @@ def start( parent_context: Optional[context_api.Context] = None, ) -> None: with self._lock: - if self.start_time is not None: + if self._start_time is not None: logger.warning("Calling start() on a started span.") return self._start_time = ( @@ -650,9 +692,9 @@ def start( def end(self, end_time: Optional[int] = None) -> None: with self._lock: - if self.start_time is None: + if self._start_time is None: raise RuntimeError("Calling end() on a not started span.") - if self.end_time is not None: + if self._end_time is not None: logger.warning("Calling end() on an ended span.") return @@ -662,14 +704,14 @@ def end(self, end_time: Optional[int] = None) -> None: @_check_span_ended def update_name(self, name: str) -> None: - self.name = name + self._name = name def is_recording(self) -> bool: return self._end_time is None @_check_span_ended def set_status(self, status: trace_api.Status) -> None: - self.status = status + self._status = status def __exit__( self, @@ -686,7 +728,7 @@ def __exit__( # Records status if span is used as context manager # i.e. with tracer.start_span() as span: if ( - self.status.status_code is StatusCode.UNSET + self._status.status_code is StatusCode.UNSET and self._set_status_on_exception ): self.set_status( @@ -880,7 +922,7 @@ def use_span( # Records status if use_span is used # i.e. with tracer.start_as_current_span() as span: if ( - span.status.status_code is StatusCode.UNSET + span._status.status_code is StatusCode.UNSET and span._set_status_on_exception ): span.set_status( diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py index ee63c84375f..9200a51c086 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py @@ -24,7 +24,7 @@ from opentelemetry.configuration import Configuration from opentelemetry.context import Context, attach, detach, set_value -from opentelemetry.sdk.trace import Span, SpanProcessor +from opentelemetry.sdk.trace import ReadableSpan, Span, SpanProcessor from opentelemetry.util import time_ns logger = logging.getLogger(__name__) @@ -45,7 +45,9 @@ class SpanExporter: `SimpleExportSpanProcessor` or a `BatchExportSpanProcessor`. """ - def export(self, spans: typing.Sequence[Span]) -> "SpanExportResult": + def export( + self, spans: typing.Sequence[ReadableSpan] + ) -> "SpanExportResult": """Exports a batch of telemetry data. Args: @@ -77,7 +79,7 @@ def on_start( ) -> None: pass - def on_end(self, span: Span) -> None: + def on_end(self, span: ReadableSpan) -> None: if not span.context.trace_flags.sampled: return token = attach(set_value("suppress_instrumentation", True)) @@ -181,7 +183,7 @@ def on_start( ) -> None: pass - def on_end(self, span: Span) -> None: + def on_end(self, span: ReadableSpan) -> None: if self.done: logger.warning("Already shutdown, dropping span.") return @@ -325,7 +327,7 @@ def _export_batch(self) -> int: return idx def _drain_queue(self): - """"Export all elements until queue is empty. + """Export all elements until queue is empty. Can only be called from the worker thread context because it invokes `export` that is not thread safe. @@ -374,14 +376,16 @@ def __init__( self, service_name: Optional[str] = None, out: typing.IO = sys.stdout, - formatter: typing.Callable[[Span], str] = lambda span: span.to_json() + formatter: typing.Callable[ + [ReadableSpan], str + ] = lambda span: span.to_json() + os.linesep, ): self.out = out self.formatter = formatter self.service_name = service_name - def export(self, spans: typing.Sequence[Span]) -> SpanExportResult: + def export(self, spans: typing.Sequence[ReadableSpan]) -> SpanExportResult: for span in spans: self.out.write(self.formatter(span)) self.out.flush() diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/in_memory_span_exporter.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/in_memory_span_exporter.py index 967d29b3a80..e46266b93b1 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/in_memory_span_exporter.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/in_memory_span_exporter.py @@ -15,7 +15,7 @@ import threading import typing -from opentelemetry.sdk.trace import Span +from opentelemetry.sdk.trace import ReadableSpan from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult @@ -42,7 +42,7 @@ def get_finished_spans(self): with self._lock: return tuple(self._finished_spans) - def export(self, spans: typing.Sequence[Span]) -> SpanExportResult: + def export(self, spans: typing.Sequence[ReadableSpan]) -> SpanExportResult: """Stores a list of spans in memory.""" if self._stopped: return SpanExportResult.FAILURE diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index d17bd2ef215..d1f7934db68 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -1128,7 +1128,7 @@ def on_start( ) -> None: self.span_list.append(span_event_start_fmt(self.name, span.name)) - def on_end(self, span: "trace.Span") -> None: + def on_end(self, span: "trace.ReadableSpan") -> None: self.span_list.append(span_event_end_fmt(self.name, span.name)) @@ -1234,7 +1234,7 @@ def test_to_json(self): trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED), ) span = trace._Span("span-name", context) - span.resource = Resource({}) + span._resource = Resource({}) # pylint: disable=protected-access self.assertEqual( span.to_json(), @@ -1271,7 +1271,7 @@ def test_attributes_to_json(self): trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED), ) span = trace._Span("span-name", context) - span.resource = Resource({}) + span._resource = Resource({}) # pylint: disable=protected-access span.set_attribute("key", "value") span.add_event("event", {"key2": "value2"}, 123) date_str = ns_to_iso_str(123) From d5143b004f5eff7aeb0b741784b3c7e49248eea9 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Mon, 1 Feb 2021 14:42:04 -0800 Subject: [PATCH 02/18] typo --- opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 66e04482d50..942dd8ef76c 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -394,9 +394,6 @@ def wrapper(self, *args, **kwargs): class ReadableSpan: """Provides read-only access to span attributes""" - _name - _context - @property def name(self): return self._name From c438281897af2c59ebe4e7ff21b8ed94f4904d3f Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Mon, 1 Feb 2021 14:50:44 -0800 Subject: [PATCH 03/18] fix tests --- .../tests/test_jaeger_exporter_protobuf.py | 6 +++--- .../tests/test_jaeger_exporter_thrift.py | 6 +++--- .../tests/test_zipkin_exporter.py | 20 +++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py index 26cfc41498e..3d807228158 100644 --- a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py +++ b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py @@ -171,7 +171,7 @@ def test_translate_to_jaeger(self): otel_spans[0].set_attribute("key_string", "hello_world") otel_spans[0].set_attribute("key_float", 111.22) otel_spans[0].set_attribute("key_tuple", ("tuple_element",)) - otel_spans[0].resource = Resource( + otel_spans[0]._resource = Resource( # pylint: disable=protected-member attributes={"key_resource": "some_resource"} ) otel_spans[0].set_status( @@ -180,11 +180,11 @@ def test_translate_to_jaeger(self): otel_spans[0].end(end_time=end_times[0]) otel_spans[1].start(start_time=start_times[1]) - otel_spans[1].resource = Resource({}) + otel_spans[1]._resource = Resource({}) # pylint: disable=protected-member otel_spans[1].end(end_time=end_times[1]) otel_spans[2].start(start_time=start_times[2]) - otel_spans[2].resource = Resource({}) + otel_spans[2]._resource = Resource({}) # pylint: disable=protected-member otel_spans[2].set_status(Status(StatusCode.OK, "Example description")) otel_spans[2].end(end_time=end_times[2]) otel_spans[2].instrumentation_info = InstrumentationInfo( diff --git a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py index 947597ab469..bc3ea32759a 100644 --- a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py +++ b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py @@ -250,7 +250,7 @@ def test_translate_to_jaeger(self): otel_spans[0].set_attribute("key_string", "hello_world") otel_spans[0].set_attribute("key_float", 111.22) otel_spans[0].set_attribute("key_tuple", ("tuple_element",)) - otel_spans[0].resource = Resource( + otel_spans[0]._resource = Resource( # pylint: disable=protected-member attributes={"key_resource": "some_resource"} ) otel_spans[0].set_status( @@ -259,11 +259,11 @@ def test_translate_to_jaeger(self): otel_spans[0].end(end_time=end_times[0]) otel_spans[1].start(start_time=start_times[1]) - otel_spans[1].resource = Resource({}) + otel_spans[1]._resource = Resource({}) # pylint: disable=protected-member otel_spans[1].end(end_time=end_times[1]) otel_spans[2].start(start_time=start_times[2]) - otel_spans[2].resource = Resource({}) + otel_spans[2]._resource = Resource({}) # pylint: disable=protected-member otel_spans[2].set_status(Status(StatusCode.OK, "Example description")) otel_spans[2].end(end_time=end_times[2]) otel_spans[2].instrumentation_info = InstrumentationInfo( diff --git a/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py b/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py index 5c2e0e7e4d0..341cecb28d4 100644 --- a/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py +++ b/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py @@ -202,7 +202,7 @@ def test_export_json(self): ] otel_spans[0].start(start_time=start_times[0]) - otel_spans[0].resource = Resource({}) + otel_spans[0]._resource = Resource({}) # pylint: disable=protected-member # added here to preserve order otel_spans[0].set_attribute("key_bool", False) otel_spans[0].set_attribute("key_string", "hello_world") @@ -213,20 +213,20 @@ def test_export_json(self): otel_spans[0].end(end_time=end_times[0]) otel_spans[1].start(start_time=start_times[1]) - otel_spans[1].resource = Resource( + otel_spans[1]._resource = Resource( # pylint: disable=protected-member attributes={"key_resource": "some_resource"} ) otel_spans[1].end(end_time=end_times[1]) otel_spans[2].start(start_time=start_times[2]) otel_spans[2].set_attribute("key_string", "hello_world") - otel_spans[2].resource = Resource( + otel_spans[2]._resource = Resource( # pylint: disable=protected-member attributes={"key_resource": "some_resource"} ) otel_spans[2].end(end_time=end_times[2]) otel_spans[3].start(start_time=start_times[3]) - otel_spans[3].resource = Resource({}) + otel_spans[3]._resource = Resource({}) # pylint: disable=protected-member otel_spans[3].end(end_time=end_times[3]) otel_spans[3].instrumentation_info = InstrumentationInfo( name="name", version="version" @@ -362,7 +362,7 @@ def test_export_json_zero_padding(self): ) otel_span.start(start_time=start_time) - otel_span.resource = Resource({}) + otel_span._resource = Resource({}) # pylint: disable=protected-member otel_span.end(end_time=end_time) service_name = "test-service" @@ -419,7 +419,7 @@ def test_export_json_max_tag_length(self): span = trace._Span(name="test-span", context=span_context,) span.start() - span.resource = Resource({}) + span._resource = Resource({}) # pylint: disable=protected-member # added here to preserve order span.set_attribute("string1", "v" * 500) span.set_attribute("string2", "v" * 50) @@ -719,7 +719,7 @@ def test_export_protobuf(self): ] otel_spans[0].start(start_time=start_times[0]) - otel_spans[0].resource = Resource({}) + otel_spans[0]._resource = Resource({}) # pylint: disable=protected-member # added here to preserve order otel_spans[0].set_attribute("key_bool", False) otel_spans[0].set_attribute("key_string", "hello_world") @@ -730,7 +730,7 @@ def test_export_protobuf(self): otel_spans[0].end(end_time=end_times[0]) otel_spans[1].start(start_time=start_times[1]) - otel_spans[1].resource = Resource( + otel_spans[1]._resource = Resource( # pylint: disable=protected-member attributes={"key_resource": "some_resource"} ) otel_spans[1].set_status(Status(StatusCode.OK)) @@ -738,13 +738,13 @@ def test_export_protobuf(self): otel_spans[2].start(start_time=start_times[2]) otel_spans[2].set_attribute("key_string", "hello_world") - otel_spans[2].resource = Resource( + otel_spans[2]._resource = Resource( # pylint: disable=protected-member attributes={"key_resource": "some_resource"} ) otel_spans[2].end(end_time=end_times[2]) otel_spans[3].start(start_time=start_times[3]) - otel_spans[3].resource = Resource({}) + otel_spans[3]._resource = Resource({}) # pylint: disable=protected-member otel_spans[3].end(end_time=end_times[3]) otel_spans[3].instrumentation_info = InstrumentationInfo( name="name", version="version" From 1b630a9bda1a9c44fb1eb32930b49da78521e4b7 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Mon, 1 Feb 2021 14:51:52 -0800 Subject: [PATCH 04/18] add changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f05dd7e832..4dc00e27046 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Allow missing carrier headers to continue without raising AttributeError ([#1545](https://github.com/open-telemetry/opentelemetry-python/pull/1545)) + +### Changed +- Read-only Span attributes have been moved to ReadableSpan class + ([#1560](https://github.com/open-telemetry/opentelemetry-python/pull/1560)) + ### Removed - Remove Configuration ([#1523](https://github.com/open-telemetry/opentelemetry-python/pull/1523)) From 4aa294f26fc7d2fa108550c88a54b1caccd7f9f0 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Mon, 1 Feb 2021 17:26:38 -0800 Subject: [PATCH 05/18] cleaning up tests --- .../tests/test_jaeger_exporter_protobuf.py | 18 +++-- .../tests/test_jaeger_exporter_thrift.py | 18 +++-- .../tests/test_zipkin_exporter.py | 69 +++++++++++-------- .../src/opentelemetry/sdk/trace/__init__.py | 26 +++---- .../sdk/trace/export/__init__.py | 6 +- opentelemetry-sdk/tests/trace/test_trace.py | 6 +- 6 files changed, 83 insertions(+), 60 deletions(-) diff --git a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py index 3d807228158..2dc53483795 100644 --- a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py +++ b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py @@ -156,12 +156,21 @@ def test_translate_to_jaeger(self): events=(event,), links=(link,), kind=trace_api.SpanKind.CLIENT, + resource=Resource( + attributes={"key_resource": "some_resource"} + ), ), trace._Span( - name=span_names[1], context=parent_span_context, parent=None + name=span_names[1], + context=parent_span_context, + parent=None, + resource=Resource({}), ), trace._Span( - name=span_names[2], context=other_context, parent=None + name=span_names[2], + context=other_context, + parent=None, + resource=Resource({}), ), ] @@ -171,20 +180,15 @@ def test_translate_to_jaeger(self): otel_spans[0].set_attribute("key_string", "hello_world") otel_spans[0].set_attribute("key_float", 111.22) otel_spans[0].set_attribute("key_tuple", ("tuple_element",)) - otel_spans[0]._resource = Resource( # pylint: disable=protected-member - attributes={"key_resource": "some_resource"} - ) otel_spans[0].set_status( Status(StatusCode.ERROR, "Example description") ) otel_spans[0].end(end_time=end_times[0]) otel_spans[1].start(start_time=start_times[1]) - otel_spans[1]._resource = Resource({}) # pylint: disable=protected-member otel_spans[1].end(end_time=end_times[1]) otel_spans[2].start(start_time=start_times[2]) - otel_spans[2]._resource = Resource({}) # pylint: disable=protected-member otel_spans[2].set_status(Status(StatusCode.OK, "Example description")) otel_spans[2].end(end_time=end_times[2]) otel_spans[2].instrumentation_info = InstrumentationInfo( diff --git a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py index bc3ea32759a..bfc690fb891 100644 --- a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py +++ b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py @@ -235,12 +235,21 @@ def test_translate_to_jaeger(self): events=(event,), links=(link,), kind=trace_api.SpanKind.CLIENT, + resource=Resource( + attributes={"key_resource": "some_resource"} + ), ), trace._Span( - name=span_names[1], context=parent_span_context, parent=None + name=span_names[1], + context=parent_span_context, + parent=None, + resource=Resource({}), ), trace._Span( - name=span_names[2], context=other_context, parent=None + name=span_names[2], + context=other_context, + parent=None, + resource=Resource({}), ), ] @@ -250,20 +259,15 @@ def test_translate_to_jaeger(self): otel_spans[0].set_attribute("key_string", "hello_world") otel_spans[0].set_attribute("key_float", 111.22) otel_spans[0].set_attribute("key_tuple", ("tuple_element",)) - otel_spans[0]._resource = Resource( # pylint: disable=protected-member - attributes={"key_resource": "some_resource"} - ) otel_spans[0].set_status( Status(StatusCode.ERROR, "Example description") ) otel_spans[0].end(end_time=end_times[0]) otel_spans[1].start(start_time=start_times[1]) - otel_spans[1]._resource = Resource({}) # pylint: disable=protected-member otel_spans[1].end(end_time=end_times[1]) otel_spans[2].start(start_time=start_times[2]) - otel_spans[2]._resource = Resource({}) # pylint: disable=protected-member otel_spans[2].set_status(Status(StatusCode.OK, "Example description")) otel_spans[2].end(end_time=end_times[2]) otel_spans[2].instrumentation_info = InstrumentationInfo( diff --git a/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py b/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py index 341cecb28d4..5c396058565 100644 --- a/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py +++ b/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py @@ -39,6 +39,7 @@ from opentelemetry.sdk.util.instrumentation import InstrumentationInfo from opentelemetry.trace import SpanKind, TraceFlags from opentelemetry.trace.status import Status, StatusCode +from pkg_resources import resource_exists class MockResponse: @@ -189,20 +190,33 @@ def test_export_json(self): parent=parent_span_context, events=(event,), links=(link,), + resource=Resource({}), ), trace._Span( - name=span_names[1], context=parent_span_context, parent=None + name=span_names[1], + context=parent_span_context, + parent=None, + resource=Resource( + attributes={"key_resource": "some_resource"} + ), ), trace._Span( - name=span_names[2], context=other_context, parent=None + name=span_names[2], + context=other_context, + parent=None, + resource=Resource( + attributes={"key_resource": "some_resource"} + ), ), trace._Span( - name=span_names[3], context=other_context, parent=None + name=span_names[3], + context=other_context, + parent=None, + resource=Resource({}), ), ] otel_spans[0].start(start_time=start_times[0]) - otel_spans[0]._resource = Resource({}) # pylint: disable=protected-member # added here to preserve order otel_spans[0].set_attribute("key_bool", False) otel_spans[0].set_attribute("key_string", "hello_world") @@ -213,20 +227,13 @@ def test_export_json(self): otel_spans[0].end(end_time=end_times[0]) otel_spans[1].start(start_time=start_times[1]) - otel_spans[1]._resource = Resource( # pylint: disable=protected-member - attributes={"key_resource": "some_resource"} - ) otel_spans[1].end(end_time=end_times[1]) otel_spans[2].start(start_time=start_times[2]) otel_spans[2].set_attribute("key_string", "hello_world") - otel_spans[2]._resource = Resource( # pylint: disable=protected-member - attributes={"key_resource": "some_resource"} - ) otel_spans[2].end(end_time=end_times[2]) otel_spans[3].start(start_time=start_times[3]) - otel_spans[3]._resource = Resource({}) # pylint: disable=protected-member otel_spans[3].end(end_time=end_times[3]) otel_spans[3].instrumentation_info = InstrumentationInfo( name="name", version="version" @@ -359,10 +366,10 @@ def test_export_json_zero_padding(self): name=span_names[0], context=span_context, parent=parent_span_context, + resource=Resource({}), ) otel_span.start(start_time=start_time) - otel_span._resource = Resource({}) # pylint: disable=protected-member otel_span.end(end_time=end_time) service_name = "test-service" @@ -416,10 +423,11 @@ def test_export_json_max_tag_length(self): trace_flags=TraceFlags(TraceFlags.SAMPLED), ) - span = trace._Span(name="test-span", context=span_context,) + span = trace._Span( + name="test-span", context=span_context, resource=Resource({}) + ) span.start() - span._resource = Resource({}) # pylint: disable=protected-member # added here to preserve order span.set_attribute("string1", "v" * 500) span.set_attribute("string2", "v" * 50) @@ -704,22 +712,35 @@ def test_export_protobuf(self): name=span_names[0], context=span_context, parent=parent_span_context, + resource=Resource({}), events=(event,), links=(link,), ), trace._Span( - name=span_names[1], context=parent_span_context, parent=None + name=span_names[1], + context=parent_span_context, + parent=None, + resource=Resource( + attributes={"key_resource": "some_resource"} + ), ), trace._Span( - name=span_names[2], context=other_context, parent=None + name=span_names[2], + context=other_context, + parent=None, + resource=Resource( + attributes={"key_resource": "some_resource"} + ), ), trace._Span( - name=span_names[3], context=other_context, parent=None + name=span_names[3], + context=other_context, + parent=None, + resource=Resource({}), ), ] otel_spans[0].start(start_time=start_times[0]) - otel_spans[0]._resource = Resource({}) # pylint: disable=protected-member # added here to preserve order otel_spans[0].set_attribute("key_bool", False) otel_spans[0].set_attribute("key_string", "hello_world") @@ -730,21 +751,14 @@ def test_export_protobuf(self): otel_spans[0].end(end_time=end_times[0]) otel_spans[1].start(start_time=start_times[1]) - otel_spans[1]._resource = Resource( # pylint: disable=protected-member - attributes={"key_resource": "some_resource"} - ) otel_spans[1].set_status(Status(StatusCode.OK)) otel_spans[1].end(end_time=end_times[1]) otel_spans[2].start(start_time=start_times[2]) otel_spans[2].set_attribute("key_string", "hello_world") - otel_spans[2]._resource = Resource( # pylint: disable=protected-member - attributes={"key_resource": "some_resource"} - ) otel_spans[2].end(end_time=end_times[2]) otel_spans[3].start(start_time=start_times[3]) - otel_spans[3]._resource = Resource({}) # pylint: disable=protected-member otel_spans[3].end(end_time=end_times[3]) otel_spans[3].instrumentation_info = InstrumentationInfo( name="name", version="version" @@ -869,10 +883,11 @@ def test_export_protobuf_max_tag_length(self): trace_flags=TraceFlags(TraceFlags.SAMPLED), ) - span = trace._Span(name="test-span", context=span_context,) + span = trace._Span( + name="test-span", context=span_context, resource=Resource({}) + ) span.start() - span.resource = Resource({}) # added here to preserve order span.set_attribute("k1", "v" * 500) span.set_attribute("k2", "v" * 50) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 9379c1d20da..eb8b9a1dfd5 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -401,47 +401,47 @@ class ReadableSpan: """Provides read-only access to span attributes""" @property - def name(self): + def name(self) -> str: return self._name @property - def context(self): + def context(self) -> trace_api.SpanContext: return self._context @property - def kind(self): + def kind(self) -> trace_api.SpanKind: return self._kind @property - def parent_id(self): - return self._parent_id + def parent(self) -> Optional[trace_api.SpanContext]: + return self._parent @property - def start_time(self): + def start_time(self) -> Optional[int]: return self._start_time @property - def end_time(self): + def end_time(self) -> Optional[int]: return self._end_time @property - def status(self): + def status(self) -> trace_api.Status: return self._status @property - def attributes(self): + def attributes(self) -> types.Attributes: return self._attributes @property - def events(self): + def events(self) -> Sequence[Event]: return self._events @property - def links(self): + def links(self) -> Sequence[trace_api.Link]: return self._links @property - def resource(self): + def resource(self) -> Resource: return self._resource @@ -492,7 +492,7 @@ def __init__( self._name = name self._context = context - self.parent = parent + self._parent = parent self.sampler = sampler self.trace_config = trace_config self._resource = resource diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py index 9ec47995df4..932d05f2335 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/export/__init__.py @@ -28,7 +28,7 @@ OTEL_BSP_MAX_QUEUE_SIZE, OTEL_BSP_SCHEDULE_DELAY, ) -from opentelemetry.sdk.trace import ReadableSpan,Span, SpanProcessor +from opentelemetry.sdk.trace import ReadableSpan, Span, SpanProcessor from opentelemetry.util import time_ns logger = logging.getLogger(__name__) @@ -380,7 +380,9 @@ def __init__( self, service_name: Optional[str] = None, out: typing.IO = sys.stdout, - formatter: typing.Callable[[ReadableSpan], str] = lambda span: span.to_json() + formatter: typing.Callable[ + [ReadableSpan], str + ] = lambda span: span.to_json() + linesep, ): self.out = out diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index a8037f3bea8..b0482600034 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -1237,8 +1237,7 @@ def test_to_json(self): is_remote=False, trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED), ) - span = trace._Span("span-name", context) - span._resource = Resource({}) # pylint: disable=protected-access + span = trace._Span("span-name", context, resource=Resource({})) self.assertEqual( span.to_json(), @@ -1274,8 +1273,7 @@ def test_attributes_to_json(self): is_remote=False, trace_flags=trace_api.TraceFlags(trace_api.TraceFlags.SAMPLED), ) - span = trace._Span("span-name", context) - span._resource = Resource({}) # pylint: disable=protected-access + span = trace._Span("span-name", context, resource=Resource({})) span.set_attribute("key", "value") span.add_event("event", {"key2": "value2"}, 123) date_str = ns_to_iso_str(123) From 8e9977aa20f6a7c08f610cb6cf8a1953d5f6b149 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Mon, 1 Feb 2021 20:59:59 -0800 Subject: [PATCH 06/18] update sha --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fa9272e9f4d..9a2ee3cbc29 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ env: # Otherwise, set variable to the commit of your branch on # opentelemetry-python-contrib which is compatible with these Core repo # changes. - CONTRIB_REPO_SHA: f005d90ed3bc75ee6eb7297f9e3a6b55a55b22aa + CONTRIB_REPO_SHA: 2379533256b9ab3d0483412e6be660a9deb2db86 jobs: build: From 25671176003327dba3cd3cf239aa90ce68bd878c Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Tue, 2 Feb 2021 10:48:31 -0800 Subject: [PATCH 07/18] return proxy instead of the dict directly --- .../src/opentelemetry/sdk/trace/__init__.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index eb8b9a1dfd5..a40dcda66f4 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -430,15 +430,15 @@ def status(self) -> trace_api.Status: @property def attributes(self) -> types.Attributes: - return self._attributes + return MappingProxyType(self._attributes) @property def events(self) -> Sequence[Event]: - return self._events + return MappingProxyType(self._events) @property def links(self) -> Sequence[trace_api.Link]: - return self._links + return MappingProxyType(self._links) @property def resource(self) -> Resource: @@ -776,7 +776,8 @@ def record_exception( class _Span(Span): """Protected implementation of `opentelemetry.trace.Span`. - This constructor should only be used internally. + This constructor exists to prevent the instantiation of the `Span` class + by other mechanisms than through the `Tracer`. """ From 86eda5f423f9f2e738973983f3fef914b31d4fec Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Tue, 2 Feb 2021 10:59:38 -0800 Subject: [PATCH 08/18] remove unused import --- .../opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py | 1 - 1 file changed, 1 deletion(-) diff --git a/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py b/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py index 5c396058565..8eb6db4605e 100644 --- a/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py +++ b/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py @@ -39,7 +39,6 @@ from opentelemetry.sdk.util.instrumentation import InstrumentationInfo from opentelemetry.trace import SpanKind, TraceFlags from opentelemetry.trace.status import Status, StatusCode -from pkg_resources import resource_exists class MockResponse: From 60fcbaaa76f4ce9c56b426ebe167f256d7b9b72f Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Tue, 2 Feb 2021 21:16:44 -0800 Subject: [PATCH 09/18] return readable span on_end --- .../src/opentelemetry/sdk/trace/__init__.py | 70 +++++++++++++------ .../tests/context/test_asyncio.py | 2 +- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index a40dcda66f4..3c2562da90e 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - +# pylint: disable=too-many-lines import abc import atexit import concurrent.futures @@ -153,8 +153,7 @@ def on_end(self, span: "ReadableSpan") -> None: sp.on_end(span) def shutdown(self) -> None: - """Sequentially shuts down all underlying span processors. - """ + """Sequentially shuts down all underlying span processors.""" for sp in self._span_processors: sp.shutdown() @@ -400,12 +399,36 @@ def wrapper(self, *args, **kwargs): class ReadableSpan: """Provides read-only access to span attributes""" + def __init__( + self, + name: str = None, + context: trace_api.SpanContext = None, + parent: Optional[trace_api.SpanContext] = None, + resource: Resource = Resource.create({}), + attributes: types.Attributes = None, + events: Sequence[Event] = None, + links: Sequence[trace_api.Link] = (), + kind: trace_api.SpanKind = trace_api.SpanKind.INTERNAL, + status: Status = Status(StatusCode.UNSET), + ) -> None: + self._name = name + self._context = context + self._kind = kind + self._parent = parent + self._start_time = None # type: Optional[int] + self._end_time = None # type: Optional[int] + self._attributes = attributes + self._events = events + self._links = links + self._resource = resource + self._status = status + @property def name(self) -> str: return self._name @property - def context(self) -> trace_api.SpanContext: + def context(self): return self._context @property @@ -489,19 +512,18 @@ def __init__( record_exception: bool = True, set_status_on_exception: bool = True, ) -> None: - - self._name = name - self._context = context - self._parent = parent + super().__init__( + name=name, + context=context, + parent=parent, + kind=kind, + resource=resource, + ) self.sampler = sampler self.trace_config = trace_config - self._resource = resource - self._kind = kind self._record_exception = record_exception self._set_status_on_exception = set_status_on_exception - self.span_processor = span_processor - self._status = Status(StatusCode.UNSET) self._lock = threading.Lock() _filter_attribute_values(attributes) @@ -526,9 +548,6 @@ def __init__( self._links = self._new_links() else: self._links = BoundedList.from_seq(SPAN_LINK_COUNT_LIMIT, links) - - self._end_time = None # type: Optional[int] - self._start_time = None # type: Optional[int] self.instrumentation_info = instrumentation_info def __repr__(self): @@ -678,6 +697,19 @@ def add_event( ) ) + def _readable_span(self) -> ReadableSpan: + return ReadableSpan( + name=self._name, + context=self._context, + parent=self._parent, + resource=self._resource, + attributes=self._attributes, + events=self._events, + links=self._links, + kind=self.kind, + status=self._status, + ) + def start( self, start_time: Optional[int] = None, @@ -703,7 +735,7 @@ def end(self, end_time: Optional[int] = None) -> None: self._end_time = end_time if end_time is not None else time_ns() - self.span_processor.on_end(self) + self.span_processor.on_end(self._readable_span()) @_check_span_ended def update_name(self, name: str) -> None: @@ -782,8 +814,7 @@ class _Span(Span): class Tracer(trace_api.Tracer): - """See `opentelemetry.trace.Tracer`. - """ + """See `opentelemetry.trace.Tracer`.""" def __init__( self, @@ -945,8 +976,7 @@ def use_span( class TracerProvider(trace_api.TracerProvider): - """See `opentelemetry.trace.TracerProvider`. - """ + """See `opentelemetry.trace.TracerProvider`.""" def __init__( self, diff --git a/opentelemetry-sdk/tests/context/test_asyncio.py b/opentelemetry-sdk/tests/context/test_asyncio.py index c235e71d83e..7f9539738ca 100644 --- a/opentelemetry-sdk/tests/context/test_asyncio.py +++ b/opentelemetry-sdk/tests/context/test_asyncio.py @@ -109,4 +109,4 @@ def test_with_asyncio(self): for span in span_list: if span is expected_parent: continue - self.assertEqual(span.parent, expected_parent.get_span_context()) + self.assertEqual(span.parent, expected_parent.context) From ef186c147bf30923be9b0887c497fd1448b9d4c0 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Fri, 5 Feb 2021 12:57:28 -0800 Subject: [PATCH 10/18] move to_json out of sdk span, into readable span --- .../src/opentelemetry/sdk/trace/__init__.py | 162 +++++++++--------- .../tests/testbed/testcase.py | 8 +- 2 files changed, 87 insertions(+), 83 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 3c2562da90e..4b72902cc81 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -410,13 +410,15 @@ def __init__( links: Sequence[trace_api.Link] = (), kind: trace_api.SpanKind = trace_api.SpanKind.INTERNAL, status: Status = Status(StatusCode.UNSET), + start_time: Optional[int] = None, + end_time: Optional[int] = None, ) -> None: self._name = name self._context = context self._kind = kind self._parent = parent - self._start_time = None # type: Optional[int] - self._end_time = None # type: Optional[int] + self._start_time = start_time + self._end_time = end_time self._attributes = attributes self._events = events self._links = links @@ -467,6 +469,83 @@ def links(self) -> Sequence[trace_api.Link]: def resource(self) -> Resource: return self._resource + def to_json(self, indent=4): + parent_id = None + if self.parent is not None: + if isinstance(self.parent, Span): + ctx = self.parent.context + parent_id = trace_api.format_span_id(ctx.span_id) + elif isinstance(self.parent, SpanContext): + parent_id = trace_api.format_span_id(self.parent.span_id) + + start_time = None + if self._start_time: + start_time = util.ns_to_iso_str(self._start_time) + + end_time = None + if self._end_time: + end_time = util.ns_to_iso_str(self._end_time) + + if self._status is not None: + status = OrderedDict() + status["status_code"] = str(self._status.status_code.name) + if self._status.description: + status["description"] = self._status.description + + f_span = OrderedDict() + + f_span["name"] = self._name + f_span["context"] = self._format_context(self._context) + f_span["kind"] = str(self.kind) + f_span["parent_id"] = parent_id + f_span["start_time"] = start_time + f_span["end_time"] = end_time + if self._status is not None: + f_span["status"] = status + f_span["attributes"] = self._format_attributes(self._attributes) + f_span["events"] = self._format_events(self._events) + f_span["links"] = self._format_links(self._links) + f_span["resource"] = self._resource.attributes + + return json.dumps(f_span, indent=indent) + + @staticmethod + def _format_context(context): + x_ctx = OrderedDict() + x_ctx["trace_id"] = trace_api.format_trace_id(context.trace_id) + x_ctx["span_id"] = trace_api.format_span_id(context.span_id) + x_ctx["trace_state"] = repr(context.trace_state) + return x_ctx + + @staticmethod + def _format_attributes(attributes): + if isinstance(attributes, BoundedDict): + return attributes._dict # pylint: disable=protected-access + if isinstance(attributes, MappingProxyType): + return attributes.copy() + return attributes + + @staticmethod + def _format_events(events): + f_events = [] + for event in events: + f_event = OrderedDict() + f_event["name"] = event.name + f_event["timestamp"] = util.ns_to_iso_str(event.timestamp) + f_event["attributes"] = Span._format_attributes(event.attributes) + f_events.append(f_event) + return f_events + + @staticmethod + def _format_links(links): + f_links = [] + for link in links: + f_link = OrderedDict() + f_link["context"] = Span._format_context(link.context) + f_link["attributes"] = Span._format_attributes(link.attributes) + f_links.append(f_link) + return f_links + class Span(trace_api.Span, ReadableSpan): """See `opentelemetry.trace.Span`. @@ -567,83 +646,6 @@ def _new_events(): def _new_links(): return BoundedList(SPAN_LINK_COUNT_LIMIT) - @staticmethod - def _format_context(context): - x_ctx = OrderedDict() - x_ctx["trace_id"] = trace_api.format_trace_id(context.trace_id) - x_ctx["span_id"] = trace_api.format_span_id(context.span_id) - x_ctx["trace_state"] = repr(context.trace_state) - return x_ctx - - @staticmethod - def _format_attributes(attributes): - if isinstance(attributes, BoundedDict): - return attributes._dict # pylint: disable=protected-access - if isinstance(attributes, MappingProxyType): - return attributes.copy() - return attributes - - @staticmethod - def _format_events(events): - f_events = [] - for event in events: - f_event = OrderedDict() - f_event["name"] = event.name - f_event["timestamp"] = util.ns_to_iso_str(event.timestamp) - f_event["attributes"] = Span._format_attributes(event.attributes) - f_events.append(f_event) - return f_events - - @staticmethod - def _format_links(links): - f_links = [] - for link in links: - f_link = OrderedDict() - f_link["context"] = Span._format_context(link.context) - f_link["attributes"] = Span._format_attributes(link.attributes) - f_links.append(f_link) - return f_links - - def to_json(self, indent=4): - parent_id = None - if self.parent is not None: - if isinstance(self.parent, Span): - ctx = self.parent.context - parent_id = trace_api.format_span_id(ctx.span_id) - elif isinstance(self.parent, SpanContext): - parent_id = trace_api.format_span_id(self.parent.span_id) - - start_time = None - if self._start_time: - start_time = util.ns_to_iso_str(self._start_time) - - end_time = None - if self._end_time: - end_time = util.ns_to_iso_str(self._end_time) - - if self._status is not None: - status = OrderedDict() - status["status_code"] = str(self._status.status_code.name) - if self._status.description: - status["description"] = self._status.description - - f_span = OrderedDict() - - f_span["name"] = self._name - f_span["context"] = self._format_context(self._context) - f_span["kind"] = str(self.kind) - f_span["parent_id"] = parent_id - f_span["start_time"] = start_time - f_span["end_time"] = end_time - if self._status is not None: - f_span["status"] = status - f_span["attributes"] = self._format_attributes(self._attributes) - f_span["events"] = self._format_events(self._events) - f_span["links"] = self._format_links(self._links) - f_span["resource"] = self._resource.attributes - - return json.dumps(f_span, indent=indent) - def get_span_context(self): return self._context @@ -708,6 +710,8 @@ def _readable_span(self) -> ReadableSpan: links=self._links, kind=self.kind, status=self._status, + start_time=self._start_time, + end_time=self._end_time, ) def start( diff --git a/shim/opentelemetry-opentracing-shim/tests/testbed/testcase.py b/shim/opentelemetry-opentracing-shim/tests/testbed/testcase.py index c1ce6ea5abd..3c16682fad3 100644 --- a/shim/opentelemetry-opentracing-shim/tests/testbed/testcase.py +++ b/shim/opentelemetry-opentracing-shim/tests/testbed/testcase.py @@ -18,11 +18,11 @@ def assertIsChildOf(self, spanA, spanB): self.assertIsNotNone(spanA.parent) ctxA = spanA.parent - if isinstance(spanA.parent, trace_api.Span): + if not isinstance(ctxA, trace_api.SpanContext): ctxA = spanA.parent.context ctxB = spanB - if isinstance(ctxB, trace_api.Span): + if not isinstance(ctxB, trace_api.SpanContext): ctxB = spanB.context return self.assertEqual(ctxA.span_id, ctxB.span_id) @@ -33,11 +33,11 @@ def assertIsNotChildOf(self, spanA, spanB): return ctxA = spanA.parent - if isinstance(spanA.parent, trace_api.Span): + if not isinstance(ctxA, trace_api.SpanContext): ctxA = spanA.parent.context ctxB = spanB - if isinstance(ctxB, trace_api.Span): + if not isinstance(ctxB, trace_api.SpanContext): ctxB = spanB.context self.assertNotEqual(ctxA.span_id, ctxB.span_id) From 0d49d957945b14d85ea00ba70fef8501092b2ea5 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Fri, 5 Feb 2021 14:17:28 -0800 Subject: [PATCH 11/18] move instrumentation_info --- .../src/opentelemetry/sdk/trace/__init__.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 4b72902cc81..5fa9a5e6f11 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -409,6 +409,7 @@ def __init__( events: Sequence[Event] = None, links: Sequence[trace_api.Link] = (), kind: trace_api.SpanKind = trace_api.SpanKind.INTERNAL, + instrumentation_info: InstrumentationInfo = None, status: Status = Status(StatusCode.UNSET), start_time: Optional[int] = None, end_time: Optional[int] = None, @@ -416,6 +417,7 @@ def __init__( self._name = name self._context = context self._kind = kind + self._instrumentation_info = instrumentation_info self._parent = parent self._start_time = start_time self._end_time = end_time @@ -429,6 +431,9 @@ def __init__( def name(self) -> str: return self._name + def get_span_context(self): + return self._context + @property def context(self): return self._context @@ -469,6 +474,10 @@ def links(self) -> Sequence[trace_api.Link]: def resource(self) -> Resource: return self._resource + @property + def instrumentation_info(self) -> InstrumentationInfo: + return self._instrumentation_info + def to_json(self, indent=4): parent_id = None if self.parent is not None: @@ -597,6 +606,7 @@ def __init__( parent=parent, kind=kind, resource=resource, + instrumentation_info=instrumentation_info, ) self.sampler = sampler self.trace_config = trace_config @@ -627,7 +637,6 @@ def __init__( self._links = self._new_links() else: self._links = BoundedList.from_seq(SPAN_LINK_COUNT_LIMIT, links) - self.instrumentation_info = instrumentation_info def __repr__(self): return '{}(name="{}", context={})'.format( @@ -712,6 +721,7 @@ def _readable_span(self) -> ReadableSpan: status=self._status, start_time=self._start_time, end_time=self._end_time, + instrumentation_info=self._instrumentation_info, ) def start( From b7658a6f8eb7616fe5eede61e03a92d2a59694a2 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Mon, 8 Feb 2021 20:17:48 -0800 Subject: [PATCH 12/18] fix tests --- .../tests/test_jaeger_exporter_protobuf.py | 6 +++--- .../tests/test_jaeger_exporter_thrift.py | 6 +++--- .../tests/test_zipkin_exporter.py | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py index 2dc53483795..80cbdfb55dd 100644 --- a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py +++ b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_protobuf.py @@ -171,6 +171,9 @@ def test_translate_to_jaeger(self): context=other_context, parent=None, resource=Resource({}), + instrumentation_info=InstrumentationInfo( + name="name", version="version" + ), ), ] @@ -191,9 +194,6 @@ def test_translate_to_jaeger(self): otel_spans[2].start(start_time=start_times[2]) otel_spans[2].set_status(Status(StatusCode.OK, "Example description")) otel_spans[2].end(end_time=end_times[2]) - otel_spans[2].instrumentation_info = InstrumentationInfo( - name="name", version="version" - ) translate = Translate(otel_spans) # pylint: disable=protected-access diff --git a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py index bfc690fb891..c0faafc1b6e 100644 --- a/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py +++ b/exporter/opentelemetry-exporter-jaeger/tests/test_jaeger_exporter_thrift.py @@ -250,6 +250,9 @@ def test_translate_to_jaeger(self): context=other_context, parent=None, resource=Resource({}), + instrumentation_info=InstrumentationInfo( + name="name", version="version" + ), ), ] @@ -270,9 +273,6 @@ def test_translate_to_jaeger(self): otel_spans[2].start(start_time=start_times[2]) otel_spans[2].set_status(Status(StatusCode.OK, "Example description")) otel_spans[2].end(end_time=end_times[2]) - otel_spans[2].instrumentation_info = InstrumentationInfo( - name="name", version="version" - ) translate = Translate(otel_spans) # pylint: disable=protected-access diff --git a/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py b/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py index 8eb6db4605e..36320b78c38 100644 --- a/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py +++ b/exporter/opentelemetry-exporter-zipkin/tests/test_zipkin_exporter.py @@ -212,6 +212,9 @@ def test_export_json(self): context=other_context, parent=None, resource=Resource({}), + instrumentation_info=InstrumentationInfo( + name="name", version="version" + ), ), ] @@ -234,9 +237,6 @@ def test_export_json(self): otel_spans[3].start(start_time=start_times[3]) otel_spans[3].end(end_time=end_times[3]) - otel_spans[3].instrumentation_info = InstrumentationInfo( - name="name", version="version" - ) service_name = "test-service" local_endpoint = {"serviceName": service_name, "port": 9411} @@ -736,6 +736,9 @@ def test_export_protobuf(self): context=other_context, parent=None, resource=Resource({}), + instrumentation_info=InstrumentationInfo( + name="name", version="version" + ), ), ] @@ -759,9 +762,6 @@ def test_export_protobuf(self): otel_spans[3].start(start_time=start_times[3]) otel_spans[3].end(end_time=end_times[3]) - otel_spans[3].instrumentation_info = InstrumentationInfo( - name="name", version="version" - ) service_name = "test-service" local_endpoint = zipkin_pb2.Endpoint( From a3c2feedc0820b42a86c890b022aa82cdd2fc21a Mon Sep 17 00:00:00 2001 From: alrex Date: Mon, 8 Feb 2021 21:02:41 -0800 Subject: [PATCH 13/18] Update test.yml --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 72fc1d52367..e3096a8775d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ env: # Otherwise, set variable to the commit of your branch on # opentelemetry-python-contrib which is compatible with these Core repo # changes. - CONTRIB_REPO_SHA: main + CONTRIB_REPO_SHA: aade876a94f0efe712aaf4a3f4827065e1edd64a jobs: build: From 54872e9bf7bb1ae434dbcc25b2c733022bd5f271 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Mon, 8 Feb 2021 21:13:35 -0800 Subject: [PATCH 14/18] forcing docs to recreate tox env --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index f6e2e18aaa4..9f30b408310 100644 --- a/tox.ini +++ b/tox.ini @@ -171,6 +171,7 @@ commands = python scripts/eachdist.py lint --check-only [testenv:docs] +recreate = True deps = -c {toxinidir}/dev-requirements.txt -r {toxinidir}/docs-requirements.txt From f87e44f4e3d080e34182b3fdef0e51729fe219f0 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Tue, 9 Feb 2021 08:43:26 -0800 Subject: [PATCH 15/18] protect more members --- .../src/opentelemetry/sdk/trace/__init__.py | 10 +++++----- opentelemetry-sdk/tests/trace/test_trace.py | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py index 5fa9a5e6f11..0a6eefbd843 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py @@ -608,11 +608,11 @@ def __init__( resource=resource, instrumentation_info=instrumentation_info, ) - self.sampler = sampler - self.trace_config = trace_config + self._sampler = sampler + self._trace_config = trace_config self._record_exception = record_exception self._set_status_on_exception = set_status_on_exception - self.span_processor = span_processor + self._span_processor = span_processor self._lock = threading.Lock() _filter_attribute_values(attributes) @@ -737,7 +737,7 @@ def start( start_time if start_time is not None else time_ns() ) - self.span_processor.on_start(self, parent_context=parent_context) + self._span_processor.on_start(self, parent_context=parent_context) def end(self, end_time: Optional[int] = None) -> None: with self._lock: @@ -749,7 +749,7 @@ def end(self, end_time: Optional[int] = None) -> None: self._end_time = end_time if end_time is not None else time_ns() - self.span_processor.on_end(self._readable_span()) + self._span_processor.on_end(self._readable_span()) @_check_span_ended def update_name(self, name: str) -> None: diff --git a/opentelemetry-sdk/tests/trace/test_trace.py b/opentelemetry-sdk/tests/trace/test_trace.py index b0482600034..6969b65b116 100644 --- a/opentelemetry-sdk/tests/trace/test_trace.py +++ b/opentelemetry-sdk/tests/trace/test_trace.py @@ -289,10 +289,10 @@ def test_span_processor_for_source(self): # pylint:disable=protected-access self.assertIs( - span1.span_processor, tracer_provider._active_span_processor + span1._span_processor, tracer_provider._active_span_processor ) self.assertIs( - span2.span_processor, tracer_provider._active_span_processor + span2._span_processor, tracer_provider._active_span_processor ) def test_start_span_implicit(self): From 2c152c8f305df9b3ed78e5b6dcb3da846b080bd0 Mon Sep 17 00:00:00 2001 From: alrex Date: Tue, 9 Feb 2021 09:53:04 -0800 Subject: [PATCH 16/18] Update test.yml --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e3096a8775d..dfa5f957bd7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ env: # Otherwise, set variable to the commit of your branch on # opentelemetry-python-contrib which is compatible with these Core repo # changes. - CONTRIB_REPO_SHA: aade876a94f0efe712aaf4a3f4827065e1edd64a + CONTRIB_REPO_SHA: 263adc5f7f524fae2c84571f656cef0896de0868 jobs: build: From fffa60ab101634eb4430f035faeb17d45bd63446 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Tue, 9 Feb 2021 11:06:51 -0800 Subject: [PATCH 17/18] Links should be None --- opentelemetry-api/src/opentelemetry/trace/__init__.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index b579e5ccf78..112075dd26d 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -138,6 +138,7 @@ def __init__( def attributes(self) -> types.Attributes: return self._attributes +_Links = typing.Optional[typing.Sequence[Link]] class SpanKind(enum.Enum): """Specifies additional details on how this span relates to its parent span. @@ -231,7 +232,7 @@ def start_span( context: typing.Optional[Context] = None, kind: SpanKind = SpanKind.INTERNAL, attributes: types.Attributes = None, - links: typing.Sequence[Link] = (), + links: _Links = None, start_time: typing.Optional[int] = None, record_exception: bool = True, set_status_on_exception: bool = True, @@ -286,7 +287,7 @@ def start_as_current_span( context: typing.Optional[Context] = None, kind: SpanKind = SpanKind.INTERNAL, attributes: types.Attributes = None, - links: typing.Sequence[Link] = (), + links: _Links = None, start_time: typing.Optional[int] = None, record_exception: bool = True, set_status_on_exception: bool = True, @@ -380,7 +381,7 @@ def start_span( context: typing.Optional[Context] = None, kind: SpanKind = SpanKind.INTERNAL, attributes: types.Attributes = None, - links: typing.Sequence[Link] = (), + links: _Links = None, start_time: typing.Optional[int] = None, record_exception: bool = True, set_status_on_exception: bool = True, @@ -395,7 +396,7 @@ def start_as_current_span( context: typing.Optional[Context] = None, kind: SpanKind = SpanKind.INTERNAL, attributes: types.Attributes = None, - links: typing.Sequence[Link] = (), + links: _Links = None, start_time: typing.Optional[int] = None, record_exception: bool = True, set_status_on_exception: bool = True, From 3a69b1da9444e77cba5b8dab3de839e02e5716f2 Mon Sep 17 00:00:00 2001 From: Alex Boten Date: Tue, 9 Feb 2021 12:52:05 -0800 Subject: [PATCH 18/18] fix lint --- opentelemetry-api/src/opentelemetry/trace/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 112075dd26d..218c8256f0d 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -138,8 +138,10 @@ def __init__( def attributes(self) -> types.Attributes: return self._attributes + _Links = typing.Optional[typing.Sequence[Link]] + class SpanKind(enum.Enum): """Specifies additional details on how this span relates to its parent span.