Skip to content

Commit

Permalink
migrated charm tracing libs (#194)
Browse files Browse the repository at this point in the history
* migrated charm tracing libs

* migrated charm tracing libs

* fix conflicts

* fix ref

* fixed some typing issues in cos_agent lib

* fmt

* pin pytest-operator

---------

Co-authored-by: michael <michael.dmitry98@gmail.com>
Co-authored-by: Michael Dmitry <33381599+michaeldmitry@users.noreply.github.com>
  • Loading branch information
3 people authored Oct 22, 2024
1 parent 51df185 commit 36401e9
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 49 deletions.
12 changes: 6 additions & 6 deletions lib/charms/grafana_agent/v0/cos_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,10 @@ def __init__(self, *args):
import pydantic
from cosl import GrafanaDashboard, JujuTopology
from cosl.rules import AlertRules
from ops import CharmBase
from ops.charm import RelationChangedEvent
from ops.framework import EventBase, EventSource, Object, ObjectEvents
from ops.model import ModelError, Relation
from ops.testing import CharmType

if TYPE_CHECKING:
try:
Expand Down Expand Up @@ -468,7 +468,7 @@ def dump(self, databag: Optional[MutableMapping] = None, clear: bool = True):
return databag


class CosAgentProviderUnitData(DatabagModel):
class CosAgentProviderUnitData(DatabagModel): # pyright: ignore [reportGeneralTypeIssues]
"""Unit databag model for `cos-agent` relation."""

# The following entries are the same for all units of the same principal.
Expand All @@ -495,7 +495,7 @@ class CosAgentProviderUnitData(DatabagModel):
KEY: ClassVar[str] = "config"


class CosAgentPeersUnitData(DatabagModel):
class CosAgentPeersUnitData(DatabagModel): # pyright: ignore [reportGeneralTypeIssues]
"""Unit databag model for `peers` cos-agent machine charm peer relation."""

# We need the principal unit name and relation metadata to be able to render identifiers
Expand Down Expand Up @@ -594,7 +594,7 @@ class Receiver(pydantic.BaseModel):
)


class CosAgentRequirerUnitData(DatabagModel): # noqa: D101
class CosAgentRequirerUnitData(DatabagModel): # pyright: ignore [reportGeneralTypeIssues] # noqa: D101
"""Application databag model for the COS-agent requirer."""

