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

# Parca

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

0.27/stable rev389-5-g748063c

```
juju deploy parca-k8s --channel 0.27/stable
```

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

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

## charms.parca\_k8s.v0.parca\_scrape

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

    Fetch library

    ```
    charmcraft fetch-lib charms.parca_k8s.v0.parca_scrape
    ```

    [Download parca\_scrape.py](https://charmhub.io/parca-k8s/libraries/parca_scrape/download)
  + *Last updated* 23 Apr 2025
  + *Revision* Library version 0.6

##### Overview.

This document explains how to integrate with the Parca charm for the purpose of providing a
profiling endpoint to Parca. It also explains how alternative implementations of the Parca charms
may maintain the same interface and be backward compatible with all currently integrated charms.

##### Provider Library Usage

This Parca charm interacts with its scrape targets using its charm library. Charms seeking to
expose profiling endpoints for the Parca charm, must do so using the `ProfilingEndpointProvider`
object from this charm library. For the simplest use cases, using the `ProfilingEndpointProvider`
object only requires instantiating it, typically in the constructor of your charm. The
`ProfilingEndpointProvider` constructor requires the name of the relation over which a scrape
target (profiling endpoint) is exposed to the Parca charm. This relation must use the
`parca_scrape` interface. By default address of the profiling endpoint is set to the unit IP
address, by each unit of the `ProfilingEndpointProvider` 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 profiling endpoint
relation is `profiling-endpoint`. 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 `ProfilingEndpointProvider` object may be instantiated as follows

```
from charms.parca_k8s.v0.parca_scrape import ProfilingEndpointProvider

def __init__(self, *args):
    super().__init__(*args)
    # ...
    self.profiling_endpoint = ProfilingEndpointProvider(self)
    # ...
```

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

An instantiated `ProfilingEndpointProvider` object will ensure that each unit of its parent charm,
is a scrape target for the `ProfilingEndpointConsumer` (Parca) charm. By default
`ProfilingEndpointProvider` assumes each unit of the consumer charm exports its profiles on port
80. These defaults may be changed by providing the `ProfilingEndpointProvider` constructor an
optional argument (`jobs`) that represents a Parca scrape job specification using Python standard
data structures. This job specification is a subset of Parca's own [scrape
configuration](https://www.parca.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 Parca 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 Parca 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 Parca when the leader unit changes (e.g. on upgrade or rescale).

##### Consumer Library Usage

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

1. Instantiate the `ProfilingEndpointConsumer` object by providing it a
   reference to the parent (Parca) charm and optionally the name of the relation that the Parca charm
   uses to interact with scrape targets. This relation must confirm to the `parca_scrape` interface
   and it is strongly recommended that this relation be named `profiling-endpoint` which is its
   default value.

For example a Parca charm may instantiate the `ProfilingEndpointConsumer` in its constructor as
follows

```
from charms.parca_k8s.v0.parca_scrape import ProfilingEndpointConsumer

def __init__(self, *args):
    super().__init__(*args)
    # ...
    self.profiling_consumer = ProfilingEndpointConsumer(self)
    # ...
```

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

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

In responding to the `TargetsChangedEvent` event the Parca charm must update the Parca
configuration so that any new scrape targets are added and/or old ones removed from the list of
scraped endpoints. For this purpose the `ProfilingEndpointConsumer` object exposes a `jobs()`
method that returns a list of scrape jobs. Each element of this list is the Parca scrape
configuration for that job. In order to update the Parca configuration, the Parca 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.profiling_consumer.jobs()
    for job in scrape_jobs:
        parca_scrape_config.append(job)
    ...
```

##### Relation Data

Units of profiles provider charms advertise their names and addresses over unit relation data using
the `parca_scrape_unit_name` and `parca_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/parca-k8s/libraries/parca_scrape#relationnotfounderror)
* + [def \_\_init\_\_(
    self,
    relation\_name)](https://charmhub.io/parca-k8s/libraries/parca_scrape#relationnotfounderror-__init__)
* [class RelationInterfaceMismatchError](https://charmhub.io/parca-k8s/libraries/parca_scrape#relationinterfacemismatcherror)
* + [def \_\_init\_\_(
    self,
    relation\_name,
    expected\_relation\_interface,
    actual\_relation\_interface)](https://charmhub.io/parca-k8s/libraries/parca_scrape#relationinterfacemismatcherror-__init__)
* [class RelationRoleMismatchError](https://charmhub.io/parca-k8s/libraries/parca_scrape#relationrolemismatcherror)
* + [def \_\_init\_\_(
    self,
    relation\_name,
    expected\_relation\_role,
    actual\_relation\_role)](https://charmhub.io/parca-k8s/libraries/parca_scrape#relationrolemismatcherror-__init__)
* [class ProviderTopology](https://charmhub.io/parca-k8s/libraries/parca_scrape#providertopology)
* + [def scrape\_identifier(
    self)](https://charmhub.io/parca-k8s/libraries/parca_scrape#providertopology-scrape_identifier)
* [class TargetsChangedEvent](https://charmhub.io/parca-k8s/libraries/parca_scrape#targetschangedevent)
* + [def \_\_init\_\_(
    self,
    handle,
    relation\_id)](https://charmhub.io/parca-k8s/libraries/parca_scrape#targetschangedevent-__init__)
* + [def snapshot(
    self)](https://charmhub.io/parca-k8s/libraries/parca_scrape#targetschangedevent-snapshot)
* + [def restore(
    self,
    snapshot)](https://charmhub.io/parca-k8s/libraries/parca_scrape#targetschangedevent-restore)
* [class MonitoringEvents](https://charmhub.io/parca-k8s/libraries/parca_scrape#monitoringevents)
* [class ProfilingEndpointConsumer](https://charmhub.io/parca-k8s/libraries/parca_scrape#profilingendpointconsumer)
* + [def \_\_init\_\_(
    self,
    charm,
    relation\_name)](https://charmhub.io/parca-k8s/libraries/parca_scrape#profilingendpointconsumer-__init__)
* + [def on\_profiling\_provider\_relation\_changed(
    self,
    event)](https://charmhub.io/parca-k8s/libraries/parca_scrape#profilingendpointconsumer-on_profiling_provider_relation_changed)
* + [def jobs(
    self)](https://charmhub.io/parca-k8s/libraries/parca_scrape#profilingendpointconsumer-jobs)
* [class ProfilingEndpointProvider](https://charmhub.io/parca-k8s/libraries/parca_scrape#profilingendpointprovider)
* + [def \_\_init\_\_(
    self,
    charm,
    relation\_name,
    jobs,
    refresh\_event)](https://charmhub.io/parca-k8s/libraries/parca_scrape#profilingendpointprovider-__init__)
* + [def update\_scrape\_job\_spec(
    self,
    jobs)](https://charmhub.io/parca-k8s/libraries/parca_scrape#profilingendpointprovider-update_scrape_job_spec)
* + [def set\_scrape\_job\_spec(
    self)](https://charmhub.io/parca-k8s/libraries/parca_scrape#profilingendpointprovider-set_scrape_job_spec)
* + [def is\_ready(
    self,
    relation)](https://charmhub.io/parca-k8s/libraries/parca_scrape#profilingendpointprovider-is_ready)

#### class RelationNotFoundError

Description

Raise if there is no relation with the given name is found. None

Methods

RelationNotFoundError.
\_\_init\_\_(

*self*

,
relation\_name: str
)

#### class RelationInterfaceMismatchError

Description

Raise if the relation with the given name has a different interface. None

Methods

RelationInterfaceMismatchError.
\_\_init\_\_(

*self*

,
relation\_name: str

,
expected\_relation\_interface: str

,
actual\_relation\_interface: str
)

#### class RelationRoleMismatchError

Description

Raise if the relation with the given name has a different role. None

Methods

RelationRoleMismatchError.
\_\_init\_\_(

*self*

,
relation\_name: str

,
expected\_relation\_role

,
actual\_relation\_role
)

#### class ProviderTopology

Description

Class for initializing topology information for ProfilingEndpointProvider. None

Methods

ProviderTopology.
scrape\_identifier(

*self*
)

Description

Format the topology information into a scrape identifier. None

#### class TargetsChangedEvent

Description

Event emitted when Parca 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 `ProfilingEndpointConsumer`. None

#### class ProfilingEndpointConsumer

Description

Parca based monitoring service. None

Methods

ProfilingEndpointConsumer.
\_\_init\_\_(

*self*

,
charm

,
relation\_name: str
)

Construct a Parca based monitoring service.

Arguments

charm

a `ops.CharmBase` instance that manages this instance of the Parca service.

relation\_name

an optional string name of the relation between `charm`
and the Parca charmed service. The default is "profiling-endpoint".

ProfilingEndpointConsumer.
on\_profiling\_provider\_relation\_changed(

*self*

,
event
)

Handle changes with related profiling providers.

Arguments

event

a `CharmEvent` resulting in the Parca charm updating its scrape configuration

Description

Anytime there are changes in relations between Parca and profiling provider charms the
Parca charm is informed, through a `TargetsChangedEvent` event. The Parca charm can then
choose to update its scrape configuration.

ProfilingEndpointConsumer.
jobs(

*self*
)

Fetch the list of scrape jobs.

Returns

A list consisting of all the static scrape configurations for each related
`ProfilingEndpointProvider` that has specified its scrape targets.

#### class ProfilingEndpointProvider

Description

Profiling endpoint for Parca. None

Methods

ProfilingEndpointProvider.
\_\_init\_\_(

*self*

,
charm

,
relation\_name: str

,
jobs

,
refresh\_event
)

Construct a profiling provider for a Parca charm.

Arguments

charm

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

relation\_name

an optional string name of the relation between `charm`
and the Parca charmed service. The default is "profiling-endpoint". 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 profiling endpoints.

jobs

an optional list of dictionaries where each dictionary represents the Parca
scrape configuration for a single job. When not provided, a default scrape
configuration is provided polling all units of the charm on port `80` using the
`ProfilingEndpointProvider` object.

refresh\_event

an optional bound event or list of bound events which
will be observed to re-set scrape job data (IP address and others)

Description

If your charm exposes a Parca profiling endpoint, the `ProfilingEndpointProvider` object
enables your charm to easily communicate how to reach that endpoint.

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

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

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

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

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

ProfilingEndpointProvider.
update\_scrape\_job\_spec(

*self*

,
jobs
)

Update scrape job specification.

Description

This will override the job specs you passed to the constructor.
Use it if for some reason you can't rely on that being up to date.

ProfilingEndpointProvider.
set\_scrape\_job\_spec(

*self*
)

Ensure the scrape target information (as passed to this object on **init**) is published.

Description

When a profiling provider charm is related to a Parca charm, the profiling provider sets
specification and metadata related to its own scrape configuration. This information is set
using Juju application data. Each of the consumer units also sets its own host address in
Juju unit relation data.

ProfilingEndpointProvider.
is\_ready(

*self*

,
relation
)

Description

Check if the relation(s) on this endpoint are ready. None
