Grafana

  • By Jose C. Massón
Channel Version Revision Published Runs on
latest/stable 64 64 31 Jan 2023
Ubuntu 20.04 Ubuntu 20.04
latest/candidate 64 64 31 Jan 2023
Ubuntu 20.04 Ubuntu 20.04
latest/beta 64 64 31 Jan 2023
Ubuntu 20.04 Ubuntu 20.04
latest/edge 67 67 02 Feb 2023
Ubuntu 20.04 Ubuntu 20.04
1.0/stable 64 64 31 Jan 2023
Ubuntu 20.04 Ubuntu 20.04
1.0/candidate 64 64 31 Jan 2023
Ubuntu 20.04 Ubuntu 20.04
1.0/beta 64 64 31 Jan 2023
Ubuntu 20.04 Ubuntu 20.04
1.0/edge 64 64 31 Jan 2023
Ubuntu 20.04 Ubuntu 20.04
juju deploy grafana-k8s
Show information

Platform:

charms.grafana_k8s.v0.grafana_source

Overview.

This document explains how to integrate with the Grafana charm for the purpose of providing a datasource which can be used by Grafana dashboards. It also explains the structure of the data expected by the grafana-source interface, and may provide a mechanism or reference point for providing a compatible interface or library by providing a definitive reference guide to the structure of relation data which is shared between the Grafana charm and any charm providing datasource information.

Provider Library Usage

The Grafana charm interacts with its datasources using its charm library. The goal of this library is to be as simple to use as possible, and instantiation of the class with or without changing the default arguments provides a complete use case. For the simplest use case of a Prometheus (or Prometheus-compatible) datasource provider in a charm which provides: grafana-source, creation of a GrafanaSourceProvider object with the default arguments is sufficient.

The default arguments are:

`charm`: `self` from the charm instantiating this library
`source_type`: None
`source_port`: None
`source_url`: None
`relation_name`: grafana-source
`refresh_event`: A `PebbleReady` event from `charm`, used to refresh
    the IP address sent to Grafana on a charm lifecycle event or
    pod restart

The value of source_url should be a fully-resolvable URL for a valid Grafana source, e.g., http://example.com/api or similar.

If your configuration requires any changes from these defaults, they may be set from the class constructor. It may be instantiated as follows:

from charms.grafana_k8s.v0.grafana_source import GrafanaSourceProvider

class FooCharm:
    def __init__(self, *args):
        super().__init__(*args, **kwargs)
        ...
        self.grafana_source_provider = GrafanaSourceProvider(
            self, source_type="prometheus", source_port="9090"
        )
        ...

The first argument (self) should be a reference to the parent (datasource) charm, as this charm's model will be used for relation data, IP addresses, and lifecycle events.

An instantiated GrafanaSourceProvider will ensure that each unit of its parent charm is added as a datasource in the Grafana configuration once a relation is established, using the Grafana datasource provisioning specification via YAML files.

This information is added to the relation data for the charms as serialized JSON from a dict, with a structure of:

