pyfect tracing into OpenTelemetry (Effect's OtelTracer).
The tracer this module installs makes each pyfect span an OpenTelemetry
span (OtelSpan) and keeps the current span active in OpenTelemetry's
context while a fiber runs, so libraries instrumented with OpenTelemetry
see it as their parent::
tracing = otel.tracer.layer.pipe(layer.provide(provider_layer))
program.with_span("request").pipe(fx.provide(tracing))A pyfect parent wins over the active OpenTelemetry span; with no pyfect
parent, a span started by other OpenTelemetry code is the parent.
make_external_span and with_span_context continue a remote trace.
Nothing is exported unless the tracer provider has span processors (see
otel.sdk).
| Attribute | Type | Description |
|---|---|---|
make | Final[Effect[Tracer, Never, OtelTracer]] = OtelTracer().map(_tracer) | A pyfect tracer starting OpenTelemetry spans with the |
layer_global_provider | Final[Layer[OtelTracerProvider]] = _layer.sync(OtelTracerProvider, trace.get_tracer_provider) | The global OpenTelemetry tracer provider. |
layer_tracer | Final[Layer[OtelTracer, Never, OtelTracerProvider]] = _layer.effect(OtelTracer, OtelTracerProvider().map(lambda p: p.get_tracer('pyfect', PYFECT_VERSION))) | A tracer from the provider, with |
layer_global_tracer | Final[Layer[OtelTracer]] = layer_tracer.pipe(_layer.provide(layer_global_provider)) | A tracer from the global tracer provider. |
layer_without_otel_tracer | Final[Layer[Never, Never, OtelTracer]] = _layer.effect(CurrentTracer, make) | Installs the bridge's tracer, using the |
layer | Final[Layer[OtelTracer, Never, OtelTracerProvider]] = layer_without_otel_tracer.pipe(_layer.provide_merge(layer_tracer)) | Installs the bridge's tracer, with a tracer from the provider. |
layer_global | Final[Layer[OtelTracer]] = layer_without_otel_tracer.pipe(_layer.provide_merge(layer_global_tracer)) | Installs the bridge's tracer, with a tracer from the global provider. |
Classes#
Functions#
current_otel_span#
current_otel_span() -> Effect[trace.Span, NoSuchElementException]The current span as an OpenTelemetry span: the bridge's own, or a view writing through to a span another tracer made. Fails outside every span, or in an external one.
Returns Effect[trace.Span, NoSuchElementException]
def current_otel_span() -> Effect[trace.Span, NoSuchElementException]:
"""The current span as an OpenTelemetry span: the bridge's own, or a
view writing through to a span another tracer made. Fails outside every
span, or in an external one."""
return Clock().flat_map(lambda clock: current_span().map(lambda s: _otel_span(s, clock)))with_span_context#
with_span_context(span_context) -> _WithSpanContextRun an effect with the OpenTelemetry span context as its parent span
(use with .pipe), continuing a trace begun outside pyfect.
| Parameter | Type | Description |
|---|---|---|
span_context | SpanContext |
Returns _WithSpanContext
def with_span_context(span_context: SpanContext) -> _WithSpanContext:
"""Run an effect with the OpenTelemetry span context as its parent span
(use with ``.pipe``), continuing a trace begun outside pyfect."""
return _WithSpanContext(span_context)make_external_span#
make_external_span(*, trace_id, span_id, trace_flags=None, trace_state=None) -> ExternalSpanA span from another tracing system, to continue its trace with
eff.with_parent_span. Its trace flags and state are kept in its
annotations; without flags it is sampled. A trace state given as text
is parsed as a tracestate header.
| Parameter | Type | Description |
|---|---|---|
trace_id | str | |
span_id | str | |
trace_flags | int | None = None | |
trace_state | str | TraceState | None = None |
Returns ExternalSpan
def make_external_span(
*,
trace_id: str,
span_id: str,
trace_flags: int | None = None,
trace_state: str | TraceState | None = None,
) -> ExternalSpan:
"""A span from another tracing system, to continue its trace with
``eff.with_parent_span``. Its trace flags and state are kept in its
annotations; without flags it is sampled. A trace state given as text
is parsed as a ``tracestate`` header."""
annotations = Context.empty()
if trace_flags is not None:
annotations = annotations.add(OtelTraceFlags, TraceFlags(trace_flags))
if isinstance(trace_state, str):
annotations = annotations.add(OtelTraceState, TraceState.from_header([trace_state]))
elif trace_state is not None:
annotations = annotations.add(OtelTraceState, trace_state)
return ExternalSpan(
span_id=span_id,
trace_id=trace_id,
sampled=True if trace_flags is None else is_sampled(trace_flags),
annotations=annotations,
)