receivers: List[Receiver] = pydantic.Field(
Expand All @@ -608,7 +608,7 @@ class COSAgentProvider(Object):

def __init__(
self,
charm: CharmType,
charm: CharmBase,
relation_name: str = DEFAULT_RELATION_NAME,
metrics_endpoints: Optional[List["_MetricsEndpointDict"]] = None,
metrics_rules_dir: str = "./src/prometheus_alert_rules",
Expand Down Expand Up @@ -877,7 +877,7 @@ class COSAgentRequirer(Object):

def __init__(
self,
charm: CharmType,
charm: CharmBase,
*,
relation_name: str = DEFAULT_RELATION_NAME,
peer_relation_name: str = DEFAULT_PEER_RELATION_NAME,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
# Quickstart
Fetch the following charm libs (and ensure the minimum version/revision numbers are satisfied):
charmcraft fetch-lib charms.tempo_k8s.v2.tracing # >= 1.10
charmcraft fetch-lib charms.tempo_k8s.v1.charm_tracing # >= 2.7
charmcraft fetch-lib charms.tempo_coordinator_k8s.v0.tracing # >= 1.10
charmcraft fetch-lib charms.tempo_coordinator_k8s.v0.charm_tracing # >= 2.7
Then edit your charm code to include:
```python
# import the necessary charm libs
from charms.tempo_k8s.v2.tracing import TracingEndpointRequirer, charm_tracing_config
from charms.tempo_k8s.v1.charm_tracing import charm_tracing
from charms.tempo_coordinator_k8s.v0.tracing import TracingEndpointRequirer, charm_tracing_config
from charms.tempo_coordinator_k8s.v0.charm_tracing import charm_tracing
# decorate your charm class with charm_tracing:
@charm_tracing(
Expand Down Expand Up @@ -51,7 +51,7 @@ def __init__(self, ...):
2) add to your charm a "my_tracing_endpoint" (you can name this attribute whatever you like)
**property**, **method** or **instance attribute** that returns an otlp http/https endpoint url.
If you are using the ``charms.tempo_k8s.v2.tracing.TracingEndpointRequirer`` as
If you are using the ``charms.tempo_coordinator_k8s.v0.tracing.TracingEndpointRequirer`` as
``self.tracing = TracingEndpointRequirer(self)``, the implementation could be:
```
Expand Down Expand Up @@ -80,7 +80,7 @@ def my_tracing_endpoint(self) -> Optional[str]:
For example:
```
from charms.tempo_k8s.v1.charm_tracing import trace_charm
from charms.tempo_coordinator_k8s.v0.charm_tracing import trace_charm
@trace_charm(
tracing_endpoint="my_tracing_endpoint",
server_cert="_server_cert"
Expand Down Expand Up @@ -129,7 +129,7 @@ def get_tracer(self) -> opentelemetry.trace.Tracer:
For example:
```
from charms.tempo_k8s.v0.charm_tracing import trace_charm
from charms.tempo_coordinator_k8s.v0.charm_tracing import trace_charm
@trace_charm(
tracing_endpoint="my_tracing_endpoint",
Expand All @@ -150,7 +150,7 @@ def my_tracing_endpoint(self) -> Optional[str]:
needs to be replaced with:
```
from charms.tempo_k8s.v1.charm_tracing import trace_charm
from charms.tempo_coordinator_k8s.v0.charm_tracing import trace_charm
@trace_charm(
tracing_endpoint="my_tracing_endpoint",
Expand Down Expand Up @@ -249,28 +249,27 @@ def _remove_stale_otel_sdk_packages():
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import Span, TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.trace import INVALID_SPAN, Tracer
from opentelemetry.trace import get_current_span as otlp_get_current_span
from opentelemetry.trace import (
INVALID_SPAN,
Tracer,
get_tracer,
get_tracer_provider,
set_span_in_context,
set_tracer_provider,
)
from opentelemetry.trace import get_current_span as otlp_get_current_span
from ops.charm import CharmBase
from ops.framework import Framework

# The unique Charmhub library identifier, never change it
LIBID = "cb1705dcd1a14ca09b2e60187d1215c7"
LIBID = "01780f1e588c42c3976d26780fdf9b89"

# Increment this major API version when introducing breaking changes
LIBAPI = 1
LIBAPI = 0

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

LIBPATCH = 15
LIBPATCH = 2

PYDEPS = ["opentelemetry-exporter-otlp-proto-http==1.21.0"]

Expand Down Expand Up @@ -332,7 +331,7 @@ def _get_tracer() -> Optional[Tracer]:
return tracer.get()
except LookupError:
# fallback: this course-corrects for a user error where charm_tracing symbols are imported
# from different paths (typically charms.tempo_k8s... and lib.charms.tempo_k8s...)
# from different paths (typically charms.tempo_coordinator_k8s... and lib.charms.tempo_coordinator_k8s...)
try:
ctx: Context = copy_context()
if context_tracer := _get_tracer_from_context(ctx):
Expand Down Expand Up @@ -372,10 +371,6 @@ class UntraceableObjectError(TracingError):
"""Raised when an object you're attempting to instrument cannot be autoinstrumented."""


class TLSError(TracingError):
"""Raised when the tracing endpoint is https but we don't have a cert yet."""


def _get_tracing_endpoint(
tracing_endpoint_attr: str,
charm_instance: object,
Expand Down Expand Up @@ -485,10 +480,15 @@ def wrap_init(self: CharmBase, framework: Framework, *args, **kwargs):
)

if tracing_endpoint.startswith("https://") and not server_cert:
raise TLSError(
logger.error(
"Tracing endpoint is https, but no server_cert has been passed."
"Please point @trace_charm to a `server_cert` attr."
"Please point @trace_charm to a `server_cert` attr. "
"This might also mean that the tracing provider is related to a "
"certificates provider, but this application is not (yet). "
"In that case, you might just have to wait a bit for the certificates "
"integration to settle. "
)
return

exporter = OTLPSpanExporter(
endpoint=tracing_endpoint,
Expand Down Expand Up @@ -562,8 +562,8 @@ def trace_charm(
method calls on instances of this class.
Usage:
>>> from charms.tempo_k8s.v1.charm_tracing import trace_charm
>>> from charms.tempo_k8s.v1.tracing import TracingEndpointRequirer
>>> from charms.tempo_coordinator_k8s.v0.charm_tracing import trace_charm
>>> from charms.tempo_coordinator_k8s.v0.tracing import TracingEndpointRequirer
>>> from ops import CharmBase
>>>
>>> @trace_charm(
Expand Down Expand Up @@ -626,7 +626,7 @@ def _autoinstrument(
Usage:
>>> from charms.tempo_k8s.v1.charm_tracing import _autoinstrument
>>> from charms.tempo_coordinator_k8s.v0.charm_tracing import _autoinstrument
>>> from ops.main import main
>>> _autoinstrument(
>>> MyCharm,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
This relation must use the `tracing` interface.
The `TracingEndpointRequirer` object may be instantiated as follows
from charms.tempo_k8s.v2.tracing import TracingEndpointRequirer
from charms.tempo_coordinator_k8s.v0.tracing import TracingEndpointRequirer
def __init__(self, *args):
super().__init__(*args)
Expand Down Expand Up @@ -58,7 +58,7 @@ def __init__(self, *args):
For example a Tempo charm may instantiate the `TracingEndpointProvider` in its constructor as
follows
from charms.tempo_k8s.v2.tracing import TracingEndpointProvider
from charms.tempo_coordinator_k8s.v0.tracing import TracingEndpointProvider
def __init__(self, *args):
super().__init__(*args)
Expand Down Expand Up @@ -100,14 +100,14 @@ def __init__(self, *args):
from pydantic import BaseModel, Field

# The unique Charmhub library identifier, never change it
LIBID = "12977e9aa0b34367903d8afeb8c3d85d"
LIBID = "d2f02b1f8d1244b5989fd55bc3a28943"

# Increment this major API version when introducing breaking changes
LIBAPI = 2
LIBAPI = 0

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

PYDEPS = ["pydantic"]

Expand Down Expand Up @@ -947,8 +947,8 @@ def charm_tracing_config(
Usage:
If you are using charm_tracing >= v1.9:
>>> from lib.charms.tempo_k8s.v1.charm_tracing import trace_charm
>>> from lib.charms.tempo_k8s.v2.tracing import charm_tracing_config
>>> 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"
Expand All @@ -958,8 +958,8 @@ def charm_tracing_config(
... self.tracing, self._cert_path)
If you are using charm_tracing < v1.9:
>>> from lib.charms.tempo_k8s.v1.charm_tracing import trace_charm
>>> from lib.charms.tempo_k8s.v2.tracing import charm_tracing_config
>>> 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"
Expand All @@ -985,11 +985,16 @@ def charm_tracing_config(
is_https = endpoint.startswith("https://")

if is_https:
if cert_path is None:
raise TracingError("Cannot send traces to an https endpoint without a certificate.")
elif not Path(cert_path).exists():
# if endpoint is https BUT we don't have a server_cert yet:
# disable charm tracing until we do to prevent tls errors
if cert_path is None or not Path(cert_path).exists():
# disable charm tracing until we obtain a cert to prevent tls errors
logger.error(
"Tracing endpoint is https, but no server_cert has been passed."
"Please point @trace_charm to a `server_cert` attr. "
"This might also mean that the tracing provider is related to a "
"certificates provider, but this application is not (yet). "
"In that case, you might just have to wait a bit for the certificates "
"integration to settle. "
)
return None, None
return endpoint, str(cert_path)
else:
Expand Down
2 changes: 1 addition & 1 deletion src/charm.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import yaml
from charms.grafana_agent.v0.cos_agent import COSAgentRequirer, ReceiverProtocol
from charms.operator_libs_linux.v2 import snap # type: ignore
from charms.tempo_k8s.v1.charm_tracing import trace_charm
from charms.tempo_coordinator_k8s.v0.charm_tracing import trace_charm
from cosl import JujuTopology
from cosl.rules import AlertRules
from ops.main import main
Expand Down
2 changes: 1 addition & 1 deletion src/grafana_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from charms.prometheus_k8s.v1.prometheus_remote_write import (
PrometheusRemoteWriteConsumer,
)
from charms.tempo_k8s.v2.tracing import TracingEndpointRequirer, charm_tracing_config
from charms.tempo_coordinator_k8s.v0.tracing import TracingEndpointRequirer, charm_tracing_config
from cosl import MandatoryRelationPairs
from ops.charm import CharmBase
from ops.model import ActiveStatus, BlockedStatus, WaitingStatus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
import pytest
import yaml
from charms.grafana_agent.v0.cos_agent import ReceiverProtocol
from charms.tempo_k8s.v2.tracing import ReceiverProtocol as TracingReceiverProtocol
from charms.tempo_coordinator_k8s.v0.tracing import ReceiverProtocol as TracingReceiverProtocol
from scenario import Context, Relation, State, SubordinateRelation

from charm import GrafanaAgentMachineCharm
from lib.charms.grafana_agent.v0.cos_agent import (
CosAgentProviderUnitData,
Receiver,
)
from lib.charms.tempo_k8s.v2.tracing import TracingProviderAppData
from lib.charms.tempo_coordinator_k8s.v0.tracing import TracingProviderAppData


def test_cos_agent_receiver_protocols_match_with_tracing():
Expand Down
4 changes: 3 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ deps =
# Temporarily pinning pytest due to https://github.com/charmed-kubernetes/pytest-operator/issues/131
pytest ~= 8.1.1
prometheus-api-client
pytest-operator
# newer versions don't work well when charmcraft pack produces more than 1 file
# build_charm only processes the 1st file
pytest-operator == 0.35.0
commands =
pytest -v --tb native --log-cli-level=INFO -s {posargs} {[vars]tst_path}/integration

Expand Down

0 comments on commit 36401e9

Please sign in to comment.