---
title: Charmhub | Deploy Tempo using Charmhub - The Open Operator Collection
description: Deploy the latest version of Tempo as a Kubernetes Operator on any cloud.
url: https://charmhub.io/tempo-k8s/libraries/charm_instrumentation
---

# Tempo

[Canonical Observability](https://charmhub.io/publisher/observability "View all packages from Canonical Observability")

* [Canonical Observability](https://charmhub.io/publisher/observability "View all packages from Canonical Observability")

Platform:

stable 71

```
juju deploy tempo-k8s
```

[Learn to deploy on juju >](https://juju.is/docs/juju/manage-applications)

[Toggle side navigation](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation#drawer)

## charms.tempo\_k8s.v0.charm\_instrumentation

* [*Docstrings*Docstrings](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation)
  [*Code*Source code](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation/source-code)
* + Download

    Fetch library

    ```
    charmcraft fetch-lib charms.tempo_k8s.v0.charm_instrumentation
    ```

    [Download charm\_instrumentation.py](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation/download)
  + *Last updated* 04 Sep 2023
  + *Revision* Library version 0.8

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")`

2. add to your charm a "my\_tracing\_endpoint" (you can name this attribute whatever you like) **property**
   that returns an otlp grpc 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'''
        return self.tracing.otlp_grpc_endpoint
```

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`.

---

Index

* [def is\_enabled(
  )](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation#is_enabled)
* [def get\_current\_span(
  )](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation#get_current_span)
* [class TracingError](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation#tracingerror)
* [class UntraceableObjectError](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation#untraceableobjecterror)
* [def trace\_charm(
  tracing\_endpoint,
  server\_cert,
  service\_name,
  extra\_types
  )](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation#trace_charm)
* [def trace\_type(
  cls
  )](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation#trace_type)
* [def trace\_method(
  method,
  static
  )](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation#trace_method)
* [def trace\_function(
  function
  )](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation#trace_function)
* [def trace(
  obj
  )](https://charmhub.io/tempo-k8s/libraries/charm_instrumentation#trace)

#### def is\_enabled()

Description

Whether charm tracing is enabled. None

#### 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 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 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.v0.charm\_instrumentation import trace\_charm
> > > from charms.tempo\_k8s.v0.tracing import TracingEndpointProvider
> > > from ops import CharmBase
> > >
> > > @trace\_charm(
> > > tracing\_endpoint="tempo\_otlp\_grpc\_endpoint",
> > > )
> > > class MyCharm(CharmBase):
> > >
> > > ```
> > > def __init__(self, framework: Framework):
> > >     ...
> > >     self.tempo = TracingEndpointProvider(self)
> > >
> > > @property
> > > def tempo_otlp_grpc_endpoint(self) -> Optional[str]:
> > >     return self.tempo.otlp_grpc_endpoint
> > > ```

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`.
