Skip to content

Commit a8d5e16

Browse files
committed
include feedback
1 parent b036ba3 commit a8d5e16

File tree

5 files changed

+78
-349
lines changed

5 files changed

+78
-349
lines changed

instrumentation/opentelemetry-instrumentation-asyncio/README.rst

+3-23
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ OpenTelemetry asyncio Instrumentation
99
AsyncioInstrumentor: Tracing Requests Made by the Asyncio Library
1010

1111

12-
The opentelemetry-instrumentation-asycnio package allows tracing asyncio applications.
12+
The opentelemetry-instrumentation-asyncio package allows tracing asyncio applications.
1313
The metric for coroutine, future, is generated even if there is no setting to generate a span.
1414

1515

@@ -85,28 +85,8 @@ Run instrumented application
8585
asyncio metric types
8686
----------------------
8787

88-
* `asyncio.futures.duration` (ms) - Duration of the future
89-
* `asyncio.futures.exceptions` (count) - Number of exceptions raised by the future
90-
* `asyncio.futures.cancelled` (count) - Number of futures cancelled
91-
* `asyncio.futures.created` (count) - Number of futures created
92-
* `asyncio.futures.active` (count) - Number of futures active
93-
* `asyncio.futures.finished` (count) - Number of futures finished
94-
* `asyncio.futures.timeouts` (count) - Number of futures timed out
95-
96-
* `asyncio.coroutine.duration` (ms) - Duration of the coroutine
97-
* `asyncio.coroutine.exceptions` (count) - Number of exceptions raised by the coroutine
98-
* `asyncio.coroutine.created` (count) - Number of coroutines created
99-
* `asyncio.coroutine.active` (count) - Number of coroutines active
100-
* `asyncio.coroutine.finished` (count) - Number of coroutines finished
101-
* `asyncio.coroutine.timeouts` (count) - Number of coroutines timed out
102-
* `asyncio.coroutine.cancelled` (count) - Number of coroutines cancelled
103-
104-
* `asyncio.to_thread.duration` (ms) - Duration of the to_thread
105-
* `asyncio.to_thread.exceptions` (count) - Number of exceptions raised by the to_thread
106-
* `asyncio.to_thread.created` (count) - Number of to_thread created
107-
* `asyncio.to_thread.active` (count) - Number of to_thread active
108-
* `asyncio.to_thread.finished` (count) - Number of to_thread finished
109-
88+
* `asyncio.process.duration` (seconds) - Duration of asyncio process
89+
* `asyncio.process.count` (count) - Number of asyncio process
11090

11191

11292
API

instrumentation/opentelemetry-instrumentation-asyncio/src/opentelemetry/instrumentation/asyncio/__init__.py

+49-212
Original file line numberDiff line numberDiff line change
@@ -69,27 +69,8 @@ def func():
6969
asyncio metric types
7070
---------------------
7171
72-
* asyncio.futures.duration (ms) - Duration of the future
73-
* asyncio.futures.exceptions (count) - Number of exceptions raised by the future
74-
* asyncio.futures.cancelled (count) - Number of futures cancelled
75-
* asyncio.futures.created (count) - Number of futures created
76-
* asyncio.futures.active (count) - Number of futures active
77-
* asyncio.futures.finished (count) - Number of futures finished
78-
* asyncio.futures.timeouts (count) - Number of futures timed out
79-
80-
* asyncio.coroutine.duration (ms) - Duration of the coroutine
81-
* asyncio.coroutine.exceptions (count) - Number of exceptions raised by the coroutine
82-
* asyncio.coroutine.created (count) - Number of coroutines created
83-
* asyncio.coroutine.active (count) - Number of coroutines active
84-
* asyncio.coroutine.finished (count) - Number of coroutines finished
85-
* asyncio.coroutine.timeouts (count) - Number of coroutines timed out
86-
* asyncio.coroutine.cancelled (count) - Number of coroutines cancelled
87-
88-
* asyncio.to_thread.duration (ms) - Duration of the to_thread
89-
* asyncio.to_thread.exceptions (count) - Number of exceptions raised by the to_thread
90-
* asyncio.to_thread.created (count) - Number of to_thread created
91-
* asyncio.to_thread.active (count) - Number of to_thread active
92-
* asyncio.to_thread.finished (count) - Number of to_thread finished
72+
* asyncio.process.duration (seconds) - Duration of asyncio process
73+
* asyncio.process.count (count) - Number of asyncio process
9374
9475
9576
API
@@ -103,30 +84,6 @@ def func():
10384

