---
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/tempo_scrape
---

# 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/tempo_scrape#drawer)

## charms.tempo\_k8s.v0.tempo\_scrape

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

    Fetch library

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

    [Download tempo\_scrape.py](https://charmhub.io/tempo-k8s/libraries/tempo_scrape/download)
  + *Last updated* 19 Apr 2023
  + *Revision* Library version 0.1

##### Overview.

This document explains how to integrate with the Tempo charm for the purpose of providing a
tracing endpoint to 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.

##### Provider Library Usage

This Tempo charm interacts with its scrape targets using its charm library. Charms seeking to
expose tracing endpoints for the Tempo charm, must do so using the `TracingEndpointProvider`
object from this charm library. For the simplest use cases, using the `TracingEndpointProvider`
object only requires instantiating it, typically in the constructor of your charm. The
`TracingEndpointProvider` constructor requires the name of the relation over which a scrape
target (tracing endpoint) is exposed to the Tempo charm. This relation must use the
`tempo_scrape` interface. By default address of the tracing endpoint is set to the unit IP
address, by each unit of the `TracingEndpointProvider` charm. These units set their address in
response to the `PebbleReady` event of each container in the unit, since container restarts of
Kubernetes charms can result in change of IP addresses. The default name for the tracing endpoint
relation is `tracing`. It is strongly recommended to use the same relation name for
consistency across charms and doing so obviates the need for an additional constructor argument.
The `TracingEndpointProvider` object may be instantiated as follows

```
from charms.tempo_k8s.v0.tempo_scrape import TracingEndpointProvider

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

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

An instantiated `TracingEndpointProvider` object will ensure that each unit of its parent charm,
is a scrape target for the `TracingEndpointConsumer` (Tempo) charm. By default
`TracingEndpointProvider` assumes each unit of the consumer charm exports its profiles on port
80. These defaults may be changed by providing the `TracingEndpointProvider` constructor an
optional argument (`jobs`) that represents a Tempo scrape job specification using Python standard
data structures. This job specification is a subset of Tempo's own [scrape
configuration](https://www.tempo.dev/docs/configuration) format but represented using Python data
structures. More than one job may be provided using the `jobs` argument. Hence `jobs` accepts a
list of dictionaries where each dictionary represents one `<scrape_config>` object as described in
the Tempo documentation. The currently supported configuration subset is: `job_name`,
`static_configs`

Suppose it is required to change the port on which scraped profiles are exposed to 8000. This may be
done by providing the following data structure as the value of `jobs`.

```
[{"static_configs": [{"targets": ["*:8000"]}]}]
```

The wildcard ("\*") host specification implies that the scrape targets will automatically be set to
the host addresses advertised by each unit of the consumer charm.

It is also possible to change the profile path and scrape multiple ports, for example

```
[{"static_configs": [{"targets": ["*:8000", "*:8081"]}]}]
```

More complex scrape configurations are possible. For example

```
[{
    "static_configs": [{
        "targets": ["10.1.32.215:7000", "*:8000"],
        "labels": {
            "some-key": "some-value"
        }
    }]
}]
```

This example scrapes the target "10.1.32.215" at port 7000 in addition to scraping each unit at
port 8000. There is however one difference between wildcard targets (specified using "\*") and fully
qualified targets (such as "10.1.32.215"). The Tempo charm automatically associates labels with
profiles generated by each target. These labels localise the source of profiles within the Juju
topology by specifying its "model name", "model UUID", "application name" and "unit name". However
unit name is associated only with wildcard targets but not with fully qualified targets.

Multiple jobs with labels are allowed, but each job must be given a unique name:

```
[
    {
        "job_name": "my-first-job",
        "static_configs": [
            {
                "targets": ["*:7000"],
                "labels": {
                    "some-key": "some-value"
                }
            }
        ]
    },
    {
        "job_name": "my-second-job",
        "static_configs": [
            {
                "targets": ["*:8000"],
                "labels": {
                    "some-other-key": "some-other-value"
                }
            }
        ]
    }
]
```

**Important:** `job_name` should be a fixed string (e.g. hardcoded literal). For instance, if you
include variable elements, like your `unit.name`, it may break the continuity of the profile time
series gathered by Tempo when the leader unit changes (e.g. on upgrade or rescale).

##### Consumer Library Usage

The `TracingEndpointConsumer` object may be used by Tempo charms to manage relations with their
scrape targets. For this purposes a Tempo charm needs to do two things

1. Instantiate the `TracingEndpointConsumer` 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 scrape targets. This relation must confirm to the `tempo_scrape` 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 `TracingEndpointConsumer` in its constructor as
follows

```
from charms.tempo_k8s.v0.tempo_scrape import TracingEndpointConsumer

def __init__(self, *args):
    super().__init__(*args)
    # ...
    self.tracing_consumer = TracingEndpointConsumer(self)
    # ...
```

2. A Tempo charm also needs to respond to the `TargetsChangedEvent` event of the
   `TracingEndpointConsumer` by adding itself as an observer for these events, as in

   self.framework.observe(
   self.tracing\_consumer.on.targets\_changed,
   self.\_on\_scrape\_targets\_changed,
   )

In responding to the `TargetsChangedEvent` event the Tempo charm must update the Tempo
configuration so that any new scrape targets are added and/or old ones removed from the list of
scraped endpoints. For this purpose the `TracingEndpointConsumer` object exposes a `jobs()`
method that returns a list of scrape jobs. Each element of this list is the Tempo scrape
configuration for that job. In order to update the Tempo configuration, the Tempo charm needs to
replace the current list of jobs with the list provided by `jobs()` as follows

```
def _on_scrape_targets_changed(self, event):
    ...
    scrape_jobs = self.tracing_consumer.jobs()
    for job in scrape_jobs:
        tempo_scrape_config.append(job)
    ...
```

##### Relation Data

Units of profiles provider charms advertise their names and addresses over unit relation data using
the `tempo_scrape_unit_name` and `tempo_scrape_unit_address` keys. While the `scrape_metadata`,
`scrape_jobs` and `alert_rules` keys in application relation data of profiles provider charms hold
eponymous information.

---

Index

* [class RelationNotFoundError](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#relationnotfounderror)
* + [def \_\_init\_\_(
    self,
    relation\_name)](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#relationnotfounderror-__init__)
* [class RelationInterfaceMismatchError](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#relationinterfacemismatcherror)
* + [def \_\_init\_\_(
    self,
    relation\_name,
    expected\_relation\_interface,
    actual\_relation\_interface)](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#relationinterfacemismatcherror-__init__)
* [class RelationRoleMismatchError](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#relationrolemismatcherror)
* + [def \_\_init\_\_(
    self,
    relation\_name,
    expected\_relation\_role,
    actual\_relation\_role)](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#relationrolemismatcherror-__init__)
* [class TargetsChangedEvent](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#targetschangedevent)
* + [def \_\_init\_\_(
    self,
    handle,
    relation\_id)](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#targetschangedevent-__init__)
* + [def snapshot(
    self)](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#targetschangedevent-snapshot)
* + [def restore(
    self,
    snapshot)](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#targetschangedevent-restore)
* [class MonitoringEvents](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#monitoringevents)
* [class TracingEndpointRequirer](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#tracingendpointrequirer)
* + [def \_\_init\_\_(
    self,
    charm,
    tempo\_endpoint,
    relation\_name)](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#tracingendpointrequirer-__init__)
* + [def update\_relation\_data(
    self,
    \_)](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#tracingendpointrequirer-update_relation_data)
* [class EndpointChangedEvent](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#endpointchangedevent)
* [class TracingEndpointEvents](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#tracingendpointevents)
* [class TracingEndpointProvider](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#tracingendpointprovider)
* + [def \_\_init\_\_(
    self,
    charm,
    relation\_name)](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#tracingendpointprovider-__init__)
* + [def endpoint(
    self)](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#tracingendpointprovider-endpoint)
* + [def otlp\_grpc\_endpoint(
    self)](https://charmhub.io/tempo-k8s/libraries/tempo_scrape#tracingendpointprovider-otlp_grpc_endpoint)

#### 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 TargetsChangedEvent

Description

Event emitted when Tempo scrape targets change. None

Methods

TargetsChangedEvent.
\_\_init\_\_(

*self*

,
handle

,
relation\_id
)

TargetsChangedEvent.
snapshot(

*self*
)

Description

Save scrape target relation information. None

TargetsChangedEvent.
restore(

*self*

,
snapshot
)

Description

Restore scrape target relation information. None

#### class MonitoringEvents

Description

Event descriptor for events raised by `TracingEndpointConsumer`. None

#### class TracingEndpointRequirer

Description

A Tempo based monitoring service. None

Methods

TracingEndpointRequirer.
\_\_init\_\_(

*self*

,
charm: CharmBase

,
tempo\_endpoint

,
relation\_name: str
)

A Tempo based Monitoring service.

Arguments

charm

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

relation\_name

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

TracingEndpointRequirer.
update\_relation\_data(

*self*

,
\_
)

#### class EndpointChangedEvent

#### class TracingEndpointEvents

#### class TracingEndpointProvider

Description

A tracing endpoint for Tempo. None

Methods

TracingEndpointProvider.
\_\_init\_\_(

*self*

,
charm: CharmBase

,
relation\_name: str
)

Construct a tracing provider for a Tempo charm.

Arguments

charm

a `CharmBase` object that manages this
`TracingEndpointProvider` 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.

Description

If your charm exposes a Tempo tracing endpoint, the `TracingEndpointProvider` object
enables your charm to easily communicate how to reach that endpoint.

By default, a charm instantiating this object has the tracing endpoints of each of its
units scraped by the related Tempo charms.

The scraped profiles are automatically tagged by the Tempo charms with Juju topology data
via the `juju_model_name`, `juju_model_uuid`, `juju_application_name` and `juju_unit`
labels. To support such tagging `TracingEndpointProvider` automatically forwards scrape
metadata to a `TracingEndpointConsumer` (Tempo charm).

Scrape targets provided by `TracingEndpointProvider` can be customized when instantiating
this object. For example in the case of a charm exposing the tracing endpoint for each of
its units on port 8080, the `TracingEndpointProvider` can be
instantiated as follows:

```
self.tracing_endpoint_provider = TracingEndpointProvider(
    self, jobs=[{"static_configs": [{"targets": ["*:8080"]}]}]
)
```

The notation `*:<port>` means "scrape each unit of this charm on port `<port>`.

TracingEndpointProvider.
endpoint(

*self*
)

TracingEndpointProvider.
otlp\_grpc\_endpoint(

*self*
)
