Skip to main content

Read the latest version of this README, with working internal links, at GitHub.

Dynatrace OneAgent SDK for Python

This SDK enables Dynatrace customers to extend request level visibility into Python applications. It provides the Python implementation of the Dynatrace OneAgent SDK.

Requirements

The SDK supports Python 2 ≥ 2.7 and Python 3 ≥ 3.4. Only the official CPython (that is, the "normal" Python, i.e. the Python implementation from https://python.org) is supported and only on Linux (musl libc is currently not supported) and Windows with the x86 (including x86-64) architecture. Additionally, pip ≥ 8.1.0 (2016-03-05) is required for installation.

The Dynatrace OneAgent SDK for Python is a wrapper of the Dynatrace OneAgent SDK for C/C++ and therefore the SDK for C/C++ is required and delivered with the Python SDK. See here for its requirements, which also apply to the SDK for Python.

The version of the SDK for C/C++ that is included in each version of the SDK for Python is shown in the following table along with the required Dynatrace OneAgent version (it is the same as listed in the OneAgent SDK for C/C++'s documentation).

OneAgent SDK for Python OneAgent SDK for C/C++ Dynatrace OneAgent
1.0 1.1.0 ≥1.141
1.1 1.3.1 ≥1.151
1.2 1.4.1 ≥1.161

Using the OneAgent SDK for Python in your application

To install the latest version of the OneAgent SDK for Python, use the PyPI package oneagent-sdk:

python -m pip install --upgrade oneagent-sdk

To verify your installation, execute

python -c "import oneagent; print(oneagent.initialize())"

If the installation was successful, you should get an output ending with InitResult(status=0, error=None). Otherwise, see the Troubleshooting section.

To load the OneAgent SDK into your application, just add the following line at the top of your script:

import oneagent

Here is a quick "Hello World" that will produce a service call in Dynatrace:

import oneagent

if not oneagent.initialize():
    print('Error initializing OneAgent SDK.')

with oneagent.get_sdk().trace_incoming_remote_call('method', 'service', 'endpoint'):
    pass

print('It may take a few moments before the path appears in the UI.')
input('Please wait...')
oneagent.shutdown()

A more detailed sample application is available here. See also the Quickstart section in the API documentation.

API Concepts

Common concepts of the Dynatrace OneAgent SDK are explained in the Dynatrace OneAgent SDK repository.

Initialization and SDK objects

Before first using any other SDK functions, you need to initialize the SDK.

init_result = oneagent.initialize()
print('OneAgent SDK initialization result' + repr(init_result))
if init_result:
    print('SDK should work (but agent might be inactive).')
if not init_result:
    print('SDK will definitely not work (i.e. functions will be no-ops).')

See the API documentation for the initialize function and the InitResult class for more information.

To use the SDK, get a reference to the SDK singleton by calling the oneagent static get_sdk method. The first thing you may want to do with this object, is checking if the agent is active by comparing the value of the agent_state property to the oneagent.common.AgentState constants. You can also have a look at the extended SDK state information.

import oneagent
from oneagent.common import AgentState
# Initialize oneagent, as above

sdk = oneagent.get_sdk()
if sdk.agent_state not in (AgentState.ACTIVE, AgentState.TEMPORARILY_INACTIVE):
    print('Too bad, you will not see data from this process.')

As a development and debugging aid it is recommended to set a diagnostic callback. The callback will be used by the SDK to inform about unusual events.

Unusual events that prevent an operation from completing successfully include:

  • API usage errors
  • other unexpected events (like out of memory situations)

NOTE: Use this as a development and debugging aid only. Your application should not rely on a calling sequence or any message content being set or passed to the callback.

def _diag_callback(unicode_message):
	print(unicode_message)

sdk.set_diagnostic_callback(_diag_callback)

Tracers

To trace any kind of call you first need to create a Tracer, using one of the various trace_* methods of the SDK object. The Tracer object controls the “life cycle” of a trace: Entering a with-block with a tracer starts the trace, exiting it ends it. Exiting the with block with an exception causes the trace to be marked as failed with the exception message (if you do not want or need this behavior, tracers have explicit methods for starting, ending and attaching error information too; see the documentation).

There are different tracer types requiring different information for creation. As an example, to trace an incoming remote call, this would be the most simple way to trace it:

import oneagent

with oneagent.get_sdk().trace_incoming_remote_call('method', 'service', 'endpoint'):
    pass # Here you would do the actual work that is timed

See the section on remote calls for more information.

Some tracers also support attaching additional information before ending it.

Important: In Python 2, tracers accept both byte (“normal”) and unicode strings. Byte strings must always use the UTF-8 encoding!

Features and how to use them

The feature sets differ slightly with each language implementation. More functionality will be added over time, see Planned features for OneAgent SDK for details on upcoming features.

A more detailed specification of the features can be found in Dynatrace OneAgent SDK.

Feature Required OneAgent SDK for Python version
Trace incoming and outgoing remote calls ≥1.0.0
SQL database requests ≥1.0.0
Incoming web requests ≥1.0.0
Outgoing web requests ≥1.1.0
Custom request attributes ≥1.1.0
In-process linking ≥1.1.0
Messaging ≥1.2.0
Custom services ≥1.2.0

Remote calls

You can use the SDK to trace communication from one process to another. This will enable you to see full Service Flow, PurePath and Smartscape topology for remoting technologies that Dynatrace is not aware of.

To trace any kind of remote call you first need to create a Tracer. The Tracer object represents the endpoint that you want to call, thus you need to supply the name of the remote service and method. In addition, you need to transport a tag in your remote call from the client side to the server side if you want to trace it end to end.

On the client side, you would trace the outgoing remote call like this:

outcall = sdk.trace_outgoing_remote_call(
    'remoteMethodToCall', 'RemoteServiceName', 'rmi://Endpoint/service',
    oneagent.sdk.Channel(oneagent.sdk.ChannelType.TCP_IP, 'remoteHost:1234'),
    protocol_name='RMI/custom')
with outcall:
    # Note: You can access outgoing_dynatrace_*_tag only after the trace
    # has started!
    strtag = outcall.outgoing_dynatrace_string_tag
    do_actual_remote_call(extra_headers={'X-dynaTrace': strtag})

On the server side, you would trace it like this:

incall = sdk.trace_incoming_remote_call(
    'remoteMethodToCall', 'RemoteServiceName', 'rmi://Endpoint/service',
    protocol_name='RMI/custom',
    str_tag=my_remote_message.get_header_optional('X-dynaTrace'))
with incall:
    pass # Here you would do the actual work that is timed

See the documentation for more information:

SQL database requests

To trace database requests you need a database info object which stores the information about your database which does not change between individual requests. This will typically be created somewhere in your initialization code (after initializing the SDK):

dbinfo = sdk.create_database_info(
    'Northwind', oneagent.sdk.DatabaseVendor.SQLSERVER,
    oneagent.sdk.Channel(oneagent.sdk.ChannelType.TCP_IP, '10.0.0.42:6666'))

Then you can trace the SQL database requests:

with sdk.trace_sql_database_request(dbinfo, 'SELECT foo FROM bar;') as tracer:
    # Do actual DB request
    tracer.set_rows_returned(42) # Optional
    tracer.set_round_trip_count(3) # Optional

Note that you need to release the database info object. You can do this by calling close() on it or using it in a with block.

See the documentation for more information:

Incoming web requests

Same as with database infos, to trace incoming web requests you need a web application info object which stores the information about your web application which does not change:

wappinfo = sdk.create_web_application_info(
    virtual_host='example.com',
    application_id='MyWebApplication',
    context_root='/my-web-app/')

Then you can trace incoming web requests:

wreq = sdk.trace_incoming_web_request(
    wappinfo,
    'http://example.com/my-web-app/foo?bar=baz',
    'GET',
    headers={'Host': 'example.com', 'X-foo': 'bar'},
    remote_address='127.0.0.1:12345')

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

Note that you need to release the web application info object. You can do this by calling close() on it or using it in a with block.

Incoming web request tracers support some more features not shown here. Be sure to check out the documentation:

Outgoing web requests

To trace an outgoing web request you need to create an 'Outgoing Web Request Tracer' object. You pass the destination URL, the HTTP method and request headers as parameters.

Let's have a look at a web request example:

from urllib.request import Request

# Create your web request.
url = 'http://example.com'

req = Request(url)
req.add_header('header1', '1234')
req.add_header('header2', '5678')

After creating/setting up the request you have to create the tracer object and pass the parameters.

# Create the tracer.
tracer = sdk.trace_outgoing_web_request(url, req.get_method(), req.headers)

The next step is to start the tracer and then to retrieve the outgoing Dynatrace tag. The tag is being used to trace a transaction from end-to-end. You have to send the tag to the destination via an additional request header which is called DYNATRACE_HTTP_HEADER_NAME. Here you can find more information on tagging.

with tracer:
	# Get and set the Dynatrace tag.
	tag = tracer.outgoing_dynatrace_string_tag
 	req.add_header(DYNATRACE_HTTP_HEADER_NAME, tag)

	# Here you process and send the web request.
	response = _process_your_outgoing_request(req)

Finally, get the response headers you want to trace and the status code of the response and add them to the tracer.

        tracer.add_response_headers({'Content-Length': response.get_content_length()})
        tracer.set_status_code(response.get_status_code())

Be sure to check out the documentation:

Trace in-process asynchronous execution

You can use the SDK to trace asynchronous in-process code execution. This might be useful if the OneAgent does not support the threading framework or specific asynchronous libraries. In-process linking should be used to link other services (Database, Webrequests, ...) between thread or queueing boundaries currently not supported out-of-the-box by the OneAgent.

To link asynchronous execution, you need to create an in-process link, where the execution forks:

in_process_link = sdk.create_in_process_link()

The provided in-process link must not be serialized and can only be used inside the process in which it was created. It must be used to start tracing where the asynchronous execution takes place:

with sdk.trace_in_process_link(in_process_link):
 	# Do the asynchronous job
 	:

Custom Request Attributes

You can use the SDK to add custom request attributes to the currently traced service. Custom request attributes allow you to do easier/better filtering of your requests in Dynatrace.

Adding custom request attributes to the currently traced service call is pretty simple. Just call the add_custom_request_attribute method with your key and value (only int, float and string values are currently supported):

sdk.add_custom_request_attribute('errorCount', 42)
sdk.add_custom_request_attribute('gross weight', 2.39)
sdk.add_custom_request_attribute('famous actor', 'Benedict Cumberbatch')

Check out the documentation at:

Custom services

You can use the SDK to trace custom service methods. A custom service method is a meaningful part of your code that you want to trace but that does not fit any other tracer. An example could be the callback of a periodic timer.

with sdk.trace_custom_service('onTimer', 'CleanupTask'):
	# Do the cleanup task
	:

Check out the documentation at:

Messaging

You can use the SDK to trace messages sent or received via a messaging system. When tracing messages, we distinguish between:

  • sending a message
  • waiting for and receiving a message
  • processing a received message

Outgoing Messages

All messaging related tracers need a messaging system info object which you have to create prior to the respective messaging tracer, which is an outgoing message tracer in the example below.

msi_handle = sdk.create_messaging_system_info(
	'myMessagingSystem', 'requestQueue', MessagingDestinationType.QUEUE,
	ChannelType.TCP_IP, '10.11.12.13')

with msi_handle:
	with sdk.trace_outgoing_message(msi_handle) as tracer:
		# Get and set the Dynatrace tag.
		tag = tracer.outgoing_dynatrace_string_tag
		message_to_send.add_header_field(oneagent.sdk.DYNATRACE_MESSAGE_PROPERTY_NAME, tag)

		# Send the message.
		the_queue.send(message_to_send)

		# Optionally set message and/or correlation IDs
		tracer.set_vendor_message_id(message_to_send.get_message_id())
		tracer.set_correlation_id(message_to_send.get_correlation_id())

Incoming Messages

On the incoming side, we need to differentiate between the blocking receiving part and processing the received message. Therefore two different tracers are being used:

  • IncomingMessageReceiveTracer
  • IncomingMessageProcessTracer
msi_handle = sdk.create_messaging_system_info(
	'myMessagingSystem', 'requestQueue', MessagingDestinationType.QUEUE,
	ChannelType.TCP_IP, '10.11.12.13')

with msi_handle:
	# Create the receive tracer for incoming messages.
	with sdk.trace_incoming_message_receive(msi_handle):
		# This is a blocking call, which will return as soon as a message is available.
		Message query_message = the_queue.receive()

		# Get the Dynatrace tag from the message.
		tag = query_message.get_header_field(oneagent.sdk.DYNATRACE_MESSAGE_PROPERTY_NAME)

		# Create the tracer for processing incoming messages.
		tracer = sdk.trace_incoming_message_process(msi_handle, str_tag=tag)
		tracer.set_vendor_message_id(query_message.get_vendor_id())
		tracer.set_correlation_id(query_message.get_correlation_id())

		with tracer:
			# Now let's handle the message ...
			print('handle incoming message')

In case of non-blocking receive (e. g. using an event handler), there is no need to use an IncomingMessageReceiveTracer - just trace processing of the message by using the IncomingMessageProcessTracer:

msi_handle = sdk.create_messaging_system_info(
	'myMessagingSystem', 'requestQueue', MessagingDestinationType.QUEUE,
	ChannelType.TCP_IP, '10.11.12.13')

def on_message_received(message):
	# Get the Dynatrace tag from the message.
	tag = message.get_header_field(oneagent.sdk.DYNATRACE_MESSAGE_PROPERTY_NAME)

	# Create the tracer for processing incoming messages.
	tracer = sdk.trace_incoming_message_process(msi_handle, str_tag=tag)
	tracer.set_vendor_message_id(message.get_vendor_id())
	tracer.set_correlation_id(message.get_correlation_id())

	with tracer:
		# Now let's handle the message ...
		print('handle incoming message')

See the documentation for more information:

Troubleshooting

Installation issues

  • ValueError when installing, complaining about missing DT_PYSDK_CSDK_PATH.

    Make sure you are using pip to install a prebuilt package wheel for your system from PyPI, as described in Using the OneAgent SDK for Python in your application. Also make sure you are using an up-to date version of pip, setuptools and wheel. You can try upgrading them with python -m pip install --upgrade pip setuptools wheel (make sure to use the same python that you use to install the oneagent-sdk package). ATTENTION: If you use the system-provided pip (e.g. installed via apt-get on Ubuntu) you should instead use a pip inside a virtualenv (the same as your project), as uprading system-provided packages via pip may cause issues.

    If this does not resolve the issue, make sure you are using a supported platform, as listed in Requirements. If you are using a supported system, you can try downloading the OneAgent SDK for C/C++ in the version corresponding to your OneAgent SDK for Python as listed in the table in Requirements. Then set the DT_PYSDK_CSDK_PATH environment variable to the .so/.dll file corresponding to your platform in the lib subdirectory of the C SDK and retry the installation (e.g. in a bash shell, use export DT_PYSDK_CSDK_PATH=path/to/onesdk_shared.so). If there is no corresponding directory, your platfom is not supported. Otherwise, regardless if it works with that method or not, please report an issue as desribed in Let us help you.

Post-installation issues

To debug your OneAgent SDK for Python installation, execute the following Python code:

import oneagent
oneagent.logger.setLevel(1)
init_result = oneagent.initialize(['loglevelsdk=finest', 'loglevel=finest'])
print('InitResult=' + repr(init_result))

If you get output containing InitResult=InitResult(status=0, error=None), your installation should be fine. Otherwise, the output is helpful in determining the issue. The extended SKD state might also help to diagnose your problem.

Known gotchas:

  • ImportError or ModuleNotFoundError in line 1 that says that there is no module named oneagent.

    Make sure that the pip install or equivalent succeeded (see here). Also make sure you use the pip corresponding to your python (if in doubt, use python -m pip instead of pip for installing).

Extended SDK State

For debugging and/or diagnosing purposes you can also use the extended SDK state information.

# The agent state is one of the integers in oneagent.sdk.AgentState.
print('Agent state:', oneagent.get_sdk().agent_state)

# The instance attribute 'agent_found' indicates whether an agent could be found or not.
print('Agent found:', oneagent.get_sdk().agent_found)

# If an agent was found but it is incompatible with this version of the SDK for Python
# then 'agent_is_compatible' would be set to false.
print('Agent is compatible:', oneagent.get_sdk().agent_is_compatible)

# The agent version is a string holding both the OneAgent version and the
# OneAgent SDK for C/C++ version separated by a '/'.
print('Agent version:', oneagent.get_sdk().agent_version_string)

Repository contents

If you are viewing the GitHub repository, you will see:

  • LICENSE: License under which the whole SDK and sample applications are published.
  • src/: Actual source code of the Python OneAgent SDK.
  • docs/: Source files for the (Sphinx-based) HTML documentation. For the actual, readable documentation, see here.
  • tests/, test-util-src/: Contains tests and test support files that are useful (only) for developers wanting to contribute to the SDK itself.
  • setup.py, setup.cfg, MANIFEST.in, project.toml: Development files required for creating e.g. the PyPI package for the Python OneAgent SDK.
  • tox.ini, pylintrc: Supporting files for developing the SDK itself. See https://tox.readthedocs.io/en/latest/ and https://www.pylint.org/.

Help & Support

The Dynatrace OneAgent SDK for Python is currently in beta status. The features are fully supported by Dynatrace.

Read the manual

Let us help you

Make sure your issue is not already solved in the available documentation before you ask for help. Especially the troubleshooting section in this README may prove helpful.

Get Help

Open a GitHub issue to:

  • Report minor defects or typos.
  • Ask for improvements or changes in the SDK API.
  • Ask any questions related to the community effort.

SLAs don't apply for GitHub tickets.

Customers can open a ticket on the Dynatrace support portal to:

  • Get support from the Dynatrace technical support engineering team
  • Manage and resolve product related technical issues

SLAs apply according to the customer's support level.

Release notes

Please see the GitHub releases page, and the PyPI release history.

License

See the LICENSE file for details. It should be included in your distribution. Otherwise, see the most recent version on GitHub.

Summary: This software is licensed under the terms of the Apache License Version 2.0 and comes bundled with the six library by Benjamin Peterson, which is licensed under the terms of the MIT license.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oneagent-sdk-1.2.0.zip (77.1 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

oneagent_sdk-1.2.0-py2.py3-none-win_amd64.whl (226.5 kB view details)

Uploaded Python 2Python 3Windows x86-64

oneagent_sdk-1.2.0-py2.py3-none-win32.whl (192.5 kB view details)

Uploaded Python 2Python 3Windows x86

oneagent_sdk-1.2.0-py2.py3-none-manylinux1_x86_64.whl (108.7 kB view details)

Uploaded Python 2Python 3

oneagent_sdk-1.2.0-py2.py3-none-manylinux1_i686.whl (106.1 kB view details)

Uploaded Python 2Python 3

File details

Details for the file oneagent-sdk-1.2.0.zip.

File metadata

  • Download URL: oneagent-sdk-1.2.0.zip
  • Upload date:
  • Size: 77.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.7.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.1

File hashes

Hashes for oneagent-sdk-1.2.0.zip
Algorithm Hash digest
SHA256 7a8f775e34288f523794f34557ef9e4c2de5b08dc966171bc19a20fe40f0be5f
MD5 d92a597dccf5d7ff91288f41ccbb1543
BLAKE2b-256 85bcc29dba7577cc85d420fd1e0e5d933e51d9bc38be4b738fba3c2ce56048ba

See more details on using hashes here.

File details

Details for the file oneagent_sdk-1.2.0-py2.py3-none-win_amd64.whl.

File metadata

  • Download URL: oneagent_sdk-1.2.0-py2.py3-none-win_amd64.whl
  • Upload date:
  • Size: 226.5 kB
  • Tags: Python 2, Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.7.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.1

File hashes

Hashes for oneagent_sdk-1.2.0-py2.py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 717ed1ef8c6c38ea4c4ddc60cc552c01d35b2a8285d5268ec9a6d261d32e4eb0
MD5 fd1c4b0743120a4a59babccc2289cb5b
BLAKE2b-256 39a3e519b6d7aa3d5b0696960856037ada970e17f4e6c4936ef597d70a56b1da

See more details on using hashes here.

File details

Details for the file oneagent_sdk-1.2.0-py2.py3-none-win32.whl.

File metadata

  • Download URL: oneagent_sdk-1.2.0-py2.py3-none-win32.whl
  • Upload date:
  • Size: 192.5 kB
  • Tags: Python 2, Python 3, Windows x86
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.7.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.1

File hashes

Hashes for oneagent_sdk-1.2.0-py2.py3-none-win32.whl
Algorithm Hash digest
SHA256 468d7c6b5f51dc7d6111466dc7e4e366822ca7d6de519bc7ae4a26d7f65617bd
MD5 a44b6be449ba17acaf9492a5421ca81d
BLAKE2b-256 25b9e4494747ae391bf91bdf81a2e13a9c3b07bb7e1998de7b349dd1a3a0bee6

See more details on using hashes here.

File details

Details for the file oneagent_sdk-1.2.0-py2.py3-none-manylinux1_x86_64.whl.

File metadata

  • Download URL: oneagent_sdk-1.2.0-py2.py3-none-manylinux1_x86_64.whl
  • Upload date:
  • Size: 108.7 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.7.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.1

File hashes

Hashes for oneagent_sdk-1.2.0-py2.py3-none-manylinux1_x86_64.whl
Algorithm Hash digest
SHA256 57b5282babd82e7305cb2685854eea62bcc2339e5c89d65afc9940f6eb46331a
MD5 783a99476775339a2d60436fd4792a95
BLAKE2b-256 9b4a0f887a14cfe00c26e6e3560808249baf0b5ab9729d1f2ce46d334dc77dce

See more details on using hashes here.

File details

Details for the file oneagent_sdk-1.2.0-py2.py3-none-manylinux1_i686.whl.

File metadata

  • Download URL: oneagent_sdk-1.2.0-py2.py3-none-manylinux1_i686.whl
  • Upload date:
  • Size: 106.1 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.1 setuptools/40.7.2 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.7.1

File hashes

Hashes for oneagent_sdk-1.2.0-py2.py3-none-manylinux1_i686.whl
Algorithm Hash digest
SHA256 e1ab23214121d983ebdab22e28175113d7311647518431ee6da3d68975c2d468
MD5 fe4642a9c106a4732f9b11d03abec653
BLAKE2b-256 231c1b21d01b7ac8ac4c472a3de540bc569f8fd55f7b26d752eeb3e9061665bb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page