10485
from wrapt import wrap_function_wrapper as _wrap
10586

106-
# pylint: disable=no-name-in-module
107-
from opentelemetry.instrumentation.asyncio.metrics import (
108-
ASYNCIO_COROUTINE_ACTIVE,
109-
ASYNCIO_COROUTINE_CANCELLED,
110-
ASYNCIO_COROUTINE_CREATED,
111-
ASYNCIO_COROUTINE_DURATION,
112-
ASYNCIO_COROUTINE_EXCEPTIONS,
113-
ASYNCIO_COROUTINE_FINISHED,
114-
ASYNCIO_COROUTINE_NAME,
115-
ASYNCIO_COROUTINE_TIMEOUTS,
116-
ASYNCIO_EXCEPTIONS_NAME,
117-
ASYNCIO_FUTURES_ACTIVE,
118-
ASYNCIO_FUTURES_CANCELLED,
119-
ASYNCIO_FUTURES_CREATED,
120-
ASYNCIO_FUTURES_DURATION,
121-
ASYNCIO_FUTURES_EXCEPTIONS,
122-
ASYNCIO_FUTURES_FINISHED,
123-
ASYNCIO_FUTURES_TIMEOUTS,
124-
ASYNCIO_TO_THREAD_ACTIVE,
125-
ASYNCIO_TO_THREAD_CREATED,
126-
ASYNCIO_TO_THREAD_DURATION,
127-
ASYNCIO_TO_THREAD_EXCEPTIONS,
128-
ASYNCIO_TO_THREAD_FINISHED,
129-
)
13087
from opentelemetry.instrumentation.asyncio.package import _instruments
13188
from opentelemetry.instrumentation.asyncio.utils import (
13289
get_coros_to_trace,
@@ -161,27 +118,8 @@ class AsyncioInstrumentor(BaseInstrumentor):
161118

162119
def __init__(self):
163120
super().__init__()
164-
self.to_thread_duration_metric = None
165-
self.to_thread_exception_metric = None
166-
self.to_thread_active_metric = None
167-
self.to_thread_created_metric = None
168-
self.to_thread_finished_metric = None
169-
170-
self.coro_duration_metric = None
171-
self.coro_exception_metric = None
172-
self.coro_cancelled_metric = None
173-
self.coro_active_metric = None
174-
self.coro_created_metric = None
175-
self.coro_finished_metric = None
176-
self.coro_timeout_metric = None
177-
178-
self.future_duration_metric = None
179-
self.future_exception_metric = None
180-
self.future_cancelled_metric = None
181-
self.future_active_metric = None
182-
self.future_created_metric = None
183-
self.future_finished_metric = None
184-
self.future_timeout_metric = None
121+
self.process_duration_metric = None
122+
self.process_counts_metric = None
185123

186124
self._tracer = None
187125
self._meter = None
@@ -203,9 +141,16 @@ def _instrument(self, **kwargs):
203141
self._future_active_enabled = get_future_trace_enabled()
204142
self._to_thread_name_to_trace = get_to_thread_to_trace()
205143

206-
self.create_coro_metric()
207-
self.create_future_metric()
208-
self.create_to_thread_metric()
144+
self.process_duration_metric = self._meter.create_histogram(
145+
name="asyncio.process.duration",
146+
description="Duration of asyncio process",
147+
unit="seconds",
148+
)
149+
self.process_counts_metric = self._meter.create_up_down_counter(
150+
name="asyncio.process.count",
151+
description="Number of asyncio process",
152+
unit="1",
153+
)
209154

210155
for method in self.methods_with_coroutine:
211156
self.instrument_method_with_coroutine(method)
@@ -295,28 +240,26 @@ def wrap_taskgroup_create_task(method, instance, args, kwargs):
295240
def trace_to_thread(self, func):
296241
"""Trace a function."""
297242
start = default_timer()
298-
self.to_thread_created_metric.add(1)
299-
self.to_thread_active_metric.add(1)
300243
span = (
301244
self._tracer.start_span(
302245
f"{ASYNCIO_PREFIX}to_thread_func-" + func.__name__
303246
)
304247
if func.__name__ in self._to_thread_name_to_trace
305248
else None
306249
)
250+
attr = {"type": "to_thread", "name": func.__name__}
251+
duration_attr = attr.copy()
307252
exception = None
308253
try:
254+
attr["state"] = "finished"
309255
return func
310-
except Exception as exc:
311-
exception_attr = {ASYNCIO_EXCEPTIONS_NAME: exc.__class__.__name__}
312-
exception = exc
313-
self.to_thread_exception_metric.add(1, exception_attr)
256+
except Exception:
257+
attr["state"] = "exception"
314258
raise
315259
finally:
316260
duration = max(round((default_timer() - start) * 1000), 0)
317-
self.to_thread_duration_metric.record(duration)
318-
self.to_thread_finished_metric.add(1)
319-
self.to_thread_active_metric.add(-1)
261+
self.process_duration_metric.record(duration, duration_attr)
262+
self.process_counts_metric.add(1, attr)
320263
if span:
321264
if span.is_recording() and exception:
322265
span.set_status(Status(StatusCode.ERROR))
@@ -336,42 +279,34 @@ def trace_item(self, coro_or_future):
336279

337280
async def trace_coroutine(self, coro):
338281
start = default_timer()
339-
coro_attr = {
340-
ASYNCIO_COROUTINE_NAME: coro.__name__,
282+
attr = {
283+
"type": "coroutine",
284+
"name": coro.__name__,
341285
}
342-
self.coro_created_metric.add(1, coro_attr)
343-
self.coro_active_metric.add(1, coro_attr)
344-
286+
duration_attr = attr.copy()
345287
span = (
346288
self._tracer.start_span(f"{ASYNCIO_PREFIX}coro-" + coro.__name__)
347289
if coro.__name__ in self._coros_name_to_trace
348290
else None
349291
)
350-
351292
exception = None
352293
try:
294+
attr["state"] = "finished"
353295
return await coro
354296
# CancelledError is raised when a coroutine is cancelled
355297
# before it has a chance to run. We don't want to record
356298
# this as an error.
357299
except asyncio.CancelledError:
358-
self.coro_cancelled_metric.add(1, coro_attr)
359-
except asyncio.TimeoutError:
360-
self.coro_timeout_metric.add(1, coro_attr)
361-
raise
300+
attr["state"] = "cancelled"
362301
except Exception as exc:
363302
exception = exc
364-
coro_exception_attr = coro_attr.copy()
365-
coro_exception_attr[
366-
ASYNCIO_EXCEPTIONS_NAME
367-
] = exc.__class__.__name__
368-
self.coro_exception_metric.add(1, coro_exception_attr)
303+
state = determine_state(exception)
304+
attr["state"] = state
369305
raise
370306
finally:
371-
duration = max(round((default_timer() - start) * 1000), 0)
372-
self.coro_duration_metric.record(duration, coro_attr)
373-
self.coro_finished_metric.add(1, coro_attr)
374-
self.coro_active_metric.add(-1, coro_attr)
307+
duration = max(round(default_timer() - start), 0)
308+
self.process_duration_metric.record(duration, duration_attr)
309+
self.process_counts_metric.add(1, attr)
375310

376311
if span:
377312
if span.is_recording() and exception:
@@ -381,30 +316,23 @@ async def trace_coroutine(self, coro):
381316

382317
def trace_future(self, future):
383318
start = default_timer()
384-
self.future_created_metric.add(1)
385-
self.future_active_metric.add(1)
386319
span = (
387320
self._tracer.start_span(f"{ASYNCIO_PREFIX}future")
388321
if self._future_active_enabled
389322
else None
390323
)
391324

392325
def callback(f):
326+
duration = max(round(default_timer() - start), 0)
393327
exception = f.exception()
394-
if isinstance(exception, asyncio.CancelledError):
395-
self.future_cancelled_metric.add(1)
396-
elif isinstance(exception, asyncio.TimeoutError):
397-
self.future_timeout_metric.add(1)
398-
elif exception:
399-
exception_attr = {
400-
ASYNCIO_EXCEPTIONS_NAME: exception.__class__.__name__
401-
}
402-
self.future_exception_metric.add(1, exception_attr)
403-
404-
duration = max(round((default_timer() - start) * 1000), 0)
405-
self.future_duration_metric.record(duration)
406-
self.future_finished_metric.add(1)
407-
self.future_active_metric.add(-1)
328+
attr = {
329+
"type": "future",
330+
}
331+
duration_attr = attr.copy()
332+
state = determine_state(exception)
333+
attr["state"] = state
334+
self.process_counts_metric.add(1, attr)
335+
self.process_duration_metric.record(duration, duration_attr)
408336
if span:
409337
if span.is_recording() and exception:
410338
span.set_status(Status(StatusCode.ERROR))
@@ -414,106 +342,15 @@ def callback(f):
414342
future.add_done_callback(callback)
415343
return future
416344

417-
def create_coro_metric(self):
418-
self.coro_duration_metric = self._meter.create_histogram(
419-
name=ASYNCIO_COROUTINE_DURATION,
420-
description="Duration of asyncio coroutine",
421-
unit="ms",
422-
)
423-
self.coro_exception_metric = self._meter.create_counter(
424-
name=ASYNCIO_COROUTINE_EXCEPTIONS,
425-
description="Number of exceptions in asyncio coroutine",
426-
unit="1",
427-
)
428-
self.coro_cancelled_metric = self._meter.create_counter(
429-
name=ASYNCIO_COROUTINE_CANCELLED,
430-
description="Number of asyncio coroutine cancelled",
431-
unit="1",
432-
)
433-
self.coro_active_metric = self._meter.create_up_down_counter(
434-
name=ASYNCIO_COROUTINE_ACTIVE,
435-
description="Number of asyncio coroutine active",
436-
unit="1",
437-
)
438-
self.coro_created_metric = self._meter.create_counter(
439-
name=ASYNCIO_COROUTINE_CREATED,
440-
description="Number of asyncio coroutine created",
441-
unit="1",
442-
)
443-
self.coro_finished_metric = self._meter.create_counter(
444-
name=ASYNCIO_COROUTINE_FINISHED,
445-
description="Number of asyncio coroutine finished",
446-
unit="1",
447-
)
448-
self.coro_timeout_metric = self._meter.create_counter(
449-
name=ASYNCIO_COROUTINE_TIMEOUTS,
450-
description="Number of asyncio coroutine timeouts",
451-
unit="1",
452-
)
453-
454-
def create_future_metric(self):
455-
self.future_duration_metric = self._meter.create_histogram(
456-
name=ASYNCIO_FUTURES_DURATION,
457-
description="Duration of asyncio future",
458-
unit="ms",
459-
)
460-
self.future_exception_metric = self._meter.create_counter(
461-
name=ASYNCIO_FUTURES_EXCEPTIONS,
462-
description="Number of exceptions in asyncio future",
463-
unit="1",
464-
)
465-
self.future_cancelled_metric = self._meter.create_counter(
466-
name=ASYNCIO_FUTURES_CANCELLED,
467-
description="Number of asyncio future cancelled",
468-
unit="1",
469-
)
470-
self.future_created_metric = self._meter.create_counter(
471-
name=ASYNCIO_FUTURES_CREATED,
472-
description="Number of asyncio future created",
473-
unit="1",
474-
)
475-
self.future_active_metric = self._meter.create_up_down_counter(
476-
name=ASYNCIO_FUTURES_ACTIVE,
477-
description="Number of asyncio future active",
478-
unit="1",
479-
)
480-
self.future_finished_metric = self._meter.create_counter(
481-
name=ASYNCIO_FUTURES_FINISHED,
482-
description="Number of asyncio future finished",
483-
unit="1",
484-
)
485-
self.future_timeout_metric = self._meter.create_counter(
486-
name=ASYNCIO_FUTURES_TIMEOUTS,
487-
description="Number of asyncio future timeouts",
488-
unit="1",
489-
)
490345

491-
def create_to_thread_metric(self):
492-
self.to_thread_duration_metric = self._meter.create_histogram(
493-
name=ASYNCIO_TO_THREAD_DURATION,
494-
description="Duration of asyncio function",
495-
unit="ms",
496-
)
497-
self.to_thread_exception_metric = self._meter.create_counter(
498-
name=ASYNCIO_TO_THREAD_EXCEPTIONS,
499-
description="Number of exceptions in asyncio function",
500-
unit="1",
501-
)
502-
self.to_thread_created_metric = self._meter.create_counter(
503-
name=ASYNCIO_TO_THREAD_CREATED,
504-
description="Number of asyncio function created",
505-
unit="1",
506-
)
507-
self.to_thread_active_metric = self._meter.create_up_down_counter(
508-
name=ASYNCIO_TO_THREAD_ACTIVE,
509-
description="Number of asyncio function active",
510-
unit="1",
511-
)
512-
self.to_thread_finished_metric = self._meter.create_counter(
513-
name=ASYNCIO_TO_THREAD_FINISHED,
514-
description="Number of asyncio function finished",
515-
unit="1",
516-
)
346+
def determine_state(exception):
347+
if isinstance(exception, asyncio.CancelledError):
348+
return "cancelled"
349+
if isinstance(exception, asyncio.TimeoutError):
350+
return "timeout"
351+
if exception:
352+
return "exception"
353+
return "finished"
517354

518355

519356
def uninstrument_taskgroup_create_task():

0 commit comments

Comments
 (0)