OneAgent SDK for Python: Service & transaction monitoring (open EAP)

Are you eager to begin monitoring your Python services and transactions with Dynatrace? In our recent blog posts about the Dynatrace OneAgent SDK for C/C++ and extending AI-based root cause analysis with the OneAgent SDK, we announced the future release of a language binding for Python that’s based on the OneAgent SDK. The wait is now over: the OneAgent SDK for Python (which is based on the OneAgent SDK for C/C++) has reached Early Access status and is now available on GitHub and the Python Package Index. The OneAgent SDK for Python provides you with all the features of the OneAgent SDK for C/C++ (v1.1) along with the expected simplicity of a Python library.

Dynatrace OneAgent SDK for Python

To use the OneAgent SDK for Python, you need access to the Python source code of the application you want to monitor. The SDK enables you to instrument your applications manually. The OneAgent SDK for Python currently supports the tracing of remote calls, incoming web requests, and SQL database requests. More capabilities will be added in the coming months. The OneAgent SDK supports Python 2 (version 2.7+) and Python 3 (version 3.4+) on CPython (the standard Python interpreter) on both Linux and Windows.

The best way to get started is to check out our GitHub repository. Here you’ll find all the necessary SDK documentation, including examples of all features and extensive reference documentation.

Integrating the SDK into an application

To add the OneAgent SDK for Python to an application, you need to install the oneagent-sdk package from Python Package Index in your environment. You can install the package by typing:

pip install oneagent-sdk

If you use a script, add 'oneagent-sdkoneagent-sdk==1.*,>=1.0' to the install_requires argument of your setup call.

Before you can use other SDK functions, the SDK must be initialized by calling oneagent.try_init(). Then, to ensure that all captured data is sent, you should call oneagent.shutdown() before Python terminates—for example, by calling atexit.register(oneagent.shutdown).

Instrumentation has no negative effect on your application and remains dormant on systems where Dynatrace OneAgent isn’t installed. If a compatible OneAgent version (v1.141 or higher) isn’t already installed on your system before you start the instrumented Python application, you must close the application, install OneAgent, and then restart the application.

Instrument a sample application

To showcase the OneAgent SDK for Python, let’s have a look at the example on GitHub.

You can install the example application by running pip install PATH_TO_SAMPLE_DIRECTORY. The oneagent-sdk package is automatically installed because, in this example, it’s listed in the setup_requires argument in the script. Now, run the example by running oneagent-sdk-basic-sample. You should get the following output (note that the exception is expected as the example demonstrates both successful and failed service calls):
Agent state: 0
Agent version:
[...] RuntimeError: Remote call failed on the server side.
Now wait until the path appears in the UI...

Now let’s have a look at the Smartscape topology visualization to see what’s going on. For the sample application, we see three Python services. One of the services, MyWebApplication, disconnected from the other two services (main and DummyPyService), and an MS SQL Server database, accessed from the DummyPyService.

OneAgent SDK for Python

Tracing incoming web requests

First, let’s have a look at the service MyWebApplication, as this is the simplest service. The service is implemented in the mock_incoming_web_request function in the example, simulating an incoming web request from a third-party client:

def mock_incoming_web_request():
    sdk = oneagent.sdk.SDK.get()
    wappinfo = sdk.create_web_application_info(
        virtual_host='', # Logical name of the host server.
        application_id='MyWebApplication', # Unique web application ID.
        context_root='/my-web-app/') # App's prefix of the path part of the URL.

    with wappinfo:
        wreq = sdk.trace_incoming_web_request(
            wappinfo, '', 'GET',
            headers={'Host': '', 'X-foo': 'bar'},
        with wreq:
            wreq.add_parameter('my_form_field', '1234')
            # ...Process web request...
            wreq.add_response_headers({'Content-Length': '1234'})
            wreq.set_status_code(200) # OK

Notice how a Python with block is used with the wreq tracer to notify the SDK that the request processing begins when entering the block and ends when leaving the block (the with wappinfo block is just there to free the application info object’s resources; see the full example for more information).

The service details show the version of the Python interpreter and the native SDK, as well as all other relevant information.

OneAgent SDK for Python

Tracing remoting calls

Now let’s take a look at a more complex service flow:

OneAgent SDK for Python

Here we see that the Service main was invoked once and then invoked DummyPyService three times, which made 5 requests to the Northwind database 67% of the time it was invoked (i.e., two out of three times). We can verify this by looking at the sample application’s source code: The main function, which traces the service with the same name, is invoked once and it calls outgoing_remote_call three times. Two out of three times (67%) it passes True for a success parameter, one time it passes False.

Let’s also have a look at the PurePath at the code level:

OneAgent SDK for Python
Now we see that the last call (with success=False) did indeed fail (as the red marker indicates). This is the one call out of three to DummyPyService that didn’t make any database requests.

The link nodes demonstrate an important concept, namely how the OneAgent SDK can be used to link outgoing calls from one service to incoming calls of another service. These services may use completely different technologies and run on completely different hosts; as long as they are both instrumented with Dynatrace (automatically with OneAgent or manually with the OneAgent SDK), you can follow the transactions end-to-end. This is implemented in the SDK by attaching a tag to the service call messages. In the example application, the remote call just goes to another thread (an in-process remote call). The thread target function is invoked with a strtag argument that transports the tag. The tag is retrieved from the SDK tracer object in the outgoing_remote_call function using the outgoing_dynatrace_string_tag property. See documentation on GitHub for more information.

call = getsdk().trace_outgoing_remote_call(
    'dummyPyMethod', 'DummyPyService', 'dupypr://localhost/dummyEndpoint',
    onesdk.Channel(onesdk.ChannelType.IN_PROCESS, 'localhost'),
    with call:
        strtag = call.outgoing_dynatrace_string_tag
        do_remote_call(strtag, success)
except RuntimeError: # Swallow the exception raised above.

The server-side of the remote call gets this tag passed as an argument and supplies it to the method that creates the tracer:

def do_remote_call_thread_func(strtag, success):
    incall = getsdk().trace_incoming_remote_call(
        'dummyPyMethod', 'DummyPyService',
        protocol_name='DUMMY_PY_PROTOCOL', str_tag=strtag)
    with incall:
        if not success:
            raise RuntimeError('Remote call failed on the server side.')
        # ...

The code snippet above also demonstrates another useful feature of the Python SDK: When using a with block to trace a call, any exception that leaves the block will be automatically detected. The exception details can be viewed in the PurePath:

OneAgent SDK for Python

Early Access Program

The OneAgent SDK for Python is currently available to all customers as an open EAP release. We encourage you to try it out. Feel free to use and modify the sample application, play around with it using the interactive Python prompt, or even integrate it into your non-production Python applications. We plan to release a supported beta version of the OneAgent SDK for Python later this year. In the meantime, we’re eager to hear your feedback! The best way for you to do this is via the GitHub repository issue tracker. You can also comment on our roadmap thread in AnswerHub.