Tracing with OpenTelemetry and Lightstep in Python
by Alex Boten
In "Getting Started with OpenTelemetry Alphas: Python", we scratched the surface of distributed tracing with OpenTelemetry in Python. In this article, we'll dive deeper into span exporters and learn how to get traces into Lightstep from your Python application. You can create a free-forever Lightstep account here to follow along.
In OpenTelemetry, an exporter allows us to send data to a variety of backends. The Span Exporter is the interface exporters must adhere to in order to integrate with the SDK. This interface allows the exporter to free the SDK from knowing about protocol-specific logic. The interface exposes two methods export and shutdown; here's what it looks like in Python:
class SpanExporter: """Interface for exporting spans. Interface to be implemented by services that want to export recorded in its own format. To export data this MUST be registered to the :class`..Tracer` using a `SimpleExportSpanProcessor` or a `BatchSpanProcessor`. """ def export(self, spans: typing.Sequence[Span]) -> "SpanExportResult": """Exports a batch of telemetry data. Args: spans: The list of `Span`s to be exported Returns: The result of the export """ def shutdown(self) -> None: """Shuts down the exporter. Called when the SDK is shut down. """
In the first part of our example, we'll leverage the
JaegerSpanExporter to send tracing information to Lightstep. The application we'll use is a client and server example available in the open-telemetry/opentelemetry-python repo. First, download the Jaeger agent and run it with the following parameters.
NOTE: You'll need a Lightstep access token before running the agent.
jaeger-agent \ --reporter.grpc.host-port=ingest.lightstep.com:443 \ --reporter.grpc.tls=true \ --jaeger.tags=access_token=<YOUR ACCESS TOKEN HERE>
Next, we'll configure a
JaegerSpanExporter in the server and client. Here's the code for the server:
#!/usr/bin/env python3 import os import flask import requests from opentelemetry import trace from opentelemetry.ext import http_requests from opentelemetry.ext.jaeger import JaegerSpanExporter from opentelemetry.ext.wsgi import OpenTelemetryMiddleware from opentelemetry.sdk.trace import Tracer from opentelemetry.sdk.trace.export import BatchExportSpanProcessor exporter = JaegerSpanExporter( service_name="http-server", agent_host_name="localhost", agent_port=6831, ) trace.set_preferred_tracer_implementation(lambda T: Tracer()) tracer = trace.tracer() span_processor = BatchExportSpanProcessor(exporter) tracer.add_span_processor(span_processor) http_requests.enable(tracer) app = flask.Flask(__name__) app.wsgi_app = OpenTelemetryMiddleware(app.wsgi_app) @app.route("/") def hello(): with tracer.start_as_current_span("parent"): requests.get("https://www.wikipedia.org/wiki/Rabbit") return "hello" if __name__ == "__main__": app.run(debug=True) span_processor.shutdown()
And the client:
#!/usr/bin/env python3 import os import requests from opentelemetry import trace from opentelemetry.ext import http_requests from opentelemetry.ext.jaeger import JaegerSpanExporter from opentelemetry.sdk.trace import Tracer from opentelemetry.sdk.trace.export import BatchExportSpanProcessor exporter = JaegerSpanExporter( service_name="http-client", agent_host_name="localhost", agent_port=6831, ) trace.set_preferred_tracer_implementation(lambda T: Tracer()) tracer = trace.tracer() span_processor = BatchExportSpanProcessor(exporter) tracer.add_span_processor(span_processor) http_requests.enable(tracer) response = requests.get(url="http://127.0.0.1:5000/") span_processor.shutdown()
After starting the server and sending some requests via the client, tracing information starts flowing into the Lightstep dashboard.
If using the OpenTelemetry alpha libraries is not bleeding edge enough, you'll love the next section. You can configure an experimental
LightstepSpanExporter to make shipping your tracing information to Lightstep even easier. With the exporter, you'll be able to ship directly to Lightstep's public satellites. First, let's install the library.
NOTE: The exporter is experimental, your mileage may vary.
pip install -e git+https://github.com/lightstep/opentelemetry-exporter-python
Then configure the exporter in both client and server code:
from opentelemetry.ext.lightstep import LightstepSpanExporter exporter = LightstepSpanExporter( name="exporter-demo-server", token="<YOUR ACCESS TOKEN HERE>", )
Restart the server and run the client. Tracing information is now available in the Lightstep dashboard, with one less component to install!
If you'd like to learn more about OpenTelemetry, checkout the project's website, we'd love to have you contribute to the project! If you're keen on improving the observability of your systems and want to see how Lightstep can help achieve that, check out our Sandbox.