Tracing¶
Overview¶
It provides an instrument tracing wrapper function to use to instrument functions manually in pubtools-* projects.
Usage¶
Set environment variables¶
Following environment variables are used in the module:
OTEL_TRACING
: settrue
to enable instrument tracing, otherwise tracing is disabled.OTEL_SERVICE_NAME
: required, set the value of the service.name resource attribute. It’s expected to be unique within the same namespace.
OTEL Exporter¶
In order to visualize and analyze telemetry, an exporter is required to export tracing data to a backend, e.g: jaeger. As part of OpenTelemetry Python you will find many exporters being available. Which exporter should be used depends on usage scenarios, e.g: ConsoleSpanExporter is useful for development and debugging tasks, while OTLPSpanExporter can be more suitable on production environment. So choosing different exporters for different scenarios is expected.
In order to have a exporter you expected, the hook otel_exporter()
is needed to be implemented,
otherwise ConsoleSpanExporter
will be used.
Instrument tracing for functions¶
Basic instrument tracing for a function
from pubtools.tracing import get_trace_wrapper
# Initialize a trace provider, batch span processor and exporter.
tw = get_trace_wrapper()
# Create a span for the function foo.
@tw.instrument_func(span_name="foo_span", args_to_attr=True)
def foo(p1="p1"):
pass
...
The function foo will be instrumented, the span name is foo_span
, and the input parameters
p1="p1"
are added in the span attributes.
The input parameter span_name
and args_to_attr
are optional, if span_name
is not
specified, the span name will use the function’s name.
Instrument a function with carrier
Imaging the case that trace context is propagated cross application systems. A carrier which carries trace context along with a call is passed to from upstream service to downstream service, then downstream service will extract trace context from the carrier.
The wrapper function is able to extract trace context from the carrier if it’s provided. For example:
from pubtools.tracing import get_trace_wrapper
# carrier={'traceparent': '00-355989206d66228f21ff34634b77ae1a-97efa33ebed5d06c-01',...}
tw = get_trace_wrapper()
@tw.instrument_func(carrier=carrier):
def foo():
pass
...
The span “foo” will appear in the trace extracted from carrier
and be as a child span of
the caller span.
Instrument functions with environment variables
Trace context can be extracted from environment variables.
from pubtools.tracing import get_trace_wrapper
# 'traceparent' environment variable is set.
# os.environ["traceparent"] = "00-355989206d66228f21ff34634b77ae1a-97efa33ebed5d06c-01"
tw = get_trace_wrapper()
@tw.instrument_func():
def foo():
pass
...
It’s similar as extracting trace context from the function parameter carrier.
It’s useful in multiple threads scenario. As opentelemetry-python library uses contextvars under the hood, trace context can not be passed across threads. It provides a solution to implement context pass in this case, for example:
from pubtools.tracing import get_trace_wrapper
tw = get_trace_wrapper()
@tw.instrument_func(span_name="sub_thread_span")
def sub_thread():
return 1
@tw.instrument_func(span_name="main_thread_span")
def main_thread(param1, param2):
with ThreadPoolExecutor(max_workers=2) as executor:
future_res = [executor.submit(sub_thread) for i in range(1, 3)]
as_completed(future_res)
...
The span sub_thread_span
and main_thread_span
are in the same trace and the sub_thread_span
is the child of main_thread_span
span.
API reference¶
- pubtools._impl.tracing.TracingWrapper.instrument_func(self, span_name=None, carrier=None, args_to_attr=False)¶
Instrument tracing for a function.
- Parameters:
span_name – str Span name. It’s assigned with the function’s name by default if it’s omitted.
carrier – dict A dictionary which holds trace context. Trace context will be extracted from it if if it’s provided.
args_to_attr – boolean Add function parameters into span attributes or not.
- Returns:
The decorated function
- pubtools._impl.tracing.TracingWrapper.force_flush(self)¶
Flush trace data into OTEL collectors