OpenTelemetry Python
Configuration¶
Before using OTEL to send Traces to DataKit, ensure that you have configured the collector.
This page shows how to use automatic instrumentation with Python in OpenTelemetry. The examples are based on an OpenTracing example. You can download or view the source files used here from the opentelemetry-python repository.
The example uses three different scripts. The main difference lies in the method of instrumentation:
server_manual.py
: Manual instrumentation.server_automatic.py
: Automatic instrumentation.server_programmatic.py
: Programmatic instrumentation.
Programmatic instrumentation is a method that requires adding only a small amount of instrumentation code to your application. Only certain instrumentation libraries provide additional features when used programmatically, giving you more control over the instrumentation process.
Please run the first script (without using the auto-instrumentation agent) and the second script (using the agent). They should produce the same results, indicating that the auto-instrumentation agent performs the same operations as manual instrumentation.
Automatic instrumentation dynamically rewrites methods and classes at runtime using monkey-patching provided by instrumentation libraries, reducing the effort required to integrate OpenTelemetry into application code. Below, you will see the differences between manual, automatic, and programmatic instrumentation in Flask routes.
Install Dependencies¶
Before running the following demo, install the current dependencies:
pip install opentelemetry-api opentelemetry-instrumentation
Automatically Instrumented¶
- Install dependencies
pip install opentelemetry-instrumentation-flask
server_automatic.py
from flask import Flask, request
app = Flask(__name__)
@app.route("/server_request")
def server_request():
print(request.args.get("param"))
return "served"
if __name__ == "__main__":
app.run(port=8082)
- Start
opentelemetry-instrument --service_name auto-instrument-service --traces_exporter console,otlp --metrics_exporter none --exporter_otlp_endpoint http://0.0.0.0:4317 python server_automatic.py
- Access
curl http://localhost:8082/server_request?param=automatic
Manually Instrumented¶
- Install dependencies
pip install opentelemetry-exporter-otlp-proto-grpc
server_manual.py
from flask import Flask, request
from opentelemetry.instrumentation.wsgi import collect_request_attributes
from opentelemetry.propagate import extract
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
BatchSpanProcessor,
ConsoleSpanExporter,
)
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.trace import (
SpanKind,
get_tracer_provider,
set_tracer_provider,
)
app = Flask(__name__)
set_tracer_provider(TracerProvider())
tracer = get_tracer_provider().get_tracer(__name__)
# Add ConsoleSpanExporter and OTLPSpanExporter to TracerProvider
get_tracer_provider().add_span_processor(
BatchSpanProcessor(ConsoleSpanExporter())
)
get_tracer_provider().add_span_processor(
BatchSpanProcessor(OTLPSpanExporter())
)
@app.route("/server_request")
def server_request():
with tracer.start_as_current_span(
"server_request",
context=extract(request.headers),
kind=SpanKind.SERVER,
attributes=collect_request_attributes(request.environ),
):
print(request.args.get("param"))
return "served"
if __name__ == "__main__":
app.run(port=8082)
- Run
export OTEL_SERVICE_NAME="manual-instrument-service"
python server_manual.py
- Access
curl http://localhost:8082/server_request?param=manual
Programmatically Instrumented¶
You can use instrumentation libraries (e.g., opentelemetry-instrumentation-flask) individually, which may offer customization benefits. However, choosing this approach means you will not benefit from automatic instrumentation when starting the application with opentelemetry-instrument, as these two methods are mutually exclusive.
- Install dependencies
pip install opentelemetry-exporter-otlp-proto-grpc
server_programmatic.py
from flask import Flask, request
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import (
BatchSpanProcessor,
ConsoleSpanExporter,
)
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.trace import get_tracer_provider, set_tracer_provider
set_tracer_provider(TracerProvider())
get_tracer_provider().add_span_processor(
BatchSpanProcessor(ConsoleSpanExporter())
)
get_tracer_provider().add_span_processor(
BatchSpanProcessor(OTLPSpanExporter())
)
instrumentor = FlaskInstrumentor()
app = Flask(__name__)
instrumentor.instrument_app(app)
# instrumentor.instrument_app(app, excluded_urls="/server_request")
@app.route("/server_request")
def server_request():
print(request.args.get("param"))
return "served"
if __name__ == "__main__":
app.run(port=8082)
- Run
export OTEL_SERVICE_NAME="programmatic-instrument-service"
python server_programmatic.py
- Access
curl http://localhost:8082/server_request?param=programmatic