OpenTelemetry Click Instrumentation
This library provides automatic instrumentation for applications built with the Click framework, allowing them to emit traces and spans compatible with the OpenTelemetry specification. It is part of the `opentelemetry-python-contrib` repository, currently in beta version 0.62b0, and receives frequent updates alongside other contributed instrumentations.
Warnings
- gotcha This instrumentation library is currently in beta (`0.62b0`). While functional, it may introduce breaking changes in future minor or patch versions before reaching a stable 1.0 release.
- gotcha For the Click instrumentation to generate telemetry, you must have `opentelemetry-api` and `opentelemetry-sdk` installed alongside `opentelemetry-instrumentation-click`. The `click` library itself must also be installed in your environment.
- gotcha In CLI applications, especially those with multiple subcommands or long-running tasks, proper context propagation can be challenging. While the instrumentation provides basic tracing, complex scenarios might require manual intervention to ensure trace context correctly flows across different parts of your Click application or to other services.
Install
-
pip install opentelemetry-instrumentation-click
Imports
- ClickInstrumentor
from opentelemetry.instrumentation.click import ClickInstrumentor
Quickstart
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor
from opentelemetry.instrumentation.click import ClickInstrumentor
import click
import os
# 1. Configure OpenTelemetry TracerProvider and Exporter
# In a real application, you would typically use an OTLPSpanExporter
# pointing to an OpenTelemetry Collector or an observability backend.
resource = Resource.create({"service.name": "my-click-cli"})
provider = TracerProvider(resource=resource)
span_processor = SimpleSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(span_processor)
trace.set_tracer_provider(provider)
# 2. Instrument Click
ClickInstrumentor().instrument()
# 3. Define a Click application
@click.group()
def cli():
"""A simple CLI application."""
pass
@cli.command()
@click.option('--name', default='World', help='Name to greet.')
def hello(name):
"""Greets the user."""
# Manual span creation to show how to add more detail
with trace.get_current_tracer().start_as_current_span("say-hello-command"):
click.echo(f"Hello, {name}!")
@cli.command()
@click.argument('num', type=int)
def square(num):
"""Calculates the square of a number."""
with trace.get_current_tracer().start_as_current_span("calculate-square-command"):
result = num * num
click.echo(f"The square of {num} is {result}")
if __name__ == '__main__':
# To run this example:
# 1. Save the code as `app.py`.
# 2. Execute from your terminal:
# python app.py hello --name OpenTelemetry
# python app.py square 7
cli()