From 6b3e057e4b40e4fec4896f35ca7abc70638bf1c6 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Wed, 26 Jun 2019 20:05:04 +0200 Subject: [PATCH 1/6] Initial support for explicit Span parent support. --- .../opentelemetry/trace/__init__.py | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/opentelemetry-api/opentelemetry/trace/__init__.py b/opentelemetry-api/opentelemetry/trace/__init__.py index 282bc72b3f0..66944372892 100644 --- a/opentelemetry-api/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/opentelemetry/trace/__init__.py @@ -73,6 +73,11 @@ class Tracer: and controlling spans' lifecycles. """ + """Constant used to represent the current span being used as a parent. + This is the default behavior when creating spans. + """ + CURRENT_SPAN = object() + def get_current_span(self) -> 'Span': """Gets the currently active span from the context. @@ -84,15 +89,19 @@ def get_current_span(self) -> 'Span': invalid :class:`.SpanContext`. """ - @contextmanager - def start_span(self, name: str, parent: 'Span') -> Iterator['Span']: + def start_span(self, + name: str, + parent: 'Span' = CURRENT_SPAN) -> Iterator['Span']: """Context manager for span creation. - Create a new child of the current span, or create a root span if no - current span exists. Start the span and set it as the current span in + Create a new span. Start the span and set it as the current span in this tracer's context. + By default the current span will be used as parent, but an explicit + parent can also be specified. If the specified value is `None`, the + created span will be a root span. + On exiting the context manager stop the span and set its parent as the current span. @@ -115,40 +124,46 @@ def start_span(self, name: str, parent: 'Span') -> Iterator['Span']: is equivalent to:: - span = tracer.create_span(name, parent=tracer.get_current_span()) + span = tracer.create_span(name) with tracer.use_span(span): do_work() Args: name: The name of the span to be created. - parent: The span's parent. + parent: The span's parent. Defaults to the current span. Yields: The newly-created span. """ - def create_span(self, name: str, parent: 'Span') -> 'Span': - """Creates a new child span of the given parent. + def create_span(self, + name: str, + parent: 'Span' = CURRENT_SPAN) -> 'Span': + """Creates a span. Creating the span does not start it, and should not affect the tracer's context. To start the span and update the tracer's context to make it the currently active span, see :meth:`use_span`. - Applications that need to explicitly set spans' parents or create spans - detached from the tracer's context should use this method. + By default the current span will be used as parent, but an explicit + parent can also be specified. If the specified value is `None`, the + created span will be a root span. + + Applications that need to create spans detached from the tracer's + context should use this method. with tracer.start_span(name) as span: do_work() This is equivalent to:: - span = tracer.create_span(name, parent=tracer.get_current_span()) + span = tracer.create_span(name) with tracer.use_span(span): do_work() Args: name: The name of the span to be created. - parent: The span's parent. + parent: The span's parent. Defaults to the current span. Returns: The newly-created span. From 14e7aaf0490a3a02b536d27ea3b816038021e92d Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Tue, 2 Jul 2019 17:17:21 +0200 Subject: [PATCH 2/6] Update the PR based on the latest feedback. --- .../src/opentelemetry/trace/__init__.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 8ea33a3538a..acad742c762 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -73,9 +73,8 @@ class Tracer: and controlling spans' lifecycles. """ - """Constant used to represent the current span being used as a parent. - This is the default behavior when creating spans. - """ + # Constant used to represent the current span being used as a parent. + # This is the default behavior when creating spans. CURRENT_SPAN = object() def get_current_span(self) -> 'Span': @@ -92,15 +91,16 @@ def get_current_span(self) -> 'Span': @contextmanager # type: ignore def start_span(self, name: str, - parent: 'Span' = CURRENT_SPAN) -> typing.Iterator['Span']: + parent: typing.Union['Span', 'SpanContext'] = CURRENT_SPAN + ) -> typing.Iterator['Span']: """Context manager for span creation. Create a new span. Start the span and set it as the current span in this tracer's context. By default the current span will be used as parent, but an explicit - parent can also be specified. If the specified value is `None`, the - created span will be a root span. + parent can also be specified, either a Span or a SpanContext. + If the specified value is `None`, the created span will be a root span. On exiting the context manager stop the span and set its parent as the current span. @@ -138,7 +138,8 @@ def start_span(self, def create_span(self, name: str, - parent: 'Span' = CURRENT_SPAN) -> 'Span': + parent: typing.Union['Span', 'SpanContext'] = CURRENT_SPAN + ) -> 'Span': """Creates a span. Creating the span does not start it, and should not affect the tracer's @@ -146,8 +147,8 @@ def create_span(self, the currently active span, see :meth:`use_span`. By default the current span will be used as parent, but an explicit - parent can also be specified. If the specified value is `None`, the - created span will be a root span. + parent can also be specified, either a Span or a SpanContext. + If the specified value is `None`, the created span will be a root span. Applications that need to create spans detached from the tracer's context should use this method. From e46599fbc3aa622e76790ce848cce460c62a9282 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Wed, 3 Jul 2019 13:22:45 +0200 Subject: [PATCH 3/6] Update opentelemetry-api/src/opentelemetry/trace/__init__.py Co-Authored-By: Chris Kleinknecht --- opentelemetry-api/src/opentelemetry/trace/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index acad742c762..d6ba69ff4b4 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -99,7 +99,7 @@ def start_span(self, this tracer's context. By default the current span will be used as parent, but an explicit - parent can also be specified, either a Span or a SpanContext. + parent can also be specified, either a ``Span`` or a ``SpanContext``. If the specified value is `None`, the created span will be a root span. On exiting the context manager stop the span and set its parent as the From 464c963d331b6238834a2d0f45de024e9d3c5cb3 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Wed, 3 Jul 2019 13:23:13 +0200 Subject: [PATCH 4/6] Update opentelemetry-api/src/opentelemetry/trace/__init__.py Co-Authored-By: Chris Kleinknecht --- opentelemetry-api/src/opentelemetry/trace/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index d6ba69ff4b4..787e69da2a8 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -100,7 +100,7 @@ def start_span(self, By default the current span will be used as parent, but an explicit parent can also be specified, either a ``Span`` or a ``SpanContext``. - If the specified value is `None`, the created span will be a root span. + If the specified value is ``None``, the created span will be a root span. On exiting the context manager stop the span and set its parent as the current span. From 9dc87e866d77dfcb5f955bf196f88aabcc16f01b Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Wed, 3 Jul 2019 15:17:33 +0200 Subject: [PATCH 5/6] Move Span/SpanContext up so we can reference it from Tracer. Specifically for CURRENT_SPAN usage. --- .../src/opentelemetry/trace/__init__.py | 110 +++++++++--------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index 787e69da2a8..d215600e906 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -66,6 +66,60 @@ import typing +class Span: + """A span represents a single operation within a trace.""" + + def start(self) -> None: + """Sets the current time as the span's start time. + + Each span represents a single operation. The span's start time is the + wall time at which the operation started. + + Only the first call to ``start`` should modify the span, and + implementations are free to ignore or raise on further calls. + """ + + def end(self) -> None: + """Sets the current time as the span's end time. + + The span's end time is the wall time at which the operation finished. + + Only the first call to ``end`` should modify the span, and + implementations are free to ignore or raise on further calls. + """ + + def get_context(self) -> 'SpanContext': + """Gets the span's SpanContext. + + Get an immutable, serializable identifier for this span that can be + used to create new child spans. + + Returns: + A :class:`.SpanContext` with a copy of this span's immutable state. + """ + + +class SpanContext: + """The state of a Span to propagate between processes. + + This class includes the immutable attributes of a :class:`.Span` that must + be propagated to a span's children and across process boundaries. + + Args: + trace_id: The ID of the trace that this span belongs to. + span_id: This span's ID. + options: Trace options to propagate. + state: Tracing-system-specific info to propagate. + """ + + def __init__(self, + trace_id: str, + span_id: str, + options: 'TraceOptions', + state: 'TraceState') -> None: + pass + + class Tracer: """Handles span creation and in-process context propagation. @@ -75,7 +129,7 @@ class Tracer: # Constant used to represent the current span being used as a parent. # This is the default behavior when creating spans. - CURRENT_SPAN = object() + CURRENT_SPAN = Span() def get_current_span(self) -> 'Span': """Gets the currently active span from the context. @@ -185,60 +239,6 @@ def use_span(self, span: 'Span') -> typing.Iterator[None]: """ -class Span: - """A span represents a single operation within a trace.""" - - def start(self) -> None: - """Sets the current time as the span's start time. - - Each span represents a single operation. The span's start time is the - wall time at which the operation started. - - Only the first call to ``start`` should modify the span, and - implementations are free to ignore or raise on further calls. - """ - - def end(self) -> None: - """Sets the current time as the span's end time. - - The span's end time is the wall time at which the operation finished. - - Only the first call to ``end`` should modify the span, and - implementations are free to ignore or raise on further calls. - """ - - def get_context(self) -> 'SpanContext': - """Gets the span's SpanContext. - - Get an immutable, serializable identifier for this span that can be - used to create new child spans. - - Returns: - A :class:`.SpanContext` with a copy of this span's immutable state. - """ - - -class SpanContext: - """The state of a Span to propagate between processes. - - This class includes the immutable attributes of a :class:`.Span` that must - be propagated to a span's children and across process boundaries. - - Args: - trace_id: The ID of the trace that this span belongs to. - span_id: This span's ID. - options: Trace options to propagate. - state: Tracing-system-specific info to propagate. - """ - - def __init__(self, - trace_id: str, - span_id: str, - options: 'TraceOptions', - state: 'TraceState') -> None: - pass - - # TODO class TraceOptions(int): pass From 30b6c21721752388a03f6221eff01168c5cdd221 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Cortez Date: Wed, 3 Jul 2019 15:34:54 +0200 Subject: [PATCH 6/6] Fix a line-too-long. --- opentelemetry-api/src/opentelemetry/trace/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/trace/__init__.py b/opentelemetry-api/src/opentelemetry/trace/__init__.py index d215600e906..10f4691f6e8 100644 --- a/opentelemetry-api/src/opentelemetry/trace/__init__.py +++ b/opentelemetry-api/src/opentelemetry/trace/__init__.py @@ -154,7 +154,8 @@ def start_span(self, By default the current span will be used as parent, but an explicit parent can also be specified, either a ``Span`` or a ``SpanContext``. - If the specified value is ``None``, the created span will be a root span. + If the specified value is ``None``, the created span will be a root + span. On exiting the context manager stop the span and set its parent as the current span. @@ -202,7 +203,8 @@ def create_span(self, By default the current span will be used as parent, but an explicit parent can also be specified, either a Span or a SpanContext. - If the specified value is `None`, the created span will be a root span. + If the specified value is `None`, the created span will be a root + span. Applications that need to create spans detached from the tracer's context should use this method.