OpenTelemetry Python
Configuration¶
Before sending Trace to DataKit using OTEL, please ensure that you have configured the collector.
This page demonstrates how to use Python auto-instrumentation in OpenTelemetry. The example is based on an OpenTracing example. You can download or view the source files used in this page from the opentelemetry-python repository.
The example uses three different scripts. Their main difference lies in the way they are instrumented:
server_manual.py: Manual instrumentation.server_automatic.py: Automatic instrumentation.server_programmatic.py: Programmatic instrumentation.
Programmatic instrumentation is a method that requires adding only minimal instrumentation code to your application. Only certain instrumentation libraries provide additional functionality when used programmatically, giving you greater control over the instrumentation process.
Please run the first script (without the automatic instrumentation agent) and the second script (with the agent) separately. They should produce the same results, indicating that the automatic instrumentation agent performs the same operations as manual instrumentation.
Automatic instrumentation reduces the effort required to integrate OpenTelemetry into application code by dynamically rewriting methods and classes at runtime through monkey-patching. Below, you will see the differences between manual, automatic, and programmatic instrumentation within Flask routes.
Install Dependencies¶
Before running the following demo, install the current dependencies first:
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 individually (e.g., opentelemetry-instrumentation-flask), which may offer advantages in terms of customization options. However, choosing this approach means you give up the convenience of automatic instrumentation via opentelemetry-instrument when starting your application, as the two approaches 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