|
1 | 1 | Auto-instrumentation
|
2 | 2 | ====================
|
3 | 3 |
|
4 |
| -One of the best ways to instrument Python applications is to use OpenTelemetry automatic instrumentation (auto-instrumentation). This approach is simple, easy, and doesn't require many code changes. You only need to install a few Python packages to successfully instrument your application's code. |
| 4 | +To learn about automatic instrumentation and how to run the example in this |
| 5 | +directory, see `Automatic Instrumentation`_. |
5 | 6 |
|
6 |
| -Overview |
7 |
| --------- |
8 |
| - |
9 |
| -This example demonstrates how to use auto-instrumentation in OpenTelemetry. |
10 |
| -The example is based on a previous OpenTracing example that |
11 |
| -you can find |
12 |
| -`here <https://github.com/yurishkuro/opentracing-tutorial/tree/master/python>`__. |
13 |
| - |
14 |
| -The source files for these examples are available `here <https://github.com/open-telemetry/opentelemetry-python/tree/main/docs/examples/auto-instrumentation>`__. |
15 |
| - |
16 |
| -This example uses two different scripts. The main difference between them is |
17 |
| -whether or not they're instrumented manually: |
18 |
| - |
19 |
| -1. ``server_instrumented.py`` - instrumented manually |
20 |
| -2. ``server_uninstrumented.py`` - not instrumented manually |
21 |
| - |
22 |
| -Run the first script without the automatic instrumentation agent and |
23 |
| -the second with the agent. They should both produce the same results, |
24 |
| -demonstrating that the automatic instrumentation agent does |
25 |
| -exactly the same thing as manual instrumentation. |
26 |
| - |
27 |
| -To better understand auto-instrumentation, see the relevant part of both scripts: |
28 |
| - |
29 |
| -Manually instrumented server |
30 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
31 |
| - |
32 |
| -``server_instrumented.py`` |
33 |
| - |
34 |
| -.. code:: python |
35 |
| -
|
36 |
| - @app.route("/server_request") |
37 |
| - def server_request(): |
38 |
| - with tracer.start_as_current_span( |
39 |
| - "server_request", |
40 |
| - context=extract(request.headers), |
41 |
| - kind=trace.SpanKind.SERVER, |
42 |
| - attributes=collect_request_attributes(request.environ), |
43 |
| - ): |
44 |
| - print(request.args.get("param")) |
45 |
| - return "served" |
46 |
| -
|
47 |
| -Server not instrumented manually |
48 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
49 |
| - |
50 |
| -``server_uninstrumented.py`` |
51 |
| - |
52 |
| -.. code:: python |
53 |
| -
|
54 |
| - @app.route("/server_request") |
55 |
| - def server_request(): |
56 |
| - print(request.args.get("param")) |
57 |
| - return "served" |
58 |
| -
|
59 |
| -Prepare |
60 |
| -------- |
61 |
| - |
62 |
| -Execute the following example in a separate virtual environment. |
63 |
| -Run the following commands to prepare for auto-instrumentation: |
64 |
| - |
65 |
| -.. code:: sh |
66 |
| -
|
67 |
| - $ mkdir auto_instrumentation |
68 |
| - $ virtualenv auto_instrumentation |
69 |
| - $ source auto_instrumentation/bin/activate |
70 |
| -
|
71 |
| -Install |
72 |
| -------- |
73 |
| - |
74 |
| -Run the following commands to install the appropriate packages. The |
75 |
| -``opentelemetry-distro`` package depends on a few others, like ``opentelemetry-sdk`` |
76 |
| -for custom instrumentation of your own code and ``opentelemetry-instrumentation`` which |
77 |
| -provides several commands that help automatically instrument a program. |
78 |
| - |
79 |
| -.. code:: sh |
80 |
| -
|
81 |
| - $ pip install opentelemetry-distro |
82 |
| - $ pip install opentelemetry-instrumentation-flask |
83 |
| - $ pip install flask |
84 |
| - $ pip install requests |
85 |
| -
|
86 |
| -The examples that follow send instrumentation results to the console. Learn more |
87 |
| -about installing and configuring the `OpenTelemetry Distro <../distro>`_ to send |
88 |
| -telemetry to other destinations, like an OpenTelemetry Collector. |
89 |
| - |
90 |
| -Execute |
91 |
| ---------- |
92 |
| - |
93 |
| -This section guides you through the manual process of instrumenting |
94 |
| -a server as well as the process of executing an automatically |
95 |
| -instrumented server. |
96 |
| - |
97 |
| -Execute a manually instrumented server |
98 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
99 |
| - |
100 |
| -Execute the server in two separate consoles, one to run each of the |
101 |
| -scripts that make up this example: |
102 |
| - |
103 |
| -.. code:: sh |
104 |
| -
|
105 |
| - $ source auto_instrumentation/bin/activate |
106 |
| - $ python server_instrumented.py |
107 |
| -
|
108 |
| -.. code:: sh |
109 |
| -
|
110 |
| - $ source auto_instrumentation/bin/activate |
111 |
| - $ python client.py testing |
112 |
| -
|
113 |
| -The console running ``server_instrumented.py`` will display the spans generated by instrumentation as JSON. |
114 |
| -The spans should appear similar to the following example: |
115 |
| - |
116 |
| -.. code:: sh |
117 |
| -
|
118 |
| - { |
119 |
| - "name": "server_request", |
120 |
| - "context": { |
121 |
| - "trace_id": "0xfa002aad260b5f7110db674a9ddfcd23", |
122 |
| - "span_id": "0x8b8bbaf3ca9c5131", |
123 |
| - "trace_state": "{}" |
124 |
| - }, |
125 |
| - "kind": "SpanKind.SERVER", |
126 |
| - "parent_id": null, |
127 |
| - "start_time": "2020-04-30T17:28:57.886397Z", |
128 |
| - "end_time": "2020-04-30T17:28:57.886490Z", |
129 |
| - "status": { |
130 |
| - "status_code": "OK" |
131 |
| - }, |
132 |
| - "attributes": { |
133 |
| - "http.method": "GET", |
134 |
| - "http.server_name": "127.0.0.1", |
135 |
| - "http.scheme": "http", |
136 |
| - "host.port": 8082, |
137 |
| - "http.host": "localhost:8082", |
138 |
| - "http.target": "/server_request?param=testing", |
139 |
| - "net.peer.ip": "127.0.0.1", |
140 |
| - "net.peer.port": 52872, |
141 |
| - "http.flavor": "1.1" |
142 |
| - }, |
143 |
| - "events": [], |
144 |
| - "links": [], |
145 |
| - "resource": { |
146 |
| - "telemetry.sdk.language": "python", |
147 |
| - "telemetry.sdk.name": "opentelemetry", |
148 |
| - "telemetry.sdk.version": "0.16b1" |
149 |
| - } |
150 |
| - } |
151 |
| -
|
152 |
| -Execute an automatically instrumented server |
153 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
154 |
| - |
155 |
| -Stop the execution of ``server_instrumented.py`` with ``ctrl + c`` |
156 |
| -and run the following command instead: |
157 |
| - |
158 |
| -.. code:: sh |
159 |
| -
|
160 |
| - $ opentelemetry-instrument --traces_exporter console python server_uninstrumented.py |
161 |
| -
|
162 |
| -In the console where you previously executed ``client.py``, run the following |
163 |
| -command again: |
164 |
| - |
165 |
| -.. code:: sh |
166 |
| -
|
167 |
| - $ python client.py testing |
168 |
| -
|
169 |
| -The console running ``server_uninstrumented.py`` will display the spans generated by instrumentation as JSON. |
170 |
| -The spans should appear similar to the following example: |
171 |
| - |
172 |
| -.. code:: sh |
173 |
| -
|
174 |
| - { |
175 |
| - "name": "server_request", |
176 |
| - "context": { |
177 |
| - "trace_id": "0x9f528e0b76189f539d9c21b1a7a2fc24", |
178 |
| - "span_id": "0xd79760685cd4c269", |
179 |
| - "trace_state": "{}" |
180 |
| - }, |
181 |
| - "kind": "SpanKind.SERVER", |
182 |
| - "parent_id": "0xb4fb7eee22ef78e4", |
183 |
| - "start_time": "2020-04-30T17:10:02.400604Z", |
184 |
| - "end_time": "2020-04-30T17:10:02.401858Z", |
185 |
| - "status": { |
186 |
| - "status_code": "OK" |
187 |
| - }, |
188 |
| - "attributes": { |
189 |
| - "http.method": "GET", |
190 |
| - "http.server_name": "127.0.0.1", |
191 |
| - "http.scheme": "http", |
192 |
| - "host.port": 8082, |
193 |
| - "http.host": "localhost:8082", |
194 |
| - "http.target": "/server_request?param=testing", |
195 |
| - "net.peer.ip": "127.0.0.1", |
196 |
| - "net.peer.port": 48240, |
197 |
| - "http.flavor": "1.1", |
198 |
| - "http.route": "/server_request", |
199 |
| - "http.status_text": "OK", |
200 |
| - "http.status_code": 200 |
201 |
| - }, |
202 |
| - "events": [], |
203 |
| - "links": [], |
204 |
| - "resource": { |
205 |
| - "telemetry.sdk.language": "python", |
206 |
| - "telemetry.sdk.name": "opentelemetry", |
207 |
| - "telemetry.sdk.version": "0.16b1", |
208 |
| - "service.name": "" |
209 |
| - } |
210 |
| - } |
211 |
| -
|
212 |
| -You can see that both outputs are the same because automatic instrumentation does |
213 |
| -exactly what manual instrumentation does. |
214 |
| - |
215 |
| -Instrumentation while debugging |
216 |
| -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
217 |
| - |
218 |
| -The debug mode can be enabled in the Flask app like this: |
219 |
| - |
220 |
| - |
221 |
| -.. code:: python |
222 |
| -
|
223 |
| - if __name__ == "__main__": |
224 |
| - app.run(port=8082, debug=True) |
225 |
| -
|
226 |
| -The debug mode can break instrumentation from happening because it enables a |
227 |
| -reloader. To run instrumentation while the debug mode is enabled, set the |
228 |
| -``use_reloader`` option to ``False``: |
229 |
| - |
230 |
| -.. code:: python |
231 |
| -
|
232 |
| - if __name__ == "__main__": |
233 |
| - app.run(port=8082, debug=True, use_reloader=False) |
| 7 | +.. _Automatic Instrumentation: https://opentelemetry.io/docs/instrumentation/python/automatic/ |
0 commit comments