{
    "application": {
        "model": charm.model.name, # from `charm` in the constructor
        "model_uuid": charm.model.uuid,
        "application": charm.model.app.name,
        "type": source_type,
    },
    "unit/0": {
        "uri": {ip_address}:{port}{path} # `ip_address` is derived at runtime, `port` from the constructor,
                                         # and `path` from the constructor, if specified
    },

This is ingested by :class:GrafanaSourceConsumer, and is sufficient for configuration.

Consumer Library Usage

The GrafanaSourceConsumer object may be used by Grafana charms to manage relations with available datasources. For this purpose, a charm consuming Grafana datasource information should do the following things:

  1. Instantiate the GrafanaSourceConsumer object by providing it a

reference to the parent (Grafana) charm and, optionally, the name of the relation that the Grafana charm uses to interact with datasources. This relation must confirm to the grafana-source interface.

For example a Grafana charm may instantiate the GrafanaSourceConsumer in its constructor as follows

from charms.grafana_k8s.v0.grafana_source import GrafanaSourceConsumer

def __init__(self, *args):
    super().__init__(*args)
    ...
    self.grafana_source_consumer = GrafanaSourceConsumer(self)
    ...

  1. A Grafana charm also needs to listen to the

GrafanaSourceEvents events emitted by the GrafanaSourceConsumer by adding itself as an observer for these events:

self.framework.observe(
    self.grafana_source_consumer.on.sources_changed,
    self._on_sources_changed,
)
self.framework.observe(
    self.grafana_source_consumer.on.sources_to_delete_changed,
    self._on_sources_to_delete_change,
)

The reason for two separate events is that Grafana keeps track of removed datasources in its datasource provisioning.

If your charm is merely implementing a grafana-source-compatible API, and is does not follow exactly the same semantics as Grafana, observing these events may not be needed.


def _type_convert_stored(obj)

Description

Convert Stored* to their appropriate types, recursively. None

class RelationNotFoundError

Description

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

Methods

RelationNotFoundError. __init__( self , relation_name: str )

class RelationInterfaceMismatchError

Description

Raised 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

Raised if the relation with the given name has a different direction. None

Methods

RelationRoleMismatchError. __init__( self , relation_name: str , expected_relation_role: RelationRole , actual_relation_role: RelationRole )

def _validate_relation_by_interface_and_direction(
    charm: CharmBase,
    relation_name: str,
    expected_relation_interface: str,
    expected_relation_role: RelationRole
)

Verifies that a relation has the necessary characteristics.

Arguments

charm
a `CharmBase` object to scan for the matching relation.
relation_name
the name of the relation to be verified.
expected_relation_interface
the interface name to be matched by the relation named `relation_name`.
expected_relation_role
whether the `relation_name` must be either provided or required by `charm`.

Description

Verifies that the `relation_name` provided: (1) exists in metadata.yaml, (2) declares as interface the interface name passed as `relation_interface` and (3) has the right "direction", i.e., it is a relation that `charm` provides or requires.

class SourceFieldsMissingError

Description

An exception to indicate there a missing fields from a Grafana datsource definition. None

class GrafanaSourcesChanged

Description

Event emitted when Grafana sources change. None

Methods

GrafanaSourcesChanged. __init__( self , handle , data )

GrafanaSourcesChanged. snapshot( self )

Description

Save grafana source information. None

GrafanaSourcesChanged. restore( self , snapshot )

Description

Restore grafana source information. None

class GrafanaSourceEvents

Description

Events raised by :class:`GrafanaSourceEvents. None

class GrafanaSourceProvider

Description

A provider object for Grafana datasources. None

Methods

GrafanaSourceProvider. __init__( self , charm: CharmBase , source_type: str , source_port , source_url , refresh_event , relation_name: str , extra_fields )

Construct a Grafana charm client.

Arguments

charm
a :class:`CharmBase` object which manages this :class:`GrafanaSourceProvider` object. Generally this is `self` in the instantiating class.
source_type
an optional (default `prometheus`) source type required for Grafana configuration. The value must match the DataSource type from the Grafana perspective.
source_port
an optional (default `9090`) source port required for Grafana configuration.
source_url
an optional source URL which can be used, for example, if ingress for a source is enabled, or a URL path to the API consumed by the datasource must be specified for another reason. If set, 'source_port' will not be used.
relation_name
string name of the relation that is provides the Grafana source service. 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 Grafana datasources.
refresh_event
a :class:`CharmEvents` event on which the IP address should be refreshed in case of pod or machine/VM restart.
extra_fields
a :dict: which is used for additional information required for some datasources in the `jsonData` field

Description

The :class:`GrafanaSourceProvider` object provides an interface to Grafana. This interface supports providing additional sources for Grafana to monitor. For example, if a charm exposes some metrics which are consumable by an ingestor (such as Prometheus), then an additional source can be added by instantiating a :class:`GrafanaSourceProvider` object and adding its datasources as follows: self.grafana = GrafanaSourceProvider(self) self.grafana.add_source( address=<address>, port=<port> )

GrafanaSourceProvider. update_source( self , source_url )

Description

Trigger the update of relation data. None

GrafanaSourceProvider. _set_sources_from_event( self , event: RelationJoinedEvent )

Description

Get a `Relation` object from the event to pass on. None

GrafanaSourceProvider. _set_sources( self , rel: Relation )

Description

Inform the consumer about the source configuration. None

GrafanaSourceProvider. _scrape_data( self )

Generate source metadata.

Returns

Source configuration data for Grafana.

GrafanaSourceProvider. _set_unit_details( self , _ )

Set unit host details.

Description

Each time a provider charm container is restarted it updates its own host address in the unit relation data for the Prometheus consumer.

class GrafanaSourceConsumer

Description

A consumer object for working with Grafana datasources. None

Methods

GrafanaSourceConsumer. __init__( self , charm: CharmBase , relation_name: str )

A Grafana based Monitoring service consumer, i.e., the charm that uses a datasource.

Arguments

charm
a :class:`CharmBase` instance that manages this instance of the Grafana source service.
relation_name
string name of the relation that is provides the Grafana source service. 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 Grafana datasources.

GrafanaSourceConsumer. _on_grafana_source_relation_changed( self , event )

Handle relation changes in related providers.

Description

If there are changes in relations between Grafana source consumers and providers, this event handler (if the unit is the leader) will get data for an incoming grafana-source relation through a

GrafanaSourceConsumer. _on_grafana_peer_changed( self , _: RelationChangedEvent )

Description

Emit source events on peer events so secondary charm data updates. None

GrafanaSourceConsumer. _get_source_config( self , rel: Relation )

Description

Generate configuration from data stored in relation data by providers. None

GrafanaSourceConsumer. _relation_hosts( self , rel: Relation )

Fetch host names and address of all provider units for a single relation.

Arguments

rel
An `ops.model.Relation` object for which the host name to address mapping is required.

Returns

A dictionary that maps unit names to unit addresses for the specified relation.

GrafanaSourceConsumer. _on_grafana_source_relation_departed( self , event: RelationDepartedEvent )

Update job config when providers depart.

Description

When a Grafana source provider departs, the configuration for that provider is removed from the list of sources jobs, added to a list of sources to remove, and other providers are informed through a :class:`GrafanaSourcesChanged` event.

GrafanaSourceConsumer. _remove_source_from_datastore( self , event: RelationDepartedEvent )

Remove the grafana-source from the datastore.

Description

Add the name to the list of sources to remove when a relation is broken. Returns a boolean indicating whether an event should be emitted.

GrafanaSourceConsumer. _remove_source( self , source_name: str )

Description

Remove a datasource by name. None

GrafanaSourceConsumer. upgrade_keys( self )

Description

On upgrade, ensure stored data maintains compatibility. None

GrafanaSourceConsumer. update_sources( self , relation )

Re-establish sources on one or more relations.

Arguments

relation
a specific relation for which the datasources have to be updated. If not specified, all relations managed by this :class:`GrafanaSourceConsumer` will be updated.

Description

If something changes between this library and a datasource, try to re-establish datasources.

GrafanaSourceConsumer. sources( self )

Description

Returns an array of sources the source_consumer knows about. None

GrafanaSourceConsumer. sources_to_delete( self )

Description

Returns an array of source names which have been removed. None

GrafanaSourceConsumer. _set_default_data( self )

Description

Set defaults if they are not in peer relation data. None

GrafanaSourceConsumer. set_peer_data( self , key: str , data: Any )

Description

Put information into the peer data bucket instead of `StoredState`. None

GrafanaSourceConsumer. get_peer_data( self , key: str )

Description

Retrieve information from the peer data bucket instead of `StoredState`. None