OpenCensus Python
OpenCensus Python is a framework for collecting application metrics and distributed traces. It enables developers to gain observability into their systems by providing libraries to gather telemetry data and export it to a chosen backend. The current version is 0.11.4. While the `opencensus-python` repository continues to see updates, the broader OpenCensus project has merged into OpenTelemetry, with users generally encouraged to migrate.
Common errors
-
ModuleNotFoundError: No module named 'opencensus'
cause The main `opencensus` package or one of its required extension packages has not been installed in the Python environment.fixInstall the core library using `pip install opencensus`. If using specific integrations (e.g., for Azure or Stackdriver), also install the relevant extension package, such as `pip install opencensus-ext-azure` or `pip install opencensus-ext-stackdriver`. -
ImportError: cannot import name 'X' from 'opencensus.Y'
cause This error typically indicates that a specific module or class being imported from `opencensus` either does not exist at the specified path, has been moved in a different version, or there's a version incompatibility between `opencensus` and another library it integrates with (e.g., `sqlalchemy`).fixVerify the exact import path against the official OpenCensus Python documentation for your installed version. If using an extension library (like `opencensus-ext-sqlalchemy`), check its compatibility matrix with the version of the integrated library (e.g., `sqlalchemy`) you are using, and consider upgrading or downgrading dependencies as needed. -
AttributeError: 'NoneType' object has no attribute 'span'
cause This usually happens when a `Tracer` or `Span` object, which is expected to be active, is `None`. This can occur if a `ProbabilitySampler` decides not to sample a given trace (resulting in a `None` span), or if the tracing context is not properly initialized or propagated, especially within custom middleware or complex application structures.fixDuring development or debugging, configure the tracer with an `AlwaysOnSampler` (e.g., `tracer = Tracer(sampler=AlwaysOnSampler())`) to ensure all traces are sampled and spans are always created. For production, ensure the tracing context is correctly managed and propagated throughout your application, especially in areas using custom middleware where the span might not be available in the execution context. -
OpenCensus traces not appearing in Stackdriver Trace (or Azure Monitor)
cause Traces are being collected by OpenCensus but are not successfully exported to or displayed in the chosen backend. Common reasons include: the default probabilistic sampling rate is too low, traces are not being flushed by the exporter before the application exits, or there's an issue with authentication/configuration (e.g., incorrect project ID, missing environment variables in containerized environments, or an expired instrumentation key for Azure Monitor).fixSet the sampler to `AlwaysOnSampler()` during debugging to ensure all traces are sent. Manually call `exporter.flush()` before your application terminates. For Google Cloud, ensure `GOOGLE_APPLICATION_CREDENTIALS` or a service account with `Cloud Trace Agent` role is configured, and that `CONTAINER_NAME` and `NAMESPACE` environment variables are set in GKE. For Azure, verify the `APPLICATIONINSIGHTS_CONNECTION_STRING` environment variable or the connection string in code is correct and valid. -
ModuleNotFoundError: No module named 'opencensus.ext.google_cloud_monitoring'
cause The specific OpenCensus exporter extension module (e.g., `opencensus-ext-google-cloud-monitoring`) has not been installed.fixInstall the required exporter package using pip: `pip install opencensus-ext-google-cloud-monitoring` (or the relevant extension for your chosen backend).
Warnings
- breaking OpenCensus has merged with OpenTracing to form OpenTelemetry, which is considered the next major version. Users are strongly encouraged to migrate to OpenTelemetry for future-proof observability solutions. While `opencensus-python` is an exception to the archiving of other OpenCensus repositories, the broader OpenCensus project does not receive new features or security patches since July 31, 2023.
- breaking Migration from OpenCensus to OpenTelemetry, even with bridge libraries, is considered a 'major version bump'. It may involve changes in import paths, method names, and telemetry data models.
- gotcha OpenCensus Python originally shipped as a monolithic package. While core functionality remains in `opencensus`, integrations (e.g., Flask, Django, Requests) and many exporters are now provided as separate `opencensus-ext-*` packages. Installing the core library alone will not include these extensions.
- gotcha By default, OpenCensus traces are exported to `stdout` using the `PrintExporter`. To send telemetry data to a real backend (e.g., Azure Monitor, Stackdriver, Zipkin), you must explicitly configure and use the appropriate exporter.
- gotcha When integrating with database ORMs like SQLAlchemy, if you also enable tracing for the underlying database driver (e.g., `mysql`, `postgresql`), you may end up with duplicate spans for the same database operation.
Install
-
pip install opencensus -
pip install opencensus-ext-azure
Imports
- Tracer
from opencensus.trace.tracer import Tracer
- AlwaysOnSampler
from opencensus.trace.samplers import AlwaysOnSampler
- PrintExporter
from opencensus.trace.exporters.print_exporter import PrintExporter
from opencensus.trace.exporters import PrintExporter
- stats
from opencensus.stats import stats as stats_module
Quickstart
from opencensus.trace.tracer import Tracer
from opencensus.trace.samplers import AlwaysOnSampler
from opencensus.trace.exporters import PrintExporter
def my_function_to_trace():
print("Doing some work inside the traced function...")
# Initialize a tracer with an exporter and a sampler
exporter = PrintExporter()
tracer = Tracer(exporter=exporter, sampler=AlwaysOnSampler())
# Use the tracer to create a span
with tracer.span(name='my_parent_span') as span:
span.add_annotation('Starting my_parent_span operation')
print(f"Current Span ID: {span.span_id}")
with tracer.span(name='my_child_span') as child_span:
child_span.add_annotation('Starting my_child_span operation')
my_function_to_trace()
child_span.add_annotation('Finished my_child_span operation')
span.add_annotation('Finished my_parent_span operation')
print("Traced operations complete.")