|
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