Skip to content

Commit 6797a82

Browse files
committed
Version 1.0.0.
1 parent ed83d9c commit 6797a82

File tree

15 files changed

+320
-161
lines changed

15 files changed

+320
-161
lines changed

LICENSE

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
Files: All contained files that aren't explicitly mentioned below
2+
Library: oneagent-sdk
3+
License:
4+
15
Apache License
26
Version 2.0, January 2004
37
http://www.apache.org/licenses/
@@ -199,3 +203,34 @@
199203
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200204
See the License for the specific language governing permissions and
201205
limitations under the License.
206+
207+
===============================================================================
208+
209+
This software uses and contains code from the following 3rd party library:
210+
211+
File: src/oneagent/_impl/six.py
212+
Library: six (http://six.readthedocs.io/)
213+
Copyright notice:
214+
215+
"""Utilities for writing code that runs on Python 2 and 3"""
216+
217+
# Copyright (c) 2010-2015 Benjamin Peterson
218+
#
219+
# Permission is hereby granted, free of charge, to any person obtaining a copy
220+
# of this software and associated documentation files (the "Software"), to deal
221+
# in the Software without restriction, including without limitation the rights
222+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
223+
# copies of the Software, and to permit persons to whom the Software is
224+
# furnished to do so, subject to the following conditions:
225+
#
226+
# The above copyright notice and this permission notice shall be included in all
227+
# copies or substantial portions of the Software.
228+
#
229+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
230+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
231+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
232+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
233+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
234+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
235+
# SOFTWARE.
236+

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ global-exclude *.pyo
66
global-exclude __pycache__/*
77
include MANIFEST.in
88
include README.md
9+
include LICENSE

README.md

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
**Disclaimer: This SDK is currently still work in progress.
22
Using the OneAgent SDK for Python is COMPLETELY UNSUPPORTED at this stage!**
33

4+
> Read the latest version of this README, with working internal links, at
5+
[GitHub](https://github.com/Dynatrace/OneAgent-SDK-for-Python#readme).
6+
47
# Dynatrace OneAgent SDK for Python
58

69
This SDK enables Dynatrace customers to extend request level visibility into
@@ -26,6 +29,7 @@ SDK](https://github.com/Dynatrace/OneAgent-SDK).
2629
* [Read the manual](#read-the-manual)
2730
* [Let us help you](#let-us-help-you)
2831
- [Release notes](#release-notes)
32+
- [License](#license)
2933

3034
<!-- tocstop -->
3135

@@ -49,7 +53,6 @@ documentation](https://github.com/Dynatrace/OneAgent-SDK-for-C/blob/master/READM
4953

5054
|OneAgent SDK for Python|OneAgent SDK for C/C++|Dynatrace OneAgent|
5155
|:----------------------|:---------------------|:-----------------|
52-
|0.1 |1.1.0 |≥1.141 |
5356
|1.0 |1.1.0 |≥1.141 |
5457

5558
<a name="#using-the-oneagent-sdk-for-python-in-your-application"></a>
@@ -93,10 +96,10 @@ input('Please wait...')
9396
oneagent.shutdown()
9497
```
9598

96-
For this, follow the
97-
[https://github.com/Dynatrace/OneAgent-SDK-for-Python/blob/master/test/onesdksamplepy.py](test/onesdksamplepy.py)
98-
example (see also Quickstart section in the
99-
[documentation](https://dynatrace.github.io/OneAgent-SDK-for-Python/)).
99+
For this, follow the [provided sample
100+
application](https://github.com/Dynatrace/OneAgent-SDK-for-Python/blob/master/samples/basic-sdk-sample/basic_sdk_sample.py)
101+
(see also Quickstart section in the
102+
[documentation](https://dynatrace.github.io/OneAgent-SDK-for-Python/docs/quickstart.html)).
100103

101104

102105
<a name="api-concepts"></a>
@@ -381,9 +384,22 @@ documentation](#documenation) before you ask for help. Especially the
381384

382385
SLAs don't apply for GitHub tickets.
383386

387+
<a name="release-notes"></a>
384388
## Release notes
385389

386390
Please see the [GitHub
387391
releases page](https://github.com/Dynatrace/OneAgent-SDK-for-Python/releases),
388392
and the [PyPI release
389393
history](https://pypi.org/project/oneagent-sdk/#history).
394+
395+
<a name="license"></a>
396+
## License
397+
398+
See the LICENSE file for details. It should be included in your distribution.
399+
Otherwise, see the most recent version on
400+
[GitHub](https://github.com/Dynatrace/OneAgent-SDK-for-Python/blob/master/LICENSE).
401+
402+
Summary: This software is licensed under the terms of the Apache License Version
403+
2.0 and comes bundled with the [six library by Benjamin
404+
Peterson](http://six.readthedocs.io/), which is licensed under the terms of the
405+
MIT license.

docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Welcome to the documentation for Dynatrace OneAgent SDK for Python
33

44
If you are new to the Dynatrace OneAgent SDK for Python, please consult the
55
`README on GitHub
6-
<https://github.com/Dynatrace/OneAgent-SDK-for-Python/blob/master/README.md#readme>`_
6+
<https://github.com/Dynatrace/OneAgent-SDK-for-Python/blob/master/README.md#readme>`_.
77
It also contains installation instructions.
88

99
.. toctree::

docs/quickstart.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ Quickstart
33

44
The following example shows most features of the Python SDK:
55

6-
.. literalinclude:: ../test/onesdksamplepy.py
6+
.. literalinclude:: ../samples/basic-sdk-sample/basic_sdk_sample.py
77

8-
See the rest of the documentation for more information.
8+
See the rest of the documentation and the `README on GitHub
9+
<https://github.com/Dynatrace/OneAgent-SDK-for-Python/blob/master/README.md#readme>`_
10+
for more information.

docs/sdkref.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
Public SDK API Reference
2-
========================
1+
oneagent-sdk API Reference
2+
==========================
33

44
For a high-level overview of SDK concepts, see
55
https://github.com/Dynatrace/OneAgent-SDK.

samples/basic-sdk-sample/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Basic OneAgent SDK for Python sample
2+
3+
This example demonstrates how to use the [OneAgent SDK for
4+
Python](https://github.com/Dynatrace/OneAgent-SDK-for-Python).
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
# -*- coding: utf-8 -*-
2+
'''This example demonstrates instrumenting a (mocked) application that executes
3+
a remote call that sometimes fails and does some database operations.'''
4+
5+
from __future__ import print_function # Python 2 compatibility.
6+
7+
import threading
8+
9+
import oneagent # SDK initialization functions
10+
import oneagent.sdk as onesdk # All other SDK functions.
11+
12+
try: # Python 2 compatibility.
13+
input = raw_input #pylint:disable=redefined-builtin
14+
except NameError:
15+
pass
16+
17+
getsdk = onesdk.SDK.get # Just to make the code shorter.
18+
19+
def traced_db_operation(dbinfo, sql):
20+
print('+db', dbinfo, sql)
21+
22+
# Entering the with block automatically start the tracer.
23+
with getsdk().trace_sql_database_request(dbinfo, sql) as tracer:
24+
25+
# In real-world code, you would do the actual database operation here,
26+
# i.e. call the database's API.
27+
28+
# Set an optional "exit"-field on the tracer. Whenever there is a
29+
# setter available on a tracer (as opposed to an optional parameter to a
30+
# trace_* function), it may be called anytime between creating and
31+
# ending the tracer (i.e. also after starting it).
32+
tracer.set_round_trip_count(3)
33+
34+
print('-db', dbinfo, sql)
35+
36+
def outgoing_remote_call(success):
37+
print('+remote')
38+
39+
# We use positional arguments to specify required values and named arguments
40+
# to specify optional values.
41+
call = getsdk().trace_outgoing_remote_call(
42+
'dummyPyMethod', 'DummyPyService', 'dupypr://localhost/dummyEndpoint',
43+
onesdk.Channel(onesdk.ChannelType.IN_PROCESS, 'localhost'),
44+
protocol_name='DUMMY_PY_PROTOCOL')
45+
try:
46+
with call:
47+
48+
# Note that this property can only be accessed after starting the
49+
# tracer. See the documentation on tagging for more information.
50+
strtag = call.outgoing_dynatrace_string_tag
51+
52+
if not success:
53+
# This demonstrates how an exception leaving a tracer's
54+
# with-block will mark the tracer as failed.
55+
raise RuntimeError('remote error message')
56+
do_remote_call(strtag)
57+
except RuntimeError: # Swallow the exception raised above.
58+
pass
59+
print('-remote')
60+
61+
failed = [False]
62+
63+
def do_remote_call_thread_func(strtag):
64+
try:
65+
print('+thread')
66+
# We use positional arguments to specify required values and named
67+
# arguments to specify optional values.
68+
incall = getsdk().trace_incoming_remote_call(
69+
'dummyPyMethod', 'DummyPyService',
70+
'dupypr://localhost/dummyEndpoint',
71+
protocol_name='DUMMY_PY_PROTOCOL', str_tag=strtag)
72+
with incall:
73+
dbinfo = getsdk().create_database_info(
74+
'Northwind', onesdk.DatabaseVendor.SQLSERVER,
75+
onesdk.Channel(onesdk.ChannelType.TCP_IP, '10.0.0.42:6666'))
76+
77+
# This with-block will automatically free the database info handle
78+
# at the end. Note that the handle is used for multiple tracers. In
79+
# general, it is recommended to reuse database (and web application)
80+
# info handles as often as possible (for efficiency reasons).
81+
with dbinfo:
82+
traced_db_operation(
83+
dbinfo, "BEGIN TRAN;")
84+
traced_db_operation(
85+
dbinfo,
86+
"SELECT TOP 1 qux FROM baz ORDER BY quux;")
87+
traced_db_operation(
88+
dbinfo,
89+
"SELECT foo, bar FROM baz WHERE qux = 23")
90+
traced_db_operation(
91+
dbinfo,
92+
"UPDATE baz SET foo = foo + 1 WHERE qux = 23;")
93+
traced_db_operation(dbinfo, "COMMIT;")
94+
print('-thread')
95+
except Exception:
96+
failed[0] = True
97+
raise
98+
99+
100+
def do_remote_call(strtag):
101+
# This function simulates doing a remote call by calling a function
102+
# do_remote_call_thread_func in another thread, passing a string tag. See
103+
# the documentation on tagging for more information.
104+
105+
workerthread = threading.Thread(
106+
target=do_remote_call_thread_func,
107+
args=(strtag,))
108+
workerthread.start()
109+
110+
# Note that we need to join the thread, as all tagging assumes synchronous
111+
# calls.
112+
workerthread.join()
113+
114+
assert not failed[0]
115+
116+
def mock_incoming_web_request():
117+
sdk = getsdk()
118+
wappinfo = sdk.create_web_application_info(
119+
virtual_host='example.com', # Logical name of the host server.
120+
application_id='MyWebApplication', # Unique web application ID.
121+
context_root='/my-web-app/') # App's prefix of the path part of the URL.
122+
123+
with wappinfo:
124+
# This with-block will automatically free web application info handle
125+
# at the end. Note that the handle can be used for multiple tracers. In
126+
# general, it is recommended to reuse web application info handles as
127+
# often as possible (for efficiency reasons). For example, if you use
128+
# WSGI, the web application info could be stored as an attribute of the
129+
# application object.
130+
#
131+
# Note that different ways to specify headers, response headers and
132+
# parameter (form fields) not shown here also exist. Consult the
133+
# documentation for trace_incoming_web_request and
134+
# IncomingWebRequestTracer.
135+
wreq = sdk.trace_incoming_web_request(
136+
wappinfo,
137+
'http://example.com/my-web-app/foo?bar=baz',
138+
'GET',
139+
headers={'Host': 'example.com', 'X-foo': 'bar'},
140+
remote_address='127.0.0.1:12345')
141+
with wreq:
142+
wreq.add_parameter('my_form_field', '1234')
143+
# Process web request
144+
wreq.add_response_headers({'Content-Length': '1234'})
145+
wreq.set_status_code(200) # OK
146+
147+
148+
def main():
149+
print('+main')
150+
151+
# This gathers arguments prefixed with '--dt_' from sys.argv into the
152+
# returned list. See try_init below.
153+
sdk_options = oneagent.sdkopts_from_commandline(remove=True)
154+
155+
# If you do not call try_init() manually, the first call to
156+
# oneagent.sdk.SDK.get() will attempt to initialize the SDK with default
157+
# options, swallowing any errors, which is why manually calling try_init()
158+
# is recommended.
159+
# Passing in the sdk_options is entirely optional and usually not required
160+
# as all settings will be automatically provided by the Dynatrace OneAgent
161+
# that is installed on the host.
162+
init_result = oneagent.try_init(sdk_options)
163+
try:
164+
if init_result.error is not None:
165+
print('Error during SDK initialization:', init_result.error)
166+
167+
# While not by much, it is a bit faster to cache the result of
168+
# oneagent.sdk.SDK.get() instead of calling the function multiple times.
169+
sdk = getsdk()
170+
171+
# The agent state is one of the integers in oneagent.sdk.AgentState.
172+
print('Agent state:', sdk.agent_state)
173+
174+
# The agent version is the version of the installed OneAgent, not the
175+
# version of the SDK.
176+
print('Agent version:', sdk.agent_version_string)
177+
178+
mock_incoming_web_request()
179+
180+
# We use trace_incoming_remote_call here, because it is one of the few
181+
# calls that create a new path if none is running yet.
182+
with sdk.trace_incoming_remote_call('main', 'main', 'main'):
183+
# Simulate some remote calls
184+
outgoing_remote_call(success=True)
185+
outgoing_remote_call(success=True)
186+
outgoing_remote_call(success=False)
187+
print('-main')
188+
input('Now wait until the path appears in the UI...')
189+
finally:
190+
shutdown_error = oneagent.shutdown()
191+
if shutdown_error:
192+
print('Error shutting down SDK:', shutdown_error)
193+
194+
if __name__ == '__main__':
195+
main()

samples/basic-sdk-sample/setup.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env python3
2+
3+
import io
4+
5+
from setuptools import setup
6+
7+
with io.open('README.md', encoding='utf-8') as readmefile:
8+
long_description = readmefile.read()
9+
del readmefile
10+
11+
setup(
12+
py_modules=['basic_sdk_sample'],
13+
zip_safe=True,
14+
name='oneagent-sdk-basic-sample',
15+
version='0.0', # This sample is not separately versioned
16+
17+
install_requires=['oneagent-sdk~=1'],
18+
19+
description='OneAgent SDK for Python: Basic sample application',
20+
long_description=long_description,
21+
long_description_content_type='text/markdown',
22+
url='https://github.com/Dynatrace/OneAgent-SDK-for-Python',
23+
maintainer='Dynatrace LLC',
24+
maintainer_email='dynatrace.oneagent.sdk@dynatrace.com',
25+
license='Apache License 2.0',
26+
entry_points={
27+
'console_scripts': ['oneagent-sdk-basic-sample=basic_sdk_sample:main'],
28+
},
29+
classifiers=[
30+
'Intended Audience :: Developers',
31+
'License :: OSI Approved',
32+
'License :: OSI Approved :: Apache Software License', # 2.0
33+
'Programming Language :: Python',
34+
'Programming Language :: Python :: 2',
35+
'Programming Language :: Python :: 2.7',
36+
'Programming Language :: Python :: 3',
37+
'Programming Language :: Python :: Implementation :: CPython',
38+
'Operating System :: POSIX :: Linux',
39+
'Operating System :: Microsoft :: Windows',
40+
'Topic :: System :: Monitoring'
41+
])

setup.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[bdist_wheel]
22
# Py 2 AND 3 compatible
33
universal=1
4+
5+
[metadata]
6+
license_file = LICENSE

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ def main():
205205
classifiers=[
206206
'Development Status :: 4 - Beta',
207207
'Intended Audience :: Developers',
208+
'License :: OSI Approved',
208209
'License :: OSI Approved :: Apache Software License', # 2.0
209210
'Programming Language :: Python',
210211
'Programming Language :: Python :: 2',

0 commit comments

Comments
 (0)