Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor charm handlers #311

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ __pycache__/
tests/integration/*-tester/lib/
.env
cos-tool*

*.egg-info/
loki_alert_rules/
prometheus_alert_rules/
grafana_dashboards/
30 changes: 30 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,33 @@ options:
Loki).
type: boolean
default: false
always_enable_zipkin:
description: >
Force-enable the receiver for the 'zipkin' protocol in Grafana Agent,
even if there is no integration currently requesting it.
type: boolean
default: false
always_enable_otlp_grpc:
description: >
Force-enable the receiver for the 'otlp_grpc' protocol in Grafana Agent,
even if there is no integration currently requesting it.
type: boolean
default: false
always_enable_otlp_http:
description: >
Force-enable the receiver for the 'otlp_http' protocol in Grafana Agent,
even if there is no integration currently requesting it.
type: boolean
default: false
always_enable_jaeger_grpc:
description: >
Force-enable the receiver for the 'jaeger_grpc' protocol in Grafana Agent,
even if there is no integration currently requesting it.
type: boolean
default: false
always_enable_jaeger_thrift_http:
description: >
Force-enable the receiver for the 'jaeger_thrift_http' protocol in Grafana Agent,
even if there is no integration currently requesting it.
type: boolean
default: false
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ def _on_certificate_removed(self, event: CertificateRemovedEvent):

"""


import json
import logging
from typing import List, Mapping
Expand All @@ -113,7 +112,7 @@ def _on_certificate_removed(self, event: CertificateRemovedEvent):

# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 7
LIBPATCH = 8

PYDEPS = ["jsonschema"]

Expand Down
16 changes: 12 additions & 4 deletions lib/charms/grafana_cloud_integrator/v0/cloud_config_requirer.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

LIBID = "e6f580481c1b4388aa4d2cdf412a47fa"
LIBAPI = 0
LIBPATCH = 4
LIBPATCH = 5

DEFAULT_RELATION_NAME = "grafana-cloud-config"

Expand Down Expand Up @@ -121,24 +121,32 @@ def loki_endpoint(self) -> dict:
def prometheus_ready(self):
return self._is_not_empty(self.prometheus_url)

@property
def tempo_ready(self):
return self._is_not_empty(self.tempo_url)

@property
def prometheus_endpoint(self) -> dict:
"""Return the prometheus endpoint dict."""
if not self.prometheus_ready:
return {}

endpoint = {}
endpoint["url"] = self.prometheus_url
if self.credentials:
endpoint["basic_auth"] = {"username": self.credentials.username, "password": self.credentials.password}
return endpoint

@property
def loki_url(self):
def loki_url(self) -> str:
return self._data.get("loki_url", "")

@property
def prometheus_url(self):
def tempo_url(self) -> str:
return self._data.get("tempo_url", "")

@property
def prometheus_url(self) -> str:
return self._data.get("prometheus_url", "")

@property
Expand Down
3 changes: 2 additions & 1 deletion lib/charms/grafana_k8s/v0/grafana_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ def __init__(self, *args):
# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version

LIBPATCH = 35
LIBPATCH = 36

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -1050,6 +1050,7 @@ def __init__(

self.framework.observe(self._charm.on.leader_elected, self._update_all_dashboards_from_dir)
self.framework.observe(self._charm.on.upgrade_charm, self._update_all_dashboards_from_dir)
self.framework.observe(self._charm.on.config_changed, self._update_all_dashboards_from_dir)

self.framework.observe(
self._charm.on[self._relation_name].relation_created,
Expand Down
59 changes: 43 additions & 16 deletions lib/charms/loki_k8s/v1/loki_push_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,24 @@
send log to Loki by implementing the consumer side of the `loki_push_api` relation interface.
For instance, a Promtail or Grafana agent charm which needs to send logs to Loki.

- `LogProxyConsumer`: This object can be used by any Charmed Operator which needs to
send telemetry, such as logs, to Loki through a Log Proxy by implementing the consumer side of the
`loki_push_api` relation interface.
- `LogProxyConsumer`: DEPRECATED.
This object can be used by any Charmed Operator which needs to send telemetry, such as logs, to
Loki through a Log Proxy by implementing the consumer side of the `loki_push_api` relation
interface.
In order to be able to control the labels on the logs pushed this object adds a Pebble layer
that runs Promtail in the workload container, injecting Juju topology labels into the
logs on the fly.
This object is deprecated. Consider migrating to LogForwarder with the release of Juju 3.6 LTS.

- `LogForwarder`: This object can be used by any Charmed Operator which needs to send the workload
standard output (stdout) through Pebble's log forwarding mechanism, to Loki endpoints through the
`loki_push_api` relation interface.
In order to be able to control the labels on the logs pushed this object updates the pebble layer's
"log-targets" section with Juju topology.

Filtering logs in Loki is largely performed on the basis of labels. In the Juju ecosystem, Juju
topology labels are used to uniquely identify the workload which generates telemetry like logs.

In order to be able to control the labels on the logs pushed this object adds a Pebble layer
that runs Promtail in the workload container, injecting Juju topology labels into the
logs on the fly.

## LokiPushApiProvider Library Usage

Expand All @@ -42,13 +46,14 @@
- `charm`: A reference to the parent (Loki) charm.

- `relation_name`: The name of the relation that the charm uses to interact
with its clients, which implement `LokiPushApiConsumer` or `LogProxyConsumer`.
with its clients, which implement `LokiPushApiConsumer` `LogForwarder`, or `LogProxyConsumer`
(note that LogProxyConsumer is deprecated).

If provided, this relation name must match a provided relation in metadata.yaml with the
`loki_push_api` interface.

The default relation name is "logging" for `LokiPushApiConsumer` and "log-proxy" for
`LogProxyConsumer`.
The default relation name is "logging" for `LokiPushApiConsumer` and `LogForwarder`, and
"log-proxy" for `LogProxyConsumer` (note that LogProxyConsumer is deprecated).

For example, a provider's `metadata.yaml` file may look as follows:

Expand Down Expand Up @@ -223,6 +228,9 @@ def __init__(self, *args):

## LogProxyConsumer Library Usage

> Note: This object is deprecated. Consider migrating to LogForwarder with the release of Juju 3.6
> LTS.

Let's say that we have a workload charm that produces logs, and we need to send those logs to a
workload implementing the `loki_push_api` interface, such as `Loki` or `Grafana Agent`.

Expand Down Expand Up @@ -519,7 +527,7 @@ def _alert_rules_error(self, event):

# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 8
LIBPATCH = 12

PYDEPS = ["cosl"]

Expand All @@ -534,13 +542,21 @@ def _alert_rules_error(self, event):
# To update Promtail version you only need to change the PROMTAIL_VERSION and
# update all sha256 sums in PROMTAIL_BINARIES. To support a new architecture
# you only need to add a new key value pair for the architecture in PROMTAIL_BINARIES.
PROMTAIL_VERSION = "v2.5.0"
PROMTAIL_VERSION = "v2.9.7"
PROMTAIL_ARM_BINARY = {
"filename": "promtail-static-arm64",
"zipsha": "c083fdb45e5c794103f974eeb426489b4142438d9e10d0ae272b2aff886e249b",
"binsha": "4cd055c477a301c0bdfdbcea514e6e93f6df5d57425ce10ffc77f3e16fec1ddf",
}

PROMTAIL_BINARIES = {
"amd64": {
"filename": "promtail-static-amd64",
"zipsha": "543e333b0184e14015a42c3c9e9e66d2464aaa66eca48b29e185a6a18f67ab6d",
"binsha": "17e2e271e65f793a9fbe81eab887b941e9d680abe82d5a0602888c50f5e0cac9",
"zipsha": "6873cbdabf23062aeefed6de5f00ff382710332af3ab90a48c253ea17e08f465",
"binsha": "28da9b99f81296fe297831f3bc9d92aea43b4a92826b8ff04ba433b8cb92fb50",
},
"arm64": PROMTAIL_ARM_BINARY,
"aarch64": PROMTAIL_ARM_BINARY,
}

# Paths in `charm` container
Expand Down Expand Up @@ -1585,7 +1601,8 @@ def __init__(
the Loki API endpoint to push logs. It is intended for workloads that can speak
loki_push_api (https://grafana.com/docs/loki/latest/api/#push-log-entries-to-loki), such
as grafana-agent.
(If you only need to forward a few workload log files, then use LogProxyConsumer.)
(If you need to forward workload stdout logs, then use LogForwarder; if you need to forward
log files, then use LogProxyConsumer.)

`LokiPushApiConsumer` can be instantiated as follows:

Expand Down Expand Up @@ -1760,6 +1777,9 @@ class LogProxyEvents(ObjectEvents):
class LogProxyConsumer(ConsumerBase):
"""LogProxyConsumer class.

> Note: This object is deprecated. Consider migrating to LogForwarder with the release of Juju
> 3.6 LTS.

The `LogProxyConsumer` object provides a method for attaching `promtail` to
a workload in order to generate structured logging data from applications
which traditionally log to syslog or do not have native Loki integration.
Expand Down Expand Up @@ -1831,7 +1851,12 @@ def __init__(

# architecture used for promtail binary
arch = platform.processor()
self._arch = "amd64" if arch == "x86_64" else arch
if arch in ["x86_64", "amd64"]:
self._arch = "amd64"
elif arch in ["aarch64", "arm64", "armv8b", "armv8l"]:
self._arch = "arm64"
else:
self._arch = arch

events = self._charm.on[relation_name]
self.framework.observe(events.relation_created, self._on_relation_created)
Expand Down Expand Up @@ -2537,7 +2562,9 @@ def _update_logging(self, _):
return

for container in self._charm.unit.containers.values():
self._update_endpoints(container, loki_endpoints)
if container.can_connect():
self._update_endpoints(container, loki_endpoints)
# else: `_update_endpoints` will be called on pebble-ready anyway.

def _retrieve_endpoints_from_relation(self) -> dict:
loki_endpoints = {}
Expand Down
Loading
Loading