Send OpenTelemetry data from a Python app to Axiom
This guide explains how to send OpenTelemetry data from a Python app to Axiom using the Python OpenTelemetry SDK.
Send OpenTelemetry data from a Python app to Axiom
This guide explains how to send OpenTelemetry data from a Python app to Axiom using the Python OpenTelemetry SDK.
Prerequisites
- Install Python version 3.7 or higher.
- Create an Axiom account. To sign up for a free account, go to the Axiom app.
- Create a dataset in Axiom. This is where the Python app sends telemetry data. For more information, see Data Settings.
- Create an API key in Axiom with permissions to query and ingest data. For more information, see Access Settings.
Install required dependencies
To install the required Python dependencies, run the following code in your terminal:
pip install opentelemetry-api opentelemetry-sdk opentelemetry-instrumentation-flask opentelemetry-exporter-otlp Flask
Install dependencies with requirements file
Alternatively, if you use a requirements.txt
file in your Python project, add these lines:
opentelemetry-api
opentelemetry-sdk
opentelemetry-instrumentation-flask
opentelemetry-exporter-otlp
Flask
Then run the following code in your terminal to install dependencies:
pip install -r requirements.txt
Create an app.py file
Create an app.py
file with the following content. This file creates a basic HTTP server using Flask. It also demonstrates the usage of span links to establish relationships between spans across different traces.
# app.py
from flask import Flask
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry import trace
from random import randint
import exporter
# Creating a Flask app instance
app = Flask(__name__)
# Automatically instruments Flask app to enable tracing
FlaskInstrumentor().instrument_app(app)
# Retrieving a tracer from the custom exporter
tracer = exporter.service1_tracer
@app.route("/rolldice")
def roll_dice(parent_span=None):
# Starting a new span for the dice roll. If a parent span is provided, link to its span context.
with tracer.start_as_current_span("roll_dice_span",
links=[trace.Link(parent_span.get_span_context())] if parent_span else None) as span:
# Spans can be created with zero or more Links to other Spans that are related.
# Links allow creating connections between different traces
return str(roll())
@app.route("/roll_with_link")
def roll_with_link():
# Starting a new 'parent_span' which may later link to other spans
with tracer.start_as_current_span("parent_span") as parent_span:
# A common scenario is to correlate one or more traces with the current span.
# This can help in tracing and debugging complex interactions across different parts of the app.
result = roll_dice(parent_span)
return f"Dice roll result (with link): {result}"
def roll():
# Function to generate a random number between 1 and 6
return randint(1, 6)
if __name__ == "__main__":
# Starting the Flask server on the specified PORT and enabling debug mode
app.run(port=8080, debug=True)
Create an exporter.py file
Create an exporter.py
file with the following content. This file establishes an OpenTelemetry configuration and sets up an exporter that sends trace data to Axiom.
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.resources import Resource, SERVICE_NAME
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
# Define the service name resource for the tracer.
resource = Resource(attributes={
SERVICE_NAME: "NAME_OF_SERVICE" # Replace `NAME_OF_SERVICE` with the name of the service you want to trace.
})
# Create a TracerProvider with the defined resource for creating tracers.
provider = TracerProvider(resource=resource)
# Configure the OTLP/HTTP Span Exporter with Axiom headers and endpoint. Replace `API_TOKEN` with your Axiom API key, and replace `DATASET_NAME` with the name of the Axiom dataset where you want to send data.
otlp_exporter = OTLPSpanExporter(
endpoint="https://api.axiom.co/v1/traces",
headers={
"Authorization": "Bearer API_TOKEN",
"X-Axiom-Dataset": "DATASET_NAME"
}
)
# Create a BatchSpanProcessor with the OTLP exporter to batch and send trace spans.
processor = BatchSpanProcessor(otlp_exporter)
provider.add_span_processor(processor)
# Set the TracerProvider as the global tracer provider.
trace.set_tracer_provider(provider)
# Define a tracer for external use in different parts of the app.
service1_tracer = trace.get_tracer("service1")
In the exporter.py
file, make the following changes:
- Replace
NAME_OF_SERVICE
with the name of the service you want to trace. This is important for identifying and categorizing trace data, particularly in systems with multiple services. - Replace
API_TOKEN
with your Axiom API key. - Replace
DATASET_NAME
with the name of the Axiom dataset where you want to send data.
For more information on the libraries imported by the exporter.py
file, see the Reference below.
Run the app
Run the following code in your terminal to run the Python project:
macOS/Linux
python3 app.py
Windows
py -3 app.py
In your browser, go to http://127.0.0.1:8080/rolldice
to interact with your Python app. Each time you load the page, the app displays a random number and sends the collected traces to Axiom.
Observe the telemetry data in Axiom
In Axiom, go the Stream tab and click your dataset. This page displays the traces sent to Axiom and enables you to monitor and analyze your app’s performance and behavior.
Observing the Telemetry data in Axiom image
Dynamic OpenTelemetry traces dashboard
In Axiom, go the Dashboards tab and click OpenTelemetry Traces (python). This pre-built traces dashboard provides further insights into the performance and behavior of your app.
Dynamic OpenTelemetry Traces dashboard
Send data from an existing Python project
Manual instrumentation
Manual instrumentation in Python with OpenTelemetry involves adding code to create and manage spans around the blocks of code you want to trace. This approach allows for precise control over the trace data.
-
Import and configure a tracer at the start of your main Python file. For example, use the tracer from the
exporter.py
configuration.import exporter tracer = exporter.service1_tracer
-
Enclose the code blocks in your app that you want to trace within spans. Start and end these spans in your code.
with tracer.start_as_current_span("operation_name"):
-
Add relevant metadata and logs to your spans to enrich the trace data, providing more context for your data.
with tracer.start_as_current_span("operation_name") as span: span.set_attribute("key", "value")
Automatic instrumentation
Automatic instrumentation in Python with OpenTelemetry simplifies the process of adding telemetry data to your app. It uses pre-built libraries that automatically instrument the frameworks and libraries.
-
Install the OpenTelemetry packages designed for specific frameworks like Flask or Django.
pip install opentelemetry-instrumentation-flask
-
Configure your app to use these libraries that automatically generate spans for standard operations.
from opentelemetry.instrumentation.flask import FlaskInstrumentor # This assumes `app` is your Flask app. FlaskInstrumentor().instrument_app(app)
After you set them up, these libraries automatically trace relevant operations without additional code changes in your app.
Reference
List of OpenTelemetry trace fields
Field Category | Field Name | Description |
---|---|---|
Unique Identifiers | ||
_rowid | Unique identifier for each row in the trace data. | |
span_id | Unique identifier for the span within the trace. | |
trace_id | Unique identifier for the entire trace. | |
Timestamps | ||
_systime | System timestamp when the trace data was recorded. | |
_time | Timestamp when the actual event being traced occurred. | |
HTTP Attributes | ||
attributes.custom[“http.host”] | Host information where the HTTP request was sent. | |
attributes.custom[“http.server_name”] | Server name for the HTTP request. | |
attributes.http.flavor | HTTP protocol version used. | |
attributes.http.method | HTTP method used for the request. | |
attributes.http.route | Route accessed during the HTTP request. | |
attributes.http.scheme | Protocol scheme (HTTP/HTTPS). | |
attributes.http.status_code | HTTP response status code. | |
attributes.http.target | Specific target of the HTTP request. | |
attributes.http.user_agent | User agent string of the client. | |
Network Attributes | ||
attributes.net.host.port | Port number on the host receiving the request. | |
attributes.net.peer.port | Port number on the peer (client) side. | |
attributes.custom[“net.peer.ip”] | IP address of the peer in the network interaction. | |
Operational Details | ||
duration | Time taken for the operation. | |
kind | Type of span (for example,, server, client). | |
name | Name of the span. | |
scope | Instrumentation scope. | |
service.name | Name of the service generating the trace. |
List of imported libraries
The exporter.py
file imports the following libraries:
from opentelemetry import trace
This module creates and manages trace data in your app. It creates spans and tracers which track the execution flow and performance of your app.
from opentelemetry.sdk.trace import TracerProvider
TracerProvider
acts as a container for the configuration of your app’s tracing behavior. It allows you to define how spans are generated and processed, essentially serving as the central point for managing trace creation and propagation in your app.
from opentelemetry.sdk.trace.export import BatchSpanProcessor
BatchSpanProcessor
is responsible for batching spans before they are exported. This is an important aspect of efficient trace data management as it aggregates multiple spans into fewer network requests, reducing the overhead on your app’s performance and the tracing backend.
from opentelemetry.sdk.resources import Resource, SERVICE_NAME
The Resource
class is used to describe your app’s service attributes, such as its name, version, and environment. This contextual information is attached to the traces and helps in identifying and categorizing trace data, making it easier to filter and analyze in your monitoring setup.
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
The OTLPSpanExporter
is responsible for sending your app’s trace data to a backend that supports the OTLP such as Axiom. It formats the trace data according to the OTLP standards and transmits it over HTTP, ensuring compatibility and standardization in how telemetry data is sent across different systems and services.
Was this page helpful?