Tempo

  • By Canonical Observability
Channel Revision Published Runs on
latest/stable 27 26 Mar 2024
Ubuntu 22.04
latest/candidate 30 26 Mar 2024
Ubuntu 22.04
latest/beta 33 26 Mar 2024
Ubuntu 22.04
latest/edge 35 17 Apr 2024
Ubuntu 22.04
juju deploy tempo-k8s
Show information

Platform:

charms.tempo_k8s.v1.charm_tracing

This charm library contains utilities to instrument your Charm with opentelemetry tracing data collection.

(yes! charm code, not workload code!)

This means that, if your charm is related to, for example, COS' Tempo charm, you will be able to inspect in real time from the Grafana dashboard the execution flow of your charm.

To start using this library, you need to do two things:

  1. decorate your charm class with

@trace_charm(tracing_endpoint="my_tracing_endpoint")

  1. add to your charm a "my_tracing_endpoint" (you can name this attribute whatever you like) property that returns an otlp http/https endpoint url. If you are using the TracingEndpointProvider as self.tracing = TracingEndpointProvider(self), the implementation could be:
    @property
    def my_tracing_endpoint(self) -> Optional[str]:
        '''Tempo endpoint for charm tracing'''
        if self.tracing.is_ready():
            return self.tracing.otlp_http_endpoint()
        else:
            return None

At this point your charm will be automatically instrumented so that:

  • charm execution starts a trace, containing
    • every event as a span (including custom events)
    • every charm method call (except dunders) as a span

if you wish to add more fine-grained information to the trace, you can do so by getting a hold of the tracer like so:

import opentelemetry
...
    @property
    def tracer(self) -> opentelemetry.trace.Tracer:
        return opentelemetry.trace.get_tracer(type(self).__name__)

By default, the tracer is named after the charm type. If you wish to override that, you can pass a different service_name argument to trace_charm.

Upgrading from v0:

If you are upgrading from charm_tracing v0, you need to take the following steps (assuming you already have the newest version of the library in your charm):

  1. If you need the dependency for your tests, add the following dependency to your charm project (or, if your project had a dependency on opentelemetry-exporter-otlp-proto-grpc only because of charm_tracing v0, you can replace it with):

opentelemetry-exporter-otlp-proto-http>=1.21.0.

  1. Update the charm method referenced to from @trace and @trace_charm, to return from TracingEndpointRequirer.otlp_http_endpoint() instead of grpc_http. For example:
    from charms.tempo_k8s.v0.charm_tracing import trace_charm

    @trace_charm(
        tracing_endpoint="my_tracing_endpoint",
    )
    class MyCharm(CharmBase):

    ...

        @property
        def my_tracing_endpoint(self) -> Optional[str]:
            '''Tempo endpoint for charm tracing'''
            if self.tracing.is_ready():
                return self.tracing.otlp_grpc_endpoint()
            else:
                return None

needs to be replaced with:

    from charms.tempo_k8s.v1.charm_tracing import trace_charm

    @trace_charm(
        tracing_endpoint="my_tracing_endpoint",
    )
    class MyCharm(CharmBase):

    ...

        @property
        def my_tracing_endpoint(self) -> Optional[str]:
            '''Tempo endpoint for charm tracing'''
            if self.tracing.is_ready():
                return self.tracing.otlp_http_endpoint()
            else:
                return None
  1. If you were passing a certificate using server_cert, you need to change it to provide an absolute path to the certificate file.

def is_enabled()

Description

Whether charm tracing is enabled. None

def charm_tracing_disabled()

Contextmanager to temporarily disable charm tracing.

Description

For usage in tests.

def get_current_span()

Return the currently active Span, if there is one, else None.

Description

If you'd rather keep your logic unconditional, you can use opentelemetry.trace.get_current_span, which will return an object that behaves like a span but records no data.

class TracingError

Description

Base class for errors raised by this module. None

class UntraceableObjectError

Description

Raised when an object you're attempting to instrument cannot be autoinstrumented. None

def trace_charm(
    tracing_endpoint: str,
    server_cert,
    service_name,
    extra_types
)

Autoinstrument the decorated charm with tracing telemetry.

Arguments

server_cert

method or property on the charm type that returns an optional absolute path to a tls certificate to be used when sending traces to a remote server. If it returns None, an insecure connection will be used.

tracing_endpoint

name of a property on the charm type that returns an optional (fully resolvable) tempo url. If None, tracing will be effectively disabled. Else, traces will be pushed to that endpoint.

service_name

service name tag to attach to all traces generated by this charm. Defaults to the juju application name this charm is deployed under.

extra_types

pass any number of types that you also wish to autoinstrument. For example, charm libs, relation endpoint wrappers, workload abstractions, ...

Description

Use this function to get out-of-the-box traces for all events emitted on this charm and all method calls on instances of this class.

Usage:

from charms.tempo_k8s.v1.charm_tracing import trace_charm from charms.tempo_k8s.v1.tracing import TracingEndpointProvider from ops import CharmBase

@trace_charm( tracing_endpoint="tempo_otlp_http_endpoint", ) class MyCharm(CharmBase):

def __init__(self, framework: Framework):
    ...
    self.tracing = TracingEndpointProvider(self)

@property
def tempo_otlp_http_endpoint(self) -> Optional[str]:
    if self.tracing.is_ready():
        return self.tracing.otlp_http_endpoint()
    else:
        return None

Methods

def trace_type(cls: _T)

Set up tracing on this class.

Description

Use this decorator to get out-of-the-box traces for all method calls on instances of this class. It assumes that this class is only instantiated after a charm type decorated with @trace_charm has been instantiated.

def trace_method(
    method: _F,
    static: bool
)

Trace this method.

Description

A span will be opened when this method is called and closed when it returns.

def trace_function(function: _F)

Trace this function.

Description

A span will be opened when this function is called and closed when it returns.

def trace(obj)

Trace this object and send the resulting spans to Tempo.

Description

It will dispatch to trace_type if the decorated object is a class, otherwise trace_function.