opentelemetry-instrumentation-crewai 0.37.1__py3-none-any.whl → 0.38.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opentelemetry/instrumentation/crewai/instrumentation.py +93 -16
- {opentelemetry_instrumentation_crewai-0.37.1.dist-info → opentelemetry_instrumentation_crewai-0.38.0.dist-info}/METADATA +1 -1
- {opentelemetry_instrumentation_crewai-0.37.1.dist-info → opentelemetry_instrumentation_crewai-0.38.0.dist-info}/RECORD +5 -5
- {opentelemetry_instrumentation_crewai-0.37.1.dist-info → opentelemetry_instrumentation_crewai-0.38.0.dist-info}/WHEEL +0 -0
- {opentelemetry_instrumentation_crewai-0.37.1.dist-info → opentelemetry_instrumentation_crewai-0.38.0.dist-info}/entry_points.txt +0 -0
@@ -1,10 +1,15 @@
|
|
1
|
+
import os
|
2
|
+
import time
|
1
3
|
from typing import Collection
|
4
|
+
|
2
5
|
from wrapt import wrap_function_wrapper
|
3
|
-
from opentelemetry.
|
4
|
-
from opentelemetry.trace import SpanKind, get_tracer
|
6
|
+
from opentelemetry.trace import SpanKind, get_tracer, Tracer
|
5
7
|
from opentelemetry.trace.status import Status, StatusCode
|
8
|
+
from opentelemetry.metrics import Histogram, Meter, get_meter
|
9
|
+
from opentelemetry.instrumentation.utils import unwrap
|
10
|
+
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
|
6
11
|
from opentelemetry.instrumentation.crewai.version import __version__
|
7
|
-
from opentelemetry.semconv_ai import SpanAttributes, TraceloopSpanKindValues
|
12
|
+
from opentelemetry.semconv_ai import SpanAttributes, TraceloopSpanKindValues, Meters
|
8
13
|
from .crewai_span_attributes import CrewAISpanAttributes, set_span_attribute
|
9
14
|
|
10
15
|
_instruments = ("crewai >= 0.70.0",)
|
@@ -19,31 +24,54 @@ class CrewAIInstrumentor(BaseInstrumentor):
|
|
19
24
|
tracer_provider = kwargs.get("tracer_provider")
|
20
25
|
tracer = get_tracer(__name__, __version__, tracer_provider)
|
21
26
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
27
|
+
meter_provider = kwargs.get("meter_provider")
|
28
|
+
meter = get_meter(__name__, __version__, meter_provider)
|
29
|
+
|
30
|
+
if is_metrics_enabled():
|
31
|
+
(
|
32
|
+
token_histogram,
|
33
|
+
duration_histogram,
|
34
|
+
) = _create_metrics(meter)
|
35
|
+
else:
|
36
|
+
(
|
37
|
+
token_histogram,
|
38
|
+
duration_histogram,
|
39
|
+
) = (None, None, None, None)
|
40
|
+
|
41
|
+
wrap_function_wrapper("crewai.crew", "Crew.kickoff",
|
42
|
+
wrap_kickoff(tracer, duration_histogram, token_histogram))
|
43
|
+
wrap_function_wrapper("crewai.agent", "Agent.execute_task",
|
44
|
+
wrap_agent_execute_task(tracer, duration_histogram, token_histogram))
|
45
|
+
wrap_function_wrapper("crewai.task", "Task.execute_sync",
|
46
|
+
wrap_task_execute(tracer, duration_histogram, token_histogram))
|
47
|
+
wrap_function_wrapper("crewai.llm", "LLM.call",
|
48
|
+
wrap_llm_call(tracer, duration_histogram, token_histogram))
|
26
49
|
|
27
50
|
def _uninstrument(self, **kwargs):
|
28
|
-
|
51
|
+
unwrap("crewai.crew.Crew", "kickoff")
|
52
|
+
unwrap("crewai.agent.Agent", "execute_task")
|
53
|
+
unwrap("crewai.task.Task", "execute_sync")
|
54
|
+
unwrap("crewai.llm.LLM", "call")
|
29
55
|
|
30
56
|
|
31
57
|
def with_tracer_wrapper(func):
|
32
58
|
"""Helper for providing tracer for wrapper functions."""
|
33
59
|
|
34
|
-
def _with_tracer(tracer):
|
60
|
+
def _with_tracer(tracer, duration_histogram, token_histogram):
|
35
61
|
def wrapper(wrapped, instance, args, kwargs):
|
36
|
-
return func(tracer, wrapped, instance, args, kwargs)
|
62
|
+
return func(tracer, duration_histogram, token_histogram, wrapped, instance, args, kwargs)
|
37
63
|
return wrapper
|
38
64
|
return _with_tracer
|
39
65
|
|
40
66
|
|
41
67
|
@with_tracer_wrapper
|
42
|
-
def wrap_kickoff(tracer
|
68
|
+
def wrap_kickoff(tracer: Tracer, duration_histogram: Histogram, token_histogram: Histogram,
|
69
|
+
wrapped, instance, args, kwargs):
|
43
70
|
with tracer.start_as_current_span(
|
44
71
|
"crewai.workflow",
|
45
72
|
kind=SpanKind.INTERNAL,
|
46
73
|
attributes={
|
74
|
+
SpanAttributes.LLM_SYSTEM: "crewai",
|
47
75
|
}
|
48
76
|
) as span:
|
49
77
|
try:
|
@@ -64,7 +92,7 @@ def wrap_kickoff(tracer, wrapped, instance, args, kwargs):
|
|
64
92
|
|
65
93
|
|
66
94
|
@with_tracer_wrapper
|
67
|
-
def wrap_agent_execute_task(tracer, wrapped, instance, args, kwargs):
|
95
|
+
def wrap_agent_execute_task(tracer, duration_histogram, token_histogram, wrapped, instance, args, kwargs):
|
68
96
|
agent_name = instance.role if hasattr(instance, "role") else "agent"
|
69
97
|
with tracer.start_as_current_span(
|
70
98
|
f"{agent_name}.agent",
|
@@ -76,7 +104,26 @@ def wrap_agent_execute_task(tracer, wrapped, instance, args, kwargs):
|
|
76
104
|
try:
|
77
105
|
CrewAISpanAttributes(span=span, instance=instance)
|
78
106
|
result = wrapped(*args, **kwargs)
|
107
|
+
if token_histogram:
|
108
|
+
token_histogram.record(
|
109
|
+
instance._token_process.get_summary().prompt_tokens,
|
110
|
+
attributes={
|
111
|
+
SpanAttributes.LLM_SYSTEM: "crewai",
|
112
|
+
SpanAttributes.LLM_TOKEN_TYPE: "input",
|
113
|
+
SpanAttributes.LLM_RESPONSE_MODEL: str(instance.llm.model),
|
114
|
+
}
|
115
|
+
)
|
116
|
+
token_histogram.record(
|
117
|
+
instance._token_process.get_summary().completion_tokens,
|
118
|
+
attributes={
|
119
|
+
SpanAttributes.LLM_SYSTEM: "crewai",
|
120
|
+
SpanAttributes.LLM_TOKEN_TYPE: "output",
|
121
|
+
SpanAttributes.LLM_RESPONSE_MODEL: str(instance.llm.model),
|
122
|
+
},
|
123
|
+
)
|
124
|
+
|
79
125
|
set_span_attribute(span, SpanAttributes.LLM_REQUEST_MODEL, str(instance.llm.model))
|
126
|
+
set_span_attribute(span, SpanAttributes.LLM_RESPONSE_MODEL, str(instance.llm.model))
|
80
127
|
span.set_status(Status(StatusCode.OK))
|
81
128
|
return result
|
82
129
|
except Exception as ex:
|
@@ -85,7 +132,7 @@ def wrap_agent_execute_task(tracer, wrapped, instance, args, kwargs):
|
|
85
132
|
|
86
133
|
|
87
134
|
@with_tracer_wrapper
|
88
|
-
def wrap_task_execute(tracer, wrapped, instance, args, kwargs):
|
135
|
+
def wrap_task_execute(tracer, duration_histogram, token_histogram, wrapped, instance, args, kwargs):
|
89
136
|
task_name = instance.description if hasattr(instance, "description") else "task"
|
90
137
|
|
91
138
|
with tracer.start_as_current_span(
|
@@ -107,7 +154,7 @@ def wrap_task_execute(tracer, wrapped, instance, args, kwargs):
|
|
107
154
|
|
108
155
|
|
109
156
|
@with_tracer_wrapper
|
110
|
-
def wrap_llm_call(tracer, wrapped, instance, args, kwargs):
|
157
|
+
def wrap_llm_call(tracer, duration_histogram, token_histogram, wrapped, instance, args, kwargs):
|
111
158
|
llm = instance.model if hasattr(instance, "model") else "llm"
|
112
159
|
with tracer.start_as_current_span(
|
113
160
|
f"{llm}.llm",
|
@@ -115,13 +162,43 @@ def wrap_llm_call(tracer, wrapped, instance, args, kwargs):
|
|
115
162
|
attributes={
|
116
163
|
}
|
117
164
|
) as span:
|
165
|
+
start_time = time.time()
|
118
166
|
try:
|
119
167
|
CrewAISpanAttributes(span=span, instance=instance)
|
120
168
|
result = wrapped(*args, **kwargs)
|
121
|
-
|
122
|
-
|
169
|
+
|
170
|
+
if duration_histogram:
|
171
|
+
duration = time.time() - start_time
|
172
|
+
duration_histogram.record(
|
173
|
+
duration,
|
174
|
+
attributes={
|
175
|
+
SpanAttributes.LLM_SYSTEM: "crewai",
|
176
|
+
SpanAttributes.LLM_RESPONSE_MODEL: str(instance.model)
|
177
|
+
},
|
178
|
+
)
|
179
|
+
|
123
180
|
span.set_status(Status(StatusCode.OK))
|
124
181
|
return result
|
125
182
|
except Exception as ex:
|
126
183
|
span.set_status(Status(StatusCode.ERROR, str(ex)))
|
127
184
|
raise
|
185
|
+
|
186
|
+
|
187
|
+
def is_metrics_enabled() -> bool:
|
188
|
+
return (os.getenv("TRACELOOP_METRICS_ENABLED") or "true").lower() == "true"
|
189
|
+
|
190
|
+
|
191
|
+
def _create_metrics(meter: Meter):
|
192
|
+
token_histogram = meter.create_histogram(
|
193
|
+
name=Meters.LLM_TOKEN_USAGE,
|
194
|
+
unit="token",
|
195
|
+
description="Measures number of input and output tokens used",
|
196
|
+
)
|
197
|
+
|
198
|
+
duration_histogram = meter.create_histogram(
|
199
|
+
name=Meters.LLM_OPERATION_DURATION,
|
200
|
+
unit="s",
|
201
|
+
description="GenAI operation duration",
|
202
|
+
)
|
203
|
+
|
204
|
+
return token_histogram, duration_histogram
|
@@ -1,8 +1,8 @@
|
|
1
1
|
opentelemetry/instrumentation/crewai/__init__.py,sha256=zdNyWV62d5IaueXR9clUD_c9F32MF39AIchZf66XI2c,245
|
2
2
|
opentelemetry/instrumentation/crewai/crewai_span_attributes.py,sha256=9ax6fn0IT4dqH2iaRG8VIZ0SWTkxQrMTiF7DWUdwfy0,4945
|
3
|
-
opentelemetry/instrumentation/crewai/instrumentation.py,sha256=
|
3
|
+
opentelemetry/instrumentation/crewai/instrumentation.py,sha256=AhQpPgpgtx9DKdnRDcrCKXn4AIuErdfznxfLlfs9OTc,7913
|
4
4
|
opentelemetry/instrumentation/crewai/version.py,sha256=ITH8IVCEQOekRajZpPo6sKNlMBNDRQRnzipIN0dqXoc,23
|
5
|
-
opentelemetry_instrumentation_crewai-0.
|
6
|
-
opentelemetry_instrumentation_crewai-0.
|
7
|
-
opentelemetry_instrumentation_crewai-0.
|
8
|
-
opentelemetry_instrumentation_crewai-0.
|
5
|
+
opentelemetry_instrumentation_crewai-0.38.0.dist-info/METADATA,sha256=KPAaEX4E4viDPTDRDFqdoywMGSysXXjQq2JqND3Q0Ds,2098
|
6
|
+
opentelemetry_instrumentation_crewai-0.38.0.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
7
|
+
opentelemetry_instrumentation_crewai-0.38.0.dist-info/entry_points.txt,sha256=4Zs98MjB2HIaX8fk8evs41x1J1xBNfztvPN428bf_b8,93
|
8
|
+
opentelemetry_instrumentation_crewai-0.38.0.dist-info/RECORD,,
|
File without changes
|