|
1 | 1 | # -*- coding: utf-8 -*-
|
| 2 | +# |
| 3 | +# Copyright 2018 Dynatrace LLC |
| 4 | +# |
| 5 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | +# you may not use this file except in compliance with the License. |
| 7 | +# You may obtain a copy of the License at |
| 8 | +# |
| 9 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | +# |
| 11 | +# Unless required by applicable law or agreed to in writing, software |
| 12 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | +# See the License for the specific language governing permissions and |
| 15 | +# limitations under the License. |
| 16 | + |
2 | 17 | '''This example demonstrates instrumenting a (mocked) application that executes
|
3 | 18 | a remote call that sometimes fails and does some database operations.'''
|
4 | 19 |
|
|
8 | 23 |
|
9 | 24 | import oneagent # SDK initialization functions
|
10 | 25 | import oneagent.sdk as onesdk # All other SDK functions.
|
11 |
| -import logging |
12 | 26 |
|
13 | 27 | try: # Python 2 compatibility.
|
14 | 28 | input = raw_input #pylint:disable=redefined-builtin
|
15 | 29 | except NameError:
|
16 | 30 | pass
|
17 | 31 |
|
18 |
| -getsdk = onesdk.SDK.get # Just to make the code shorter. |
| 32 | +getsdk = oneagent.get_sdk # Just to make the code shorter. |
19 | 33 |
|
20 | 34 | def traced_db_operation(dbinfo, sql):
|
21 | 35 | print('+db', dbinfo, sql)
|
@@ -144,49 +158,103 @@ def mock_incoming_web_request():
|
144 | 158 | wreq.add_response_headers({'Content-Length': '1234'})
|
145 | 159 | wreq.set_status_code(200) # OK
|
146 | 160 |
|
| 161 | + # Add 3 different custom attributes. |
| 162 | + sdk.add_custom_request_attribute('custom int attribute', 42) |
| 163 | + sdk.add_custom_request_attribute('custom float attribute', 1.778) |
| 164 | + sdk.add_custom_request_attribute('custom string attribute', 'snow is falling') |
| 165 | + |
| 166 | + # This call will trigger the diagnostic callback. |
| 167 | + sdk.add_custom_request_attribute('another key', None) |
| 168 | + |
| 169 | +def _process_my_outgoing_request(_tag): |
| 170 | + pass |
| 171 | + |
| 172 | +def mock_outgoing_web_request(): |
| 173 | + sdk = getsdk() |
| 174 | + |
| 175 | + # Create tracer and and request headers. |
| 176 | + tracer = sdk.trace_outgoing_web_request('http://example.com/their-web-app/bar?foo=foz', 'GET', |
| 177 | + headers={'X-not-a-useful-header': 'python-was-here'}) |
| 178 | + |
| 179 | + with tracer: |
| 180 | + # Now get the outgoing dynatrace tag. You have to add this tag as request header to your |
| 181 | + # request if you want that the path is continued on the receiving site. Use the constant |
| 182 | + # oneagent.common.DYNATRACE_HTTP_HEADER_NAME as request header name. |
| 183 | + tag = tracer.outgoing_dynatrace_string_tag |
| 184 | + |
| 185 | + # Here you process and send your web request. |
| 186 | + _process_my_outgoing_request(tag) |
| 187 | + |
| 188 | + # As soon as the response is received, you can add the response headers to the |
| 189 | + # tracer and you shouldn't forget to set the status code, too. |
| 190 | + tracer.add_response_headers({'Content-Length': '1234'}) |
| 191 | + tracer.set_status_code(200) # OK |
| 192 | + |
| 193 | +def _diag_callback(text): |
| 194 | + print(text) |
147 | 195 |
|
148 | 196 | def main():
|
149 | 197 | print('+main')
|
150 | 198 |
|
151 |
| - oneagent.logger.setLevel(1) |
152 |
| - oneagent.logger.addHandler(logging.StreamHandler()) |
153 |
| - |
154 | 199 | # This gathers arguments prefixed with '--dt_' from sys.argv into the
|
155 |
| - # returned list. See try_init below. |
| 200 | + # returned list. See initialize below. |
156 | 201 | sdk_options = oneagent.sdkopts_from_commandline(remove=True)
|
157 | 202 |
|
158 |
| - # If you do not call try_init() manually, the first call to |
159 |
| - # oneagent.sdk.SDK.get() will attempt to initialize the SDK with default |
160 |
| - # options, swallowing any errors, which is why manually calling try_init() |
161 |
| - # is recommended. |
| 203 | + # Before using the SDK you have to initialize the OneAgent. You can call oneagent.initialize() |
| 204 | + # as often as you want, but you also have to call oneagent.shutdown() for every call to |
| 205 | + # initialize() as well. |
| 206 | + # |
162 | 207 | # Passing in the sdk_options is entirely optional and usually not required
|
163 | 208 | # as all settings will be automatically provided by the Dynatrace OneAgent
|
164 | 209 | # that is installed on the host.
|
165 |
| - init_result = oneagent.try_init(sdk_options) |
| 210 | + init_result = oneagent.initialize(sdk_options) |
166 | 211 | try:
|
167 | 212 | if init_result.error is not None:
|
168 | 213 | print('Error during SDK initialization:', init_result.error)
|
169 | 214 |
|
170 | 215 | # While not by much, it is a bit faster to cache the result of
|
171 |
| - # oneagent.sdk.SDK.get() instead of calling the function multiple times. |
| 216 | + # oneagent.get_sdk() instead of calling the function multiple times. |
172 | 217 | sdk = getsdk()
|
173 | 218 |
|
| 219 | + # Set the diagnostic callback. |
| 220 | + sdk.set_diagnostic_callback(_diag_callback) |
| 221 | + |
174 | 222 | # The agent state is one of the integers in oneagent.sdk.AgentState.
|
175 | 223 | print('Agent state:', sdk.agent_state)
|
176 | 224 |
|
177 |
| - # The agent version is the version of the installed OneAgent, not the |
178 |
| - # version of the SDK. |
| 225 | + # The instance attribute 'agent_found' indicates whether an agent could be found or not. |
| 226 | + print('Agent found:', sdk.agent_found) |
| 227 | + |
| 228 | + # If an agent was found but it is incompatible with this version of the SDK for Python |
| 229 | + # then 'agent_is_compatible' would be set to false. |
| 230 | + print('Agent is compatible:', sdk.agent_is_compatible) |
| 231 | + |
| 232 | + # The agent version is a string holding both the OneAgent version and the |
| 233 | + # OneAgent SDK for C/C++ version separated by a '/'. |
179 | 234 | print('Agent version:', sdk.agent_version_string)
|
180 | 235 |
|
181 | 236 | mock_incoming_web_request()
|
182 | 237 |
|
| 238 | + mock_outgoing_web_request() |
| 239 | + |
183 | 240 | # We use trace_incoming_remote_call here, because it is one of the few
|
184 | 241 | # calls that create a new path if none is running yet.
|
185 | 242 | with sdk.trace_incoming_remote_call('main', 'main', 'main'):
|
| 243 | + # We want to start an asynchronous execution at this time, so we create an |
| 244 | + # in-process link which we will use afterwards (or in a different thread). |
| 245 | + link = sdk.create_in_process_link() |
| 246 | + |
186 | 247 | # Simulate some remote calls
|
187 | 248 | outgoing_remote_call(success=True)
|
188 | 249 | outgoing_remote_call(success=True)
|
189 | 250 | outgoing_remote_call(success=False)
|
| 251 | + |
| 252 | + # Now the asynchronous execution starts. So we create an in-process tracer. We're using |
| 253 | + # the in-process link which we've created above. This link specifies where the traced |
| 254 | + # actions below will show up in the path. |
| 255 | + with sdk.trace_in_process_link(link): |
| 256 | + outgoing_remote_call(success=True) |
| 257 | + |
190 | 258 | print('-main')
|
191 | 259 | input('Now wait until the path appears in the UI...')
|
192 | 260 | finally:
|
|
0 commit comments