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

# Tempo Coordinator K8s

[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:

2.10/stable 162

```
juju deploy tempo-coordinator-k8s --channel 2.10/stable
```

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

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

## charms.tempo\_coordinator\_k8s.v0.tracing

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

    Fetch library

    ```
    charmcraft fetch-lib charms.tempo_coordinator_k8s.v0.tracing
    ```

    [Download tracing.py](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing/download)
  + *Last updated* 29 Aug 2025
  + *Revision* Library version 0.11

##### Overview.

This document explains how to integrate with the Tempo charm for the purpose of pushing traces to a
tracing endpoint provided by Tempo. It also explains how alternative implementations of the Tempo charm
may maintain the same interface and be backward compatible with all currently integrated charms.

##### Requirer Library Usage

Charms seeking to push traces to Tempo, must do so using the `TracingEndpointRequirer`
object from this charm library. For the simplest use cases, using the `TracingEndpointRequirer`
object only requires instantiating it, typically in the constructor of your charm. The
`TracingEndpointRequirer` constructor requires the name of the relation over which a tracing endpoint
is exposed by the Tempo charm, and a list of protocols it intends to send traces with.
This relation must use the `tracing` interface.
The `TracingEndpointRequirer` object may be instantiated as follows

```
from charms.tempo_coordinator_k8s.v0.tracing import TracingEndpointRequirer

def __init__(self, *args):
    super().__init__(*args)
    # ...
    self.tracing = TracingEndpointRequirer(self,
        protocols=['otlp_grpc', 'otlp_http', 'jaeger_http_thrift']
    )
    # ...
```

Note that the first argument (`self`) to `TracingEndpointRequirer` is always a reference to the
parent charm.

Alternatively to providing the list of requested protocols at init time, the charm can do it at
any point in time by calling the
`TracingEndpointRequirer.request_protocols(*protocol:str, relation:Optional[Relation])` method.
Using this method also allows you to use per-relation protocols.

Units of requirer charms obtain the tempo endpoint to which they will push their traces by calling
`TracingEndpointRequirer.get_endpoint(protocol: str)`, where `protocol` is, for example:

* `otlp_grpc`
* `otlp_http`
* `zipkin`
* `tempo`

If the `protocol` is not in the list of protocols that the charm requested at endpoint set-up time,
the library will raise an error.

We recommend that you scale up your tracing provider and relate it to an ingress so that your tracing requests
go through the ingress and get load balanced across all units. Otherwise, if the provider's leader goes down, your tracing goes down.

##### Provider Library Usage

The `TracingEndpointProvider` object may be used by charms to manage relations with their
trace sources. For this purposes a Tempo-like charm needs to do two things

1. Instantiate the `TracingEndpointProvider` object by providing it a
   reference to the parent (Tempo) charm and optionally the name of the relation that the Tempo charm
   uses to interact with its trace sources. This relation must conform to the `tracing` interface
   and it is strongly recommended that this relation be named `tracing` which is its
   default value.

For example a Tempo charm may instantiate the `TracingEndpointProvider` in its constructor as
follows

```
from charms.tempo_coordinator_k8s.v0.tracing import TracingEndpointProvider

def __init__(self, *args):
    super().__init__(*args)
    # ...
    self.tracing = TracingEndpointProvider(self)
    # ...
```

---

Index

* [class TransportProtocolType](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#transportprotocoltype)
* [class TracingError](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingerror)
* [class NotReadyError](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#notreadyerror)
* [class ProtocolNotRequestedError](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#protocolnotrequestederror)
* [class DataValidationError](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#datavalidationerror)
* [class DataAccessPermissionError](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#dataaccesspermissionerror)
* [class AmbiguousRelationUsageError](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#ambiguousrelationusageerror)
* [class Receiver](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#receiver)
* [class TracingProviderAppData](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingproviderappdata)
* [class TracingRequirerAppData](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingrequirerappdata)
* [class RelationNotFoundError](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#relationnotfounderror)
* + [def \_\_init\_\_(
    self,
    relation\_name)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#relationnotfounderror-__init__)
* [class RelationInterfaceMismatchError](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#relationinterfacemismatcherror)
* + [def \_\_init\_\_(
    self,
    relation\_name,
    expected\_relation\_interface,
    actual\_relation\_interface)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#relationinterfacemismatcherror-__init__)
* [class RelationRoleMismatchError](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#relationrolemismatcherror)
* + [def \_\_init\_\_(
    self,
    relation\_name,
    expected\_relation\_role,
    actual\_relation\_role)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#relationrolemismatcherror-__init__)
* [class RequestEvent](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#requestevent)
* + [def requested\_receivers(
    self)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#requestevent-requested_receivers)
* [class BrokenEvent](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#brokenevent)
* [class TracingEndpointProviderEvents](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointproviderevents)
* [class TracingEndpointProvider](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointprovider)
* + [def \_\_init\_\_(
    self,
    charm,
    external\_url,
    relation\_name)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointprovider-__init__)
* + [def is\_requirer\_ready(
    self,
    relation)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointprovider-is_requirer_ready)
* + [def requested\_protocols(
    self)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointprovider-requested_protocols)
* + [def relations(
    self)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointprovider-relations)
* + [def publish\_receivers(
    self,
    receivers)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointprovider-publish_receivers)
* [class EndpointRemovedEvent](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#endpointremovedevent)
* [class EndpointChangedEvent](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#endpointchangedevent)
* + [def receivers(
    self)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#endpointchangedevent-receivers)
* [class TracingEndpointRequirerEvents](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointrequirerevents)
* [class TracingEndpointRequirer](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointrequirer)
* + [def \_\_init\_\_(
    self,
    charm,
    relation\_name,
    protocols)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointrequirer-__init__)
* + [def request\_protocols(
    self,
    protocols,
    relation)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointrequirer-request_protocols)
* + [def relations(
    self)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointrequirer-relations)
* + [def is\_ready(
    self,
    relation)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointrequirer-is_ready)
* + [def get\_all\_endpoints(
    self,
    relation)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointrequirer-get_all_endpoints)
* + [def get\_endpoint(
    self,
    protocol,
    relation)](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#tracingendpointrequirer-get_endpoint)
* [def charm\_tracing\_config(
  endpoint\_requirer,
  cert\_path
  )](https://charmhub.io/tempo-coordinator-k8s/libraries/tracing#charm_tracing_config)

#### class TransportProtocolType

Description

Receiver Type. None

#### class TracingError

Description

Base class for custom errors raised by this library. None

#### class NotReadyError

Description

Raised by the provider wrapper if a requirer hasn't published the required data (yet). None

#### class ProtocolNotRequestedError

Description

Raised if the user attempts to obtain an endpoint for a protocol it did not request. None

#### class DataValidationError

Description

Raised when data validation fails on IPU relation data. None

#### class DataAccessPermissionError

Description

Raised when follower units attempt leader-only operations. None

#### class AmbiguousRelationUsageError

Description

Raised when one wrongly assumes that there can only be one relation on an endpoint. None

#### class Receiver

Description

Specification of an active receiver. None

#### class TracingProviderAppData

Description

Application databag model for the tracing provider. None

#### class TracingRequirerAppData

Description

Application databag model for the tracing requirer. None

#### class RelationNotFoundError

Description

Raised if no relation with the given name is found. None

Methods

RelationNotFoundError.
\_\_init\_\_(

*self*

,
relation\_name: str
)

#### class RelationInterfaceMismatchError

Description

Raised if the relation with the given name has an unexpected interface. None

Methods

RelationInterfaceMismatchError.
\_\_init\_\_(

*self*

,
relation\_name: str

,
expected\_relation\_interface: str

,
actual\_relation\_interface: str
)

#### class RelationRoleMismatchError

Description

Raised if the relation with the given name has a different role than expected. None

Methods

RelationRoleMismatchError.
\_\_init\_\_(

*self*

,
relation\_name: str

,
expected\_relation\_role: RelationRole

,
actual\_relation\_role: RelationRole
)

#### class RequestEvent

Description

Event emitted when a remote requests a tracing endpoint. None

Methods

RequestEvent.
requested\_receivers(

*self*
)

Description

List of receiver protocols that have been requested. None

#### class BrokenEvent

Description

Event emitted when a relation on tracing is broken. None

#### class TracingEndpointProviderEvents

Description

TracingEndpointProvider events. None

#### class TracingEndpointProvider

Description

Class representing a trace receiver service. None

Methods

TracingEndpointProvider.
\_\_init\_\_(

*self*

,
charm: CharmBase

,
external\_url

,
relation\_name: str
)

Initialize.

Arguments

charm

a `CharmBase` instance that manages this instance of the Tempo service.

external\_url

external address of the node hosting the tempo server,
if an ingress is present.

relation\_name

an optional string name of the relation between `charm`
and the Tempo charmed service. The default is "tracing".

TracingEndpointProvider.
is\_requirer\_ready(

*self*

,
relation: Relation
)

Description

Attempt to determine if requirer has already populated app data. None

TracingEndpointProvider.
requested\_protocols(

*self*
)

Description

All receiver protocols that have been requested by our related apps. None

TracingEndpointProvider.
relations(

*self*
)

Description

All relations active on this endpoint. None

TracingEndpointProvider.
publish\_receivers(

*self*

,
receivers
)

Description

Let all requirers know that these receivers are active and listening. None

#### class EndpointRemovedEvent

Description

Event representing a change in one of the receiver endpoints. None

#### class EndpointChangedEvent

Description

Event representing a change in one of the receiver endpoints. None

Methods

EndpointChangedEvent.
receivers(

*self*
)

Description

Cast receivers back from dict. None

#### class TracingEndpointRequirerEvents

Description

TracingEndpointRequirer events. None

#### class TracingEndpointRequirer

Description

A tracing endpoint for Tempo. None

Methods

TracingEndpointRequirer.
\_\_init\_\_(

*self*

,
charm: CharmBase

,
relation\_name: str

,
protocols
)

Construct a tracing requirer for a Tempo charm.

Arguments

charm

a `CharmBase` object that manages this
`TracingEndpointRequirer` object. Typically, this is `self` in the instantiating
class.

relation\_name

an optional string name of the relation between `charm`
and the Tempo charmed service. The default is "tracing". It is strongly
advised not to change the default, so that people deploying your charm will have a
consistent experience with all other charms that provide tracing endpoints.

protocols

optional list of protocols that the charm intends to send traces with.
The provider will enable receivers for these and only these protocols,
so be sure to enable all protocols the charm or its workload are going to need.

Description

If your application supports pushing traces to a distributed tracing backend, the
`TracingEndpointRequirer` object enables your charm to easily access endpoint information
exchanged over a `tracing` relation interface.

TracingEndpointRequirer.
request\_protocols(

*self*

,
protocols

,
relation
)

Description

Publish the list of protocols which the provider should activate. None

TracingEndpointRequirer.
relations(

*self*
)

Description

The tracing relations associated with this endpoint. None

TracingEndpointRequirer.
is\_ready(

*self*

,
relation
)

Description

Is this endpoint ready? None

TracingEndpointRequirer.
get\_all\_endpoints(

*self*

,
relation
)

Description

Unmarshalled relation data. None

TracingEndpointRequirer.
get\_endpoint(

*self*

,
protocol: ReceiverProtocol

,
relation
)

Receiver endpoint for the given protocol.

Description

It could happen that this function gets called before the provider publishes the endpoints.
In such a scenario, if a non-leader unit calls this function, a permission denied exception will be raised due to
restricted access. To prevent this, this function needs to be guarded by the `is_ready` check.

Raises:
ProtocolNotRequestedError:
If the charm unit is the leader unit and attempts to obtain an endpoint for a protocol it did not request.

#### def charm\_tracing\_config(     endpoint\_requirer: TracingEndpointRequirer,     cert\_path )

Return the charm\_tracing config you likely want.

Description

If no endpoint is provided:
disable charm tracing.
If https endpoint is provided but cert\_path is not found on disk:
disable charm tracing.
If https endpoint is provided and cert\_path is None:
ERROR
Else:
proceed with charm tracing (with or without tls, as appropriate)

Usage:

> > > from lib.charms.tempo\_coordinator\_k8s.v0.charm\_tracing import trace\_charm
> > > from lib.charms.tempo\_coordinator\_k8s.v0.tracing import charm\_tracing\_config
> > > @trace\_charm(tracing\_endpoint="my\_endpoint", cert\_path="cert\_path")
> > > class MyCharm(...):
> > > \_cert\_path = "/path/to/cert/on/charm/container.crt"
> > > def **init**(self, ...):
> > > self.tracing = TracingEndpointRequirer(...)
> > > self.my\_endpoint, self.cert\_path = charm\_tracing\_config(
> > > ... self.tracing, self.\_cert\_path)
