tempo-k8s docs how to instrument your charm

Tracing your charm execution

When we talk about tracing, we often refer to traces that are being sent from the workload container. However, there might be cases, for debugging purposes, where you might want to instrument your charm itself to send traces about its execution.

Fetch the charm_tracing charm library

charmcraft fetch-lib charms.tempo_k8s.v1.charm_tracing

For the purpose of auto-instrumenting your charm to send its traces, charm_tracing charm library is used.

It contains utilities to instrument your charm not the workload with opentelemetry tracing data collection. This means that, if your charm is related to tempo-k8s charm and tempo-k8s is related to grafana-k8s, you will be able to inspect in real time from the Grafana dashboard the execution flow of your charm.

Use charm_tracing library

from charms.tempo_k8s.v1.charm_tracing import trace_charm

  @trace_charm(
      tracing_endpoint="my_tracing_endpoint",
  )
  class FooCharm:

  ...

      @property
      def my_tracing_endpoint(self) -> Optional[str]:
          '''Tempo endpoint for charm tracing'''
          if self.tracing.is_ready():
              return self.tracing.otlp_http_endpoint()
          else:
              return None

by decorating your charm class Foo with trace_charm decorator, it’s expected to provide a Tempo Opentelemetry otlp_http protocol endpoint to it, which will be retrieved from the class property my_tracing_endpoint.

The decorator assumes your charm already have access to the tempo endpoint, which can be retrieved by integrating with tempo-k8s over tracing using the otlp_http protocol.

At this point your charm Foo will be automatically instrumented so that:

  • Every charm execution starts a trace, containing
    • every juju event as a span.
    • every ops event as a span.
    • every charm method call (except dunders) as a span.

See more about the analogy between charm execution and traces in traces in the charm realm.

Auto instrument other types

The decorator will create spans for your Charm Class method calls. However, you might have other classes that you make use of inside your charm class, like charm libs, relation endpoint wrappers, workload abstractions, …etc, and you want to auto-instrument them as well.

This can be achieved using extra_types parameter.

Using extra_types parameter

from charms.tempo_k8s.v1.charm_tracing import trace_charm
from charms.prometheus_k8s.v0.prometheus_scrape import MetricsEndpointProvider

  @trace_charm(
      tracing_endpoint="my_tracing_endpoint",
      extra_types=[
        MetricsEndpointProvider,
      ],
  )
  class FooCharm:

  ...

appending types to the list passed to extra_types will make the decorator get out-of-the-box traces for all method calls on instances of this class MetricsEndpointProvider.