This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
observlib is a Python library that provides a unified interface for observability (tracing, metrics, and logging) using OpenTelemetry. It simplifies configuration of distributed tracing, metric collection, and structured logging with support for OTLP, Prometheus, and Pyroscope backends.
observlib/
├── observlib/ # Main package
│ ├── __init__.py # Main API: configure_telemetry()
│ ├── decorator.py # @traced decorator for instrumenting functions
│ ├── logs.py # Logging configuration with OTLP
│ ├── metrics.py # Metrics configuration (Prometheus + OTLP)
│ └── traces.py # Tracing configuration with Pyroscope support
├── tests/ # Test suite
│ └── test_observlib.py # Integration tests using pytest
├── nix/ # Nix development environment
├── pyproject.toml # Project metadata and dependencies
├── pytest.ini # Pytest configuration
└── uv.lock # Locked dependency versions
The library has three main configuration modules that work together:
- Tracing (
traces.py): Sets up OpenTelemetry TracerProvider with OTLP span exporter and Pyroscope span processor - Metrics (
metrics.py): Configures MeterProvider with Prometheus reader and optional OTLP exporter - Logging (
logs.py): Sets up LoggerProvider with OTLP log exporter and Python logging integration
The @traced decorator (decorator.py) is the main user-facing API that:
- Creates spans for function execution
- Records execution time as histogram metrics
- Records function calls as counter metrics
- Supports both sync and async functions
- Allows custom labels and amounts via
label_fnandamount_fncallbacks
The configure_telemetry() function in __init__.py is the entry point that:
- Sets up all three telemetry components
- Accepts optional OTLP server endpoint, Pyroscope server, and resource attributes
- Creates a Resource with service.name and any custom attributes
The project uses Nix for reproducible development environments:
# Enter development shell
nix flake update # Update dependencies if needed
nix develop # Activates development environment with all dependenciesAll dependencies (both main and test) are installed via the Nix devshell. When you add new dependencies to pyproject.toml, update nix/shells/dev/default.nix to include them in the packages list.
Code Quality:
ruff check observlib/ # Lint code
ruff format observlib/ # Format codeRunning Code:
cd observlib
python -c "from observlib import configure_telemetry; ..." # Direct importsTesting:
cd observlib
# Install test dependencies
nix develop --command uv sync --extra test
# Run all tests
nix develop --command uv run pytest -v
# Run specific test file
nix develop --command uv run pytest tests/test_observlib.py -vDependency Management:
- Update
pyproject.tomlto add/remove dependencies - Update
nix/shells/dev/default.nixto include the new packages in thepackageslist withpython313Packages.package_name - Re-enter the nix shell:
exitandnix develop
-
OpenTelemetry: Distributed tracing and metrics instrumentation
opentelemetry-api: Core APIopentelemetry-sdk: SDK with exporters and processorsopentelemetry-exporter-otlp: HTTP-based OTLP protocol exporteropentelemetry-exporter-prometheus: Prometheus metrics readeropentelemetry-instrumentation-logging: Python logging integration
-
Pyroscope: Continuous profiling
pyroscope-io: Profiler clientpyroscope-otel: OpenTelemetry integration
The decorator in decorator.py:8 wraps both sync and async functions. Key features:
- Tracing: Always creates a span using the tracer provider (line 111/148)
- Metrics Recording:
- Histograms record execution time (line 51-73)
- Counters track invocations with configurable amounts (line 88-104)
- Error Handling: Sets span status to ERROR on exceptions (line 119/157)
- Flexible Configuration:
timer/timer_factory: Configure histogram metricscounter/counter_factory: Configure counter metricslabel_fn: Function returning dict of custom labelsamount_fn: Function returning amount to increment countertracer: Specify tracer instance (defaults to global tracer)func_name_as_label: Automatically adds function name to labels (default: True)
The configure_telemetry() function accepts resource_attrs={} (line 18 in __init__.py) which are merged with the service.name attribute using dictionary union operator (line 28).
- Pyroscope configured if
pyroscope_serverprovided (line 20-25) - Resource created with service.name + custom attrs (line 27-29)
- Tracing configured if
serverprovided (line 32) - Logging configured if
serverprovided (line 33) - Metrics always configured (line 35)
The library includes comprehensive integration tests in observlib/tests/test_observlib.py using pytest. The test suite covers:
- configure_telemetry() tests: Validation of service name requirements, configuration with/without OTLP server, resource attributes, Pyroscope integration, and logging setup
- @traced decorator tests:
- Basic functionality with sync and async functions
- Exception handling and error propagation
- Metrics recording (histograms and counters)
- Custom label and amount functions
- Function signature preservation
- Class methods and nested calls
- Generator functions
- Integration tests: Real provider interactions and end-to-end flows
Tests use pytest with the pytest-asyncio plugin for async test support. From the observlib/ directory:
# Run all tests
nix develop --command uv run pytest -v
# Run with coverage
nix develop --command uv run pytest --cov=observlib
# Run specific test
nix develop --command uv run pytest tests/test_observlib.py::test_traced_decorator_async_function -vTest dependencies are defined in pyproject.toml under [project.optional-dependencies]:
pytest>=7.0: Test frameworkpytest-asyncio>=0.23.0: Async test supportpytest-mock>=3.12.0: Mocking utilities
Install with: uv sync --extra test