Python OpenTracing (deprecated)
OpenTracing is deprecated, and Instana Python 2.5.3 is the latest version that supports OpenTracing.
For information about how to install this version, see Installation of the Instana Python package with OpenTracing support.
OpenTracing provides "Vendor-neutral APIs and instrumentation for distributed tracing". If you're not familiar with OpenTracing, see the OpenTracing portal for more details.
Existing applications that utilize the OpenTracing API or those who wish to add support can easily integrate with this Python package.
When you use this package, the OpenTracing Tracer (opentracing.tracer
) is automatically set to the InstanaTracer
.
For best results when utilizing OpenTracing, also take note of our best practices outlined in this OpenTracing page.
Installing the Instana Python package with OpenTracing support
You can manually install the Instana Python package for different Python versions.
For runtimes with Python 3.8 and later
To manually install the Instana Python package into a virtualenv, pipenv, or container, run the following command:
pip install git+https://github.com/instana/python-sensor@v2.5.3
For runtimes with Python 3.7
To manually install the Instana Python package into a virtualenv, pipenv, or container, run the following command:
pip install git+https://github.com/instana/python-sensor@v2.4.0
Example
import opentracing
with opentracing.tracer.start_active_span('asteroid 💫') as pscope:
pscope.span.set_tag(ext.COMPONENT, "Python simple example app")
pscope.span.set_tag(ext.SPAN_KIND, ext.SPAN_KIND_RPC_SERVER)
pscope.span.set_tag(ext.PEER_HOSTNAME, "localhost")
pscope.span.set_tag(ext.HTTP_URL, "/python/simple/one")
pscope.span.set_tag(ext.HTTP_METHOD, "GET")
pscope.span.set_tag(ext.HTTP_STATUS_CODE, 200)
pscope.span.log_kv({"foo": "bar"})
# ... work ...
with opentracing.tracer.start_active_span('spacedust 🌚', child_of=pscope.span) as cscope:
cscope.span.set_tag(ext.SPAN_KIND, ext.SPAN_KIND_RPC_CLIENT)
cscope.span.set_tag(ext.PEER_HOSTNAME, "localhost")
cscope.span.set_tag(ext.HTTP_URL, "/python/simple/two")
cscope.span.set_tag(ext.HTTP_METHOD, "POST")
cscope.span.set_tag(ext.HTTP_STATUS_CODE, 204)
cscope.span.set_baggage_item("someBaggage", "someValue")
# ... work ...
Instana Python Tracing SDK with OpenTracing support
The Instana Python module provides an API to trace any arbitrary part of your application.
You can instrument a section of code for tracing with an API as follows:
from instana.singletons import tracer
try:
span = tracer.start_span("mywork")
# The code to be instrumented
id = user.find_by_name('john.smith')
span.set_tag('user_id', id)
except Exception as e:
span.log_exception(e)
finally:
span.finish()
Alternatively, you can use the context manager with the with-as
statement, which automatically captures and logs any exceptions that are raised, as follows:
from instana.singletons import tracer
with tracer.start_active_span("mywork") as scope:
# The code to be instrumented
id = user.find_by_name('john.smith')
scope.span.set_tag('user_id', id)
Asynchronous tracing
Some operations that you want to trace might be asynchronous, which means that they return immediately but still continue to work separately from the main sequence of instructions. To trace these operations, for example, with the asyncio library,
you can use the async_tracer
related tracing methods as follows:
import asyncio
from instana.singletons import tracer, async_tracer
async def do_work(parent_span):
with async_tracer.start_active_span('launch_async_work', child_of=parent_span):
print('Work stared')
await asyncio.sleep(1)
print('Work finished!')
with tracer.start_active_span('launch_uvloop') as sync_scope:
asyncio.run(do_work(sync_scope.span))
Tracing spans in forked processes
If you want to trace spans in a forked process, add a time period after span.finish()
. For example:
def forked_process(num):
print(f'in forked process {num}')
try:
span = tracer.start_span(f"forked process {num}")
print(f'sleep 10 for forked process {num}')
time.sleep(10)
except Exception as e:
span.log_exception(e)
finally:
span.finish()
logger.warning(f'sleep 2 for forked process {num}')
time.sleep(2) ## < -- with a sleep after span.finish(), the span can be collected
Carrying context into new threads
Tracing is local to a thread. If you create a new thread, the context must be carried to that new thread and then picked up. You can instrument the code to carry context in to new threads as follows:
from threading import Thread
def child_thread_function(parent_span):
with tracer.start_active_span('child_thread_span', child_of=parent_span) as child_scope:
print('Thread offloaded work goes here')
with tracer.start_active_span('parent_thread_span') as parent_scope:
thread = Thread(target = child_thread_function, args = (parent_scope.span, ))
thread.start()
thread.join()
Tracing jobs scheduled to run later
You can instrument jobs that are queued to run later as follows:
# Python 3.8
import asyncio
import datetime
import uvloop
import aiohttp
from instana.singletons import tracer, async_tracer
uvloop.install()
async def launch_async_calls(parent_span):
with async_tracer.start_active_span('launch_async_calls', child_of=parent_span):
async with aiohttp.ClientSession() as session:
async with session.get('https://wikipedia.org') as resp:
print(resp.status)
print(await resp.text())
async def run_at(dt, coro):
await asyncio.sleep((dt - datetime.datetime.now()).total_seconds())
return await coro
with tracer.start_active_span('launch_uvloop') as sync_scope:
sync_scope.span.set_tag('span.kind', 'entry')
asyncio.run(
run_at(datetime.datetime.now() + datetime.timedelta(seconds=5),
launch_async_calls(sync_scope.span)))