monocle-apptrace 0.3.1b1__py3-none-any.whl → 0.4.0b2__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.
Potentially problematic release.
This version of monocle-apptrace might be problematic. Click here for more details.
- monocle_apptrace/exporters/aws/s3_exporter.py +3 -1
- monocle_apptrace/exporters/azure/blob_exporter.py +2 -2
- monocle_apptrace/exporters/base_exporter.py +10 -4
- monocle_apptrace/exporters/file_exporter.py +19 -4
- monocle_apptrace/exporters/monocle_exporters.py +8 -5
- monocle_apptrace/exporters/okahu/okahu_exporter.py +5 -2
- monocle_apptrace/instrumentation/common/__init__.py +1 -1
- monocle_apptrace/instrumentation/common/constants.py +12 -5
- monocle_apptrace/instrumentation/common/instrumentor.py +44 -22
- monocle_apptrace/instrumentation/common/span_handler.py +100 -50
- monocle_apptrace/instrumentation/common/tracing.md +68 -0
- monocle_apptrace/instrumentation/common/utils.py +101 -63
- monocle_apptrace/instrumentation/common/wrapper.py +223 -48
- monocle_apptrace/instrumentation/common/wrapper_method.py +15 -7
- monocle_apptrace/instrumentation/metamodel/aiohttp/__init__.py +0 -0
- monocle_apptrace/instrumentation/metamodel/aiohttp/_helper.py +66 -0
- monocle_apptrace/instrumentation/metamodel/aiohttp/entities/http.py +51 -0
- monocle_apptrace/instrumentation/metamodel/aiohttp/methods.py +13 -0
- monocle_apptrace/instrumentation/metamodel/anthropic/methods.py +4 -2
- monocle_apptrace/instrumentation/metamodel/flask/_helper.py +50 -3
- monocle_apptrace/instrumentation/metamodel/flask/entities/http.py +48 -0
- monocle_apptrace/instrumentation/metamodel/flask/methods.py +10 -1
- monocle_apptrace/instrumentation/metamodel/haystack/_helper.py +17 -4
- monocle_apptrace/instrumentation/metamodel/haystack/entities/inference.py +5 -2
- monocle_apptrace/instrumentation/metamodel/haystack/methods.py +8 -4
- monocle_apptrace/instrumentation/metamodel/langchain/_helper.py +12 -4
- monocle_apptrace/instrumentation/metamodel/langchain/entities/inference.py +1 -1
- monocle_apptrace/instrumentation/metamodel/langchain/methods.py +6 -14
- monocle_apptrace/instrumentation/metamodel/llamaindex/_helper.py +13 -9
- monocle_apptrace/instrumentation/metamodel/llamaindex/entities/inference.py +1 -1
- monocle_apptrace/instrumentation/metamodel/llamaindex/methods.py +16 -15
- monocle_apptrace/instrumentation/metamodel/openai/_helper.py +10 -2
- monocle_apptrace/instrumentation/metamodel/openai/entities/inference.py +174 -26
- monocle_apptrace/instrumentation/metamodel/openai/methods.py +6 -8
- monocle_apptrace/instrumentation/metamodel/requests/_helper.py +31 -0
- monocle_apptrace/instrumentation/metamodel/requests/entities/http.py +51 -0
- monocle_apptrace/instrumentation/metamodel/requests/methods.py +2 -1
- monocle_apptrace/instrumentation/metamodel/teamsai/_helper.py +55 -5
- monocle_apptrace/instrumentation/metamodel/teamsai/entities/inference/actionplanner_output_processor.py +13 -33
- monocle_apptrace/instrumentation/metamodel/teamsai/entities/inference/teamsai_output_processor.py +24 -20
- monocle_apptrace/instrumentation/metamodel/teamsai/methods.py +42 -8
- {monocle_apptrace-0.3.1b1.dist-info → monocle_apptrace-0.4.0b2.dist-info}/METADATA +2 -1
- {monocle_apptrace-0.3.1b1.dist-info → monocle_apptrace-0.4.0b2.dist-info}/RECORD +46 -39
- {monocle_apptrace-0.3.1b1.dist-info → monocle_apptrace-0.4.0b2.dist-info}/WHEEL +0 -0
- {monocle_apptrace-0.3.1b1.dist-info → monocle_apptrace-0.4.0b2.dist-info}/licenses/LICENSE +0 -0
- {monocle_apptrace-0.3.1b1.dist-info → monocle_apptrace-0.4.0b2.dist-info}/licenses/NOTICE +0 -0
|
@@ -6,76 +6,204 @@ from opentelemetry.context import set_value, attach, detach, get_value
|
|
|
6
6
|
from monocle_apptrace.instrumentation.common.span_handler import SpanHandler
|
|
7
7
|
from monocle_apptrace.instrumentation.common.utils import (
|
|
8
8
|
get_fully_qualified_class_name,
|
|
9
|
+
set_scopes,
|
|
9
10
|
with_tracer_wrapper,
|
|
10
11
|
set_scope,
|
|
11
|
-
remove_scope
|
|
12
|
-
async_wrapper
|
|
12
|
+
remove_scope
|
|
13
13
|
)
|
|
14
|
-
from monocle_apptrace.instrumentation.common.constants import WORKFLOW_TYPE_KEY
|
|
14
|
+
from monocle_apptrace.instrumentation.common.constants import WORKFLOW_TYPE_KEY, ADD_NEW_WORKFLOW
|
|
15
15
|
logger = logging.getLogger(__name__)
|
|
16
16
|
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
def get_auto_close_span(to_wrap, kwargs):
|
|
18
|
+
try:
|
|
19
|
+
if to_wrap.get("output_processor") and to_wrap.get("output_processor").get("is_auto_close"):
|
|
20
|
+
return to_wrap.get("output_processor").get("is_auto_close")(kwargs)
|
|
21
|
+
return True
|
|
22
|
+
except Exception as e:
|
|
23
|
+
logger.warning("Warning: Error occurred in get_auto_close_span: %s", str(e))
|
|
24
|
+
return True
|
|
25
|
+
|
|
26
|
+
def pre_process_span(name, tracer, handler, add_workflow_span, to_wrap, wrapped, instance, args, kwargs, span, source_path):
|
|
27
|
+
SpanHandler.set_default_monocle_attributes(span, source_path)
|
|
28
|
+
if SpanHandler.is_root_span(span) or add_workflow_span:
|
|
29
|
+
# This is a direct API call of a non-framework type
|
|
30
|
+
SpanHandler.set_workflow_properties(span, to_wrap)
|
|
31
|
+
else:
|
|
32
|
+
SpanHandler.set_non_workflow_properties(span)
|
|
33
|
+
try:
|
|
34
|
+
handler.pre_task_processing(to_wrap, wrapped, instance, args, kwargs, span)
|
|
35
|
+
except Exception as e:
|
|
36
|
+
logger.info(f"Warning: Error occurred in pre_task_processing: {e}")
|
|
37
|
+
|
|
38
|
+
def post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, return_value, span, ex = None):
|
|
39
|
+
if not (SpanHandler.is_root_span(span) or get_value(ADD_NEW_WORKFLOW) == True):
|
|
40
|
+
try:
|
|
41
|
+
handler.hydrate_span(to_wrap, wrapped, instance, args, kwargs, return_value, span, ex)
|
|
42
|
+
except Exception as e:
|
|
43
|
+
logger.info(f"Warning: Error occurred in hydrate_span: {e}")
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
handler.post_task_processing(to_wrap, wrapped, instance, args, kwargs, return_value, span)
|
|
47
|
+
except Exception as e:
|
|
48
|
+
logger.info(f"Warning: Error occurred in post_task_processing: {e}")
|
|
21
49
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
elif to_wrap.get("span_name"):
|
|
50
|
+
def get_span_name(to_wrap, instance):
|
|
51
|
+
if to_wrap.get("span_name"):
|
|
25
52
|
name = to_wrap.get("span_name")
|
|
26
53
|
else:
|
|
27
54
|
name = get_fully_qualified_class_name(instance)
|
|
55
|
+
return name
|
|
28
56
|
|
|
57
|
+
def monocle_wrapper_span_processor(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, source_path, add_workflow_span, args, kwargs):
|
|
58
|
+
# Main span processing logic
|
|
59
|
+
name = get_span_name(to_wrap, instance)
|
|
29
60
|
return_value = None
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
61
|
+
span_status = None
|
|
62
|
+
if(get_auto_close_span(to_wrap, kwargs)):
|
|
63
|
+
with tracer.start_as_current_span(name) as span:
|
|
64
|
+
pre_process_span(name, tracer, handler, add_workflow_span, to_wrap, wrapped, instance, args, kwargs, span, source_path)
|
|
65
|
+
|
|
66
|
+
if SpanHandler.is_root_span(span) or add_workflow_span:
|
|
67
|
+
# Recursive call for the actual span
|
|
68
|
+
return_value, span_status = monocle_wrapper_span_processor(tracer, handler, to_wrap, wrapped, instance, source_path, False, args, kwargs)
|
|
69
|
+
span.set_status(span_status)
|
|
39
70
|
else:
|
|
71
|
+
ex:Exception = None
|
|
72
|
+
try:
|
|
73
|
+
with SpanHandler.workflow_type(to_wrap, span):
|
|
74
|
+
return_value = wrapped(*args, **kwargs)
|
|
75
|
+
except Exception as e:
|
|
76
|
+
ex = e
|
|
77
|
+
raise
|
|
78
|
+
finally:
|
|
79
|
+
post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, return_value, span, ex)
|
|
80
|
+
span_status = span.status
|
|
81
|
+
else:
|
|
82
|
+
span = tracer.start_span(name)
|
|
83
|
+
|
|
84
|
+
pre_process_span(name, tracer, handler, add_workflow_span, to_wrap, wrapped, instance, args, kwargs, span, source_path)
|
|
85
|
+
|
|
86
|
+
def post_process_span_internal(ret_val):
|
|
87
|
+
nonlocal handler, to_wrap, wrapped, instance, args, kwargs, span
|
|
88
|
+
post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, ret_val, span)
|
|
89
|
+
span.end()
|
|
90
|
+
|
|
91
|
+
try:
|
|
92
|
+
with SpanHandler.workflow_type(to_wrap, span):
|
|
40
93
|
return_value = wrapped(*args, **kwargs)
|
|
94
|
+
finally:
|
|
95
|
+
if to_wrap.get("output_processor") and to_wrap.get("output_processor").get("response_processor"):
|
|
96
|
+
# Process the stream
|
|
97
|
+
to_wrap.get("output_processor").get("response_processor")(to_wrap, return_value, post_process_span_internal)
|
|
98
|
+
else:
|
|
99
|
+
span.end()
|
|
100
|
+
span_status = span.status
|
|
101
|
+
return return_value, span_status
|
|
102
|
+
|
|
103
|
+
def monocle_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, source_path, args, kwargs):
|
|
104
|
+
return_value = None
|
|
105
|
+
token = None
|
|
106
|
+
try:
|
|
107
|
+
try:
|
|
108
|
+
handler.pre_tracing(to_wrap, wrapped, instance, args, kwargs)
|
|
109
|
+
except Exception as e:
|
|
110
|
+
logger.info(f"Warning: Error occurred in pre_tracing: {e}")
|
|
111
|
+
if to_wrap.get('skip_span', False) or handler.skip_span(to_wrap, wrapped, instance, args, kwargs):
|
|
112
|
+
return_value = wrapped(*args, **kwargs)
|
|
41
113
|
else:
|
|
42
|
-
|
|
114
|
+
add_workflow_span = get_value(ADD_NEW_WORKFLOW) == True
|
|
115
|
+
token = attach(set_value(ADD_NEW_WORKFLOW, False))
|
|
116
|
+
try:
|
|
117
|
+
return_value, span_status = monocle_wrapper_span_processor(tracer, handler, to_wrap, wrapped, instance, source_path, add_workflow_span, args, kwargs)
|
|
118
|
+
finally:
|
|
119
|
+
detach(token)
|
|
43
120
|
return return_value
|
|
44
121
|
finally:
|
|
45
|
-
|
|
46
|
-
|
|
122
|
+
try:
|
|
123
|
+
handler.post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value)
|
|
124
|
+
except Exception as e:
|
|
125
|
+
logger.info(f"Warning: Error occurred in post_tracing: {e}")
|
|
126
|
+
|
|
127
|
+
async def amonocle_wrapper_span_processor(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, source_path, add_workflow_span, args, kwargs):
|
|
128
|
+
# Main span processing logic
|
|
129
|
+
name = get_span_name(to_wrap, instance)
|
|
130
|
+
return_value = None
|
|
131
|
+
span_status = None
|
|
132
|
+
if(get_auto_close_span(to_wrap, kwargs)):
|
|
133
|
+
with tracer.start_as_current_span(name) as span:
|
|
134
|
+
pre_process_span(name, tracer, handler, add_workflow_span, to_wrap, wrapped, instance, args, kwargs, span, source_path)
|
|
135
|
+
|
|
136
|
+
if SpanHandler.is_root_span(span) or add_workflow_span:
|
|
137
|
+
# Recursive call for the actual span
|
|
138
|
+
return_value, span_status = await amonocle_wrapper_span_processor(tracer, handler, to_wrap, wrapped, instance, source_path, False, args, kwargs)
|
|
139
|
+
span.set_status(span_status)
|
|
140
|
+
else:
|
|
141
|
+
ex:Exception = None
|
|
142
|
+
try:
|
|
143
|
+
with SpanHandler.workflow_type(to_wrap, span):
|
|
144
|
+
return_value = await wrapped(*args, **kwargs)
|
|
145
|
+
except Exception as e:
|
|
146
|
+
ex = e
|
|
147
|
+
raise
|
|
148
|
+
finally:
|
|
149
|
+
post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, return_value, span, ex)
|
|
150
|
+
span_status = span.status
|
|
151
|
+
else:
|
|
152
|
+
span = tracer.start_span(name)
|
|
153
|
+
|
|
154
|
+
pre_process_span(name, tracer, handler, add_workflow_span, to_wrap, wrapped, instance, args, kwargs, span, source_path)
|
|
155
|
+
|
|
156
|
+
def post_process_span_internal(ret_val):
|
|
157
|
+
nonlocal handler, to_wrap, wrapped, instance, args, kwargs, span
|
|
158
|
+
post_process_span(handler, to_wrap, wrapped, instance, args, kwargs, ret_val, span)
|
|
159
|
+
span.end()
|
|
160
|
+
|
|
161
|
+
try:
|
|
162
|
+
with SpanHandler.workflow_type(to_wrap, span):
|
|
163
|
+
return_value = await wrapped(*args, **kwargs)
|
|
164
|
+
finally:
|
|
165
|
+
if to_wrap.get("output_processor") and to_wrap.get("output_processor").get("response_processor"):
|
|
166
|
+
# Process the stream
|
|
167
|
+
to_wrap.get("output_processor").get("response_processor")(to_wrap, return_value, post_process_span_internal)
|
|
168
|
+
else:
|
|
169
|
+
span.end()
|
|
170
|
+
span_status = span.status
|
|
171
|
+
return return_value, span.status
|
|
47
172
|
|
|
48
|
-
def
|
|
49
|
-
# For singleton spans, eg OpenAI inference generate a workflow span to format the workflow specific attributes
|
|
173
|
+
async def amonocle_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, source_path, args, kwargs):
|
|
50
174
|
return_value = None
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return_value =
|
|
175
|
+
token = None
|
|
176
|
+
try:
|
|
177
|
+
try:
|
|
178
|
+
handler.pre_tracing(to_wrap, wrapped, instance, args, kwargs)
|
|
179
|
+
except Exception as e:
|
|
180
|
+
logger.info(f"Warning: Error occurred in pre_tracing: {e}")
|
|
181
|
+
if to_wrap.get('skip_span', False) or handler.skip_span(to_wrap, wrapped, instance, args, kwargs):
|
|
182
|
+
return_value = await wrapped(*args, **kwargs)
|
|
59
183
|
else:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
184
|
+
add_workflow_span = get_value(ADD_NEW_WORKFLOW) == True
|
|
185
|
+
token = attach(set_value(ADD_NEW_WORKFLOW, False))
|
|
186
|
+
try:
|
|
187
|
+
return_value, span_status = await amonocle_wrapper_span_processor(tracer, handler, to_wrap, wrapped, instance, source_path, add_workflow_span, args, kwargs)
|
|
188
|
+
finally:
|
|
189
|
+
detach(token)
|
|
190
|
+
return return_value
|
|
191
|
+
finally:
|
|
192
|
+
try:
|
|
193
|
+
handler.post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value)
|
|
194
|
+
except Exception as e:
|
|
195
|
+
logger.info(f"Warning: Error occurred in post_tracing: {e}")
|
|
68
196
|
|
|
69
197
|
@with_tracer_wrapper
|
|
70
|
-
def task_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, args, kwargs):
|
|
71
|
-
return
|
|
198
|
+
def task_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, source_path, args, kwargs):
|
|
199
|
+
return monocle_wrapper(tracer, handler, to_wrap, wrapped, instance, source_path, args, kwargs)
|
|
72
200
|
|
|
73
201
|
@with_tracer_wrapper
|
|
74
|
-
async def atask_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, args, kwargs):
|
|
75
|
-
return
|
|
202
|
+
async def atask_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, source_path, args, kwargs):
|
|
203
|
+
return await amonocle_wrapper(tracer, handler, to_wrap, wrapped, instance, source_path, args, kwargs)
|
|
76
204
|
|
|
77
205
|
@with_tracer_wrapper
|
|
78
|
-
def scope_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, args, kwargs):
|
|
206
|
+
def scope_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, source_path, args, kwargs):
|
|
79
207
|
scope_name = to_wrap.get('scope_name', None)
|
|
80
208
|
if scope_name:
|
|
81
209
|
token = set_scope(scope_name)
|
|
@@ -85,8 +213,55 @@ def scope_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instan
|
|
|
85
213
|
return return_value
|
|
86
214
|
|
|
87
215
|
@with_tracer_wrapper
|
|
88
|
-
async def ascope_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, args, kwargs):
|
|
216
|
+
async def ascope_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, source_path, args, kwargs):
|
|
89
217
|
scope_name = to_wrap.get('scope_name', None)
|
|
90
218
|
scope_value = to_wrap.get('scope_value', None)
|
|
91
|
-
|
|
92
|
-
|
|
219
|
+
token = None
|
|
220
|
+
try:
|
|
221
|
+
if scope_name:
|
|
222
|
+
token = set_scope(scope_name, scope_value)
|
|
223
|
+
return_value = await wrapped(*args, **kwargs)
|
|
224
|
+
return return_value
|
|
225
|
+
finally:
|
|
226
|
+
if token:
|
|
227
|
+
remove_scope(token)
|
|
228
|
+
|
|
229
|
+
@with_tracer_wrapper
|
|
230
|
+
def scopes_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, source_path, args, kwargs):
|
|
231
|
+
scope_values = to_wrap.get('scope_values', None)
|
|
232
|
+
scope_values = evaluate_scope_values(args, kwargs, scope_values)
|
|
233
|
+
token = None
|
|
234
|
+
try:
|
|
235
|
+
if scope_values:
|
|
236
|
+
token = set_scopes(scope_values)
|
|
237
|
+
return_value = wrapped(*args, **kwargs)
|
|
238
|
+
return return_value
|
|
239
|
+
finally:
|
|
240
|
+
if token:
|
|
241
|
+
remove_scope(token)
|
|
242
|
+
|
|
243
|
+
@with_tracer_wrapper
|
|
244
|
+
async def ascopes_wrapper(tracer: Tracer, handler: SpanHandler, to_wrap, wrapped, instance, source_path, args, kwargs):
|
|
245
|
+
scope_values = to_wrap.get('scope_values', None)
|
|
246
|
+
scope_values = evaluate_scope_values(args, kwargs, scope_values)
|
|
247
|
+
token = None
|
|
248
|
+
try:
|
|
249
|
+
if scope_values:
|
|
250
|
+
token = set_scopes(scope_values)
|
|
251
|
+
return_value = await wrapped(*args, **kwargs)
|
|
252
|
+
return return_value
|
|
253
|
+
finally:
|
|
254
|
+
if token:
|
|
255
|
+
remove_scope(token)
|
|
256
|
+
|
|
257
|
+
def evaluate_scope_values(args, kwargs, scope_values):
|
|
258
|
+
if callable(scope_values):
|
|
259
|
+
try:
|
|
260
|
+
scope_values = scope_values(args, kwargs)
|
|
261
|
+
except Exception as e:
|
|
262
|
+
logger.warning("Warning: Error occurred in evaluate_scope_values: %s", str(e))
|
|
263
|
+
scope_values = None
|
|
264
|
+
if isinstance(scope_values, dict):
|
|
265
|
+
return scope_values
|
|
266
|
+
return None
|
|
267
|
+
|
|
@@ -10,14 +10,16 @@ from monocle_apptrace.instrumentation.metamodel.langchain.methods import (
|
|
|
10
10
|
from monocle_apptrace.instrumentation.metamodel.llamaindex.methods import (LLAMAINDEX_METHODS, )
|
|
11
11
|
from monocle_apptrace.instrumentation.metamodel.haystack.methods import (HAYSTACK_METHODS, )
|
|
12
12
|
from monocle_apptrace.instrumentation.metamodel.openai.methods import (OPENAI_METHODS,)
|
|
13
|
+
from monocle_apptrace.instrumentation.metamodel.openai._helper import OpenAISpanHandler
|
|
13
14
|
from monocle_apptrace.instrumentation.metamodel.langgraph.methods import LANGGRAPH_METHODS
|
|
14
15
|
from monocle_apptrace.instrumentation.metamodel.flask.methods import (FLASK_METHODS, )
|
|
15
|
-
from monocle_apptrace.instrumentation.metamodel.flask._helper import FlaskSpanHandler
|
|
16
|
+
from monocle_apptrace.instrumentation.metamodel.flask._helper import FlaskSpanHandler, FlaskResponseSpanHandler
|
|
16
17
|
from monocle_apptrace.instrumentation.metamodel.requests.methods import (REQUESTS_METHODS, )
|
|
17
18
|
from monocle_apptrace.instrumentation.metamodel.requests._helper import RequestSpanHandler
|
|
18
19
|
from monocle_apptrace.instrumentation.metamodel.teamsai.methods import (TEAMAI_METHODS, )
|
|
19
20
|
from monocle_apptrace.instrumentation.metamodel.anthropic.methods import (ANTHROPIC_METHODS, )
|
|
20
|
-
|
|
21
|
+
from monocle_apptrace.instrumentation.metamodel.aiohttp.methods import (AIOHTTP_METHODS, )
|
|
22
|
+
from monocle_apptrace.instrumentation.metamodel.aiohttp._helper import aiohttpSpanHandler
|
|
21
23
|
class WrapperMethod:
|
|
22
24
|
def __init__(
|
|
23
25
|
self,
|
|
@@ -29,7 +31,8 @@ class WrapperMethod:
|
|
|
29
31
|
wrapper_method = task_wrapper,
|
|
30
32
|
span_handler = 'default',
|
|
31
33
|
scope_name: str = None,
|
|
32
|
-
span_type: str = None
|
|
34
|
+
span_type: str = None,
|
|
35
|
+
scope_values = None,
|
|
33
36
|
):
|
|
34
37
|
self.package = package
|
|
35
38
|
self.object = object_name
|
|
@@ -37,10 +40,11 @@ class WrapperMethod:
|
|
|
37
40
|
self.span_name = span_name
|
|
38
41
|
self.output_processor=output_processor
|
|
39
42
|
self.span_type = span_type
|
|
43
|
+
self.scope_values = scope_values
|
|
40
44
|
|
|
41
45
|
self.span_handler:SpanHandler.__class__ = span_handler
|
|
42
46
|
self.scope_name = scope_name
|
|
43
|
-
if scope_name:
|
|
47
|
+
if scope_name and not scope_values:
|
|
44
48
|
self.wrapper_method = scope_wrapper
|
|
45
49
|
else:
|
|
46
50
|
self.wrapper_method = wrapper_method
|
|
@@ -56,19 +60,23 @@ class WrapperMethod:
|
|
|
56
60
|
'wrapper_method': self.wrapper_method,
|
|
57
61
|
'span_handler': self.span_handler,
|
|
58
62
|
'scope_name': self.scope_name,
|
|
59
|
-
'span_type': self.span_type
|
|
63
|
+
'span_type': self.span_type,
|
|
64
|
+
'scope_values': self.scope_values,
|
|
60
65
|
}
|
|
61
66
|
return instance_dict
|
|
62
67
|
|
|
63
68
|
def get_span_handler(self) -> SpanHandler:
|
|
64
69
|
return self.span_handler()
|
|
65
70
|
|
|
66
|
-
DEFAULT_METHODS_LIST = LANGCHAIN_METHODS + LLAMAINDEX_METHODS + HAYSTACK_METHODS + BOTOCORE_METHODS + FLASK_METHODS + REQUESTS_METHODS + LANGGRAPH_METHODS + OPENAI_METHODS + TEAMAI_METHODS + ANTHROPIC_METHODS
|
|
71
|
+
DEFAULT_METHODS_LIST = LANGCHAIN_METHODS + LLAMAINDEX_METHODS + HAYSTACK_METHODS + BOTOCORE_METHODS + FLASK_METHODS + REQUESTS_METHODS + LANGGRAPH_METHODS + OPENAI_METHODS + TEAMAI_METHODS + ANTHROPIC_METHODS + AIOHTTP_METHODS
|
|
67
72
|
|
|
68
73
|
MONOCLE_SPAN_HANDLERS: Dict[str, SpanHandler] = {
|
|
69
74
|
"default": SpanHandler(),
|
|
75
|
+
"aiohttp_handler": aiohttpSpanHandler(),
|
|
70
76
|
"botocore_handler": BotoCoreSpanHandler(),
|
|
71
77
|
"flask_handler": FlaskSpanHandler(),
|
|
78
|
+
"flask_response_handler": FlaskResponseSpanHandler(),
|
|
72
79
|
"request_handler": RequestSpanHandler(),
|
|
73
|
-
"non_framework_handler": NonFrameworkSpanHandler()
|
|
80
|
+
"non_framework_handler": NonFrameworkSpanHandler(),
|
|
81
|
+
"openai_handler": OpenAISpanHandler(),
|
|
74
82
|
}
|
|
File without changes
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from threading import local
|
|
3
|
+
from monocle_apptrace.instrumentation.common.utils import extract_http_headers, clear_http_scopes, try_option, Option, MonocleSpanException
|
|
4
|
+
from monocle_apptrace.instrumentation.common.span_handler import SpanHandler
|
|
5
|
+
from monocle_apptrace.instrumentation.common.constants import HTTP_SUCCESS_CODES
|
|
6
|
+
from urllib.parse import unquote
|
|
7
|
+
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
MAX_DATA_LENGTH = 1000
|
|
10
|
+
token_data = local()
|
|
11
|
+
token_data.current_token = None
|
|
12
|
+
|
|
13
|
+
def get_route(args) -> str:
|
|
14
|
+
route_path: Option[str] = try_option(getattr, args[0], 'path')
|
|
15
|
+
return route_path.unwrap_or("")
|
|
16
|
+
|
|
17
|
+
def get_method(args) -> str:
|
|
18
|
+
# return args[0]['method'] if 'method' in args[0] else ""
|
|
19
|
+
http_method: Option[str] = try_option(getattr, args[0], 'method')
|
|
20
|
+
return http_method.unwrap_or("")
|
|
21
|
+
|
|
22
|
+
def get_params(args) -> dict:
|
|
23
|
+
params: Option[str] = try_option(getattr, args[0], 'query_string')
|
|
24
|
+
return unquote(params.unwrap_or(""))
|
|
25
|
+
|
|
26
|
+
def get_body(args) -> dict:
|
|
27
|
+
return ""
|
|
28
|
+
|
|
29
|
+
def extract_response(result) -> str:
|
|
30
|
+
if hasattr(result, 'text'):
|
|
31
|
+
response = result.text[0:max(result.text.__len__(), MAX_DATA_LENGTH)]
|
|
32
|
+
else:
|
|
33
|
+
response = ""
|
|
34
|
+
return response
|
|
35
|
+
|
|
36
|
+
def extract_status(result) -> str:
|
|
37
|
+
status = f"{result.status}" if hasattr(result, 'status') else ""
|
|
38
|
+
if status not in HTTP_SUCCESS_CODES:
|
|
39
|
+
error_message = extract_response(result)
|
|
40
|
+
raise MonocleSpanException(f"error: {status} - {error_message}")
|
|
41
|
+
return status
|
|
42
|
+
|
|
43
|
+
def aiohttp_pre_tracing(args):
|
|
44
|
+
token_data.current_token = extract_http_headers(args[0].headers)
|
|
45
|
+
|
|
46
|
+
def aiohttp_post_tracing():
|
|
47
|
+
clear_http_scopes(token_data.current_token)
|
|
48
|
+
token_data.current_token = None
|
|
49
|
+
|
|
50
|
+
def aiohttp_skip_span(args) -> bool:
|
|
51
|
+
if get_method(args) == "HEAD":
|
|
52
|
+
return True
|
|
53
|
+
return False
|
|
54
|
+
|
|
55
|
+
class aiohttpSpanHandler(SpanHandler):
|
|
56
|
+
|
|
57
|
+
def pre_tracing(self, to_wrap, wrapped, instance, args, kwargs):
|
|
58
|
+
aiohttp_pre_tracing(args)
|
|
59
|
+
return super().pre_tracing(to_wrap, wrapped, instance, args, kwargs)
|
|
60
|
+
|
|
61
|
+
def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value):
|
|
62
|
+
aiohttp_post_tracing()
|
|
63
|
+
return super().post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value)
|
|
64
|
+
|
|
65
|
+
def skip_span(self, to_wrap, wrapped, instance, args, kwargs) -> bool:
|
|
66
|
+
return aiohttp_skip_span(args)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from monocle_apptrace.instrumentation.metamodel.aiohttp import _helper
|
|
2
|
+
AIO_HTTP_PROCESSOR = {
|
|
3
|
+
"type": "http.process",
|
|
4
|
+
"attributes": [
|
|
5
|
+
[
|
|
6
|
+
{
|
|
7
|
+
"_comment": "request method, request URI",
|
|
8
|
+
"attribute": "method",
|
|
9
|
+
"accessor": lambda arguments: _helper.get_method(arguments['args'])
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"_comment": "request method, request URI",
|
|
13
|
+
"attribute": "route",
|
|
14
|
+
"accessor": lambda arguments: _helper.get_route(arguments['args'])
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"_comment": "request method, request URI",
|
|
18
|
+
"attribute": "body",
|
|
19
|
+
"accessor": lambda arguments: _helper.get_body(arguments['args'])
|
|
20
|
+
},
|
|
21
|
+
]
|
|
22
|
+
],
|
|
23
|
+
"events": [
|
|
24
|
+
{
|
|
25
|
+
"name": "data.input",
|
|
26
|
+
"attributes": [
|
|
27
|
+
{
|
|
28
|
+
"_comment": "route params",
|
|
29
|
+
"attribute": "params",
|
|
30
|
+
"accessor": lambda arguments: _helper.get_params(arguments['args'])
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"name": "data.output",
|
|
36
|
+
"attributes": [
|
|
37
|
+
{
|
|
38
|
+
"_comment": "status from HTTP response",
|
|
39
|
+
"attribute": "status",
|
|
40
|
+
"accessor": lambda arguments: _helper.extract_status(arguments['result'])
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"_comment": "this is result from LLM",
|
|
44
|
+
"attribute": "response",
|
|
45
|
+
"accessor": lambda arguments: _helper.extract_response(arguments['result'])
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
]
|
|
51
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from monocle_apptrace.instrumentation.common.wrapper import atask_wrapper
|
|
2
|
+
from monocle_apptrace.instrumentation.metamodel.aiohttp.entities.http import AIO_HTTP_PROCESSOR
|
|
3
|
+
|
|
4
|
+
AIOHTTP_METHODS = [
|
|
5
|
+
{
|
|
6
|
+
"package": "aiohttp.web_app",
|
|
7
|
+
"object": "Application",
|
|
8
|
+
"method": "_handle",
|
|
9
|
+
"wrapper_method": atask_wrapper,
|
|
10
|
+
"span_handler": "aiohttp_handler",
|
|
11
|
+
"output_processor": AIO_HTTP_PROCESSOR
|
|
12
|
+
}
|
|
13
|
+
]
|
|
@@ -5,17 +5,19 @@ from monocle_apptrace.instrumentation.metamodel.anthropic.entities.inference imp
|
|
|
5
5
|
|
|
6
6
|
ANTHROPIC_METHODS = [
|
|
7
7
|
{
|
|
8
|
-
"package": "anthropic.resources
|
|
8
|
+
"package": "anthropic.resources",
|
|
9
9
|
"object": "Messages",
|
|
10
10
|
"method": "create",
|
|
11
11
|
"wrapper_method": task_wrapper,
|
|
12
|
+
"span_handler": "non_framework_handler",
|
|
12
13
|
"output_processor": INFERENCE
|
|
13
14
|
},
|
|
14
15
|
{
|
|
15
|
-
"package": "anthropic.resources
|
|
16
|
+
"package": "anthropic.resources",
|
|
16
17
|
"object": "AsyncMessages",
|
|
17
18
|
"method": "create",
|
|
18
19
|
"wrapper_method": atask_wrapper,
|
|
20
|
+
"span_handler": "non_framework_handler",
|
|
19
21
|
"output_processor": INFERENCE
|
|
20
22
|
},
|
|
21
23
|
|
|
@@ -1,11 +1,46 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from threading import local
|
|
2
3
|
from monocle_apptrace.instrumentation.common.utils import extract_http_headers, clear_http_scopes
|
|
3
|
-
from opentelemetry.propagate import extract
|
|
4
|
-
from opentelemetry.context import Context, attach, detach
|
|
5
4
|
from monocle_apptrace.instrumentation.common.span_handler import SpanHandler
|
|
5
|
+
from monocle_apptrace.instrumentation.common.constants import HTTP_SUCCESS_CODES
|
|
6
|
+
from monocle_apptrace.instrumentation.common.utils import MonocleSpanException
|
|
7
|
+
from urllib.parse import unquote
|
|
8
|
+
from opentelemetry.context import get_current
|
|
9
|
+
from opentelemetry.trace import Span, get_current_span
|
|
10
|
+
from opentelemetry.trace.propagation import _SPAN_KEY
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger(__name__)
|
|
13
|
+
MAX_DATA_LENGTH = 1000
|
|
6
14
|
token_data = local()
|
|
7
15
|
token_data.current_token = None
|
|
8
16
|
|
|
17
|
+
def get_route(args) -> str:
|
|
18
|
+
return args[0]['PATH_INFO'] if 'PATH_INFO' in args[0] else ""
|
|
19
|
+
|
|
20
|
+
def get_method(args) -> str:
|
|
21
|
+
return args[0]['REQUEST_METHOD'] if 'REQUEST_METHOD' in args[0] else ""
|
|
22
|
+
|
|
23
|
+
def get_params(args) -> dict:
|
|
24
|
+
params = args[0]['QUERY_STRING'] if 'QUERY_STRING' in args[0] else ""
|
|
25
|
+
return unquote(params)
|
|
26
|
+
|
|
27
|
+
def get_body(args) -> dict:
|
|
28
|
+
return ""
|
|
29
|
+
|
|
30
|
+
def extract_response(instance) -> str:
|
|
31
|
+
if hasattr(instance, 'data') and hasattr(instance, 'content_length'):
|
|
32
|
+
response = instance.data[0:max(instance.content_length, MAX_DATA_LENGTH)]
|
|
33
|
+
else:
|
|
34
|
+
response = ""
|
|
35
|
+
return response
|
|
36
|
+
|
|
37
|
+
def extract_status(instance) -> str:
|
|
38
|
+
status = f"{instance.status_code}" if hasattr(instance, 'status_code') else ""
|
|
39
|
+
if status not in HTTP_SUCCESS_CODES:
|
|
40
|
+
error_message = extract_response(instance)
|
|
41
|
+
raise MonocleSpanException(f"error: {status} - {error_message}")
|
|
42
|
+
return status
|
|
43
|
+
|
|
9
44
|
def flask_pre_tracing(args):
|
|
10
45
|
headers = dict()
|
|
11
46
|
for key, value in args[0].items():
|
|
@@ -26,4 +61,16 @@ class FlaskSpanHandler(SpanHandler):
|
|
|
26
61
|
|
|
27
62
|
def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value):
|
|
28
63
|
flask_post_tracing()
|
|
29
|
-
return super().post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value)
|
|
64
|
+
return super().post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value)
|
|
65
|
+
|
|
66
|
+
class FlaskResponseSpanHandler(SpanHandler):
|
|
67
|
+
def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value):
|
|
68
|
+
try:
|
|
69
|
+
_parent_span_context = get_current()
|
|
70
|
+
if _parent_span_context is not None:
|
|
71
|
+
parent_span: Span = _parent_span_context.get(_SPAN_KEY, None)
|
|
72
|
+
if parent_span is not None:
|
|
73
|
+
self.hydrate_events(to_wrap, wrapped, instance, args, kwargs, return_value, parent_span)
|
|
74
|
+
except Exception as e:
|
|
75
|
+
logger.info(f"Failed to propogate flask response: {e}")
|
|
76
|
+
super().post_tracing(to_wrap, wrapped, instance, args, kwargs, return_value)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from monocle_apptrace.instrumentation.metamodel.flask import _helper
|
|
2
|
+
FLASK_HTTP_PROCESSOR = {
|
|
3
|
+
"type": "http.process",
|
|
4
|
+
"attributes": [
|
|
5
|
+
[
|
|
6
|
+
{
|
|
7
|
+
"_comment": "request method, request URI",
|
|
8
|
+
"attribute": "method",
|
|
9
|
+
"accessor": lambda arguments: _helper.get_method(arguments['args'])
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"_comment": "request method, request URI",
|
|
13
|
+
"attribute": "route",
|
|
14
|
+
"accessor": lambda arguments: _helper.get_route(arguments['args'])
|
|
15
|
+
},
|
|
16
|
+
]
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
FLASK_RESPONSE_PROCESSOR = {
|
|
21
|
+
"events": [
|
|
22
|
+
{
|
|
23
|
+
"name": "data.input",
|
|
24
|
+
"attributes": [
|
|
25
|
+
{
|
|
26
|
+
"_comment": "route params",
|
|
27
|
+
"attribute": "params",
|
|
28
|
+
"accessor": lambda arguments: _helper.get_params(arguments['args'])
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "data.output",
|
|
34
|
+
"attributes": [
|
|
35
|
+
{
|
|
36
|
+
"_comment": "status from HTTP response",
|
|
37
|
+
"attribute": "status",
|
|
38
|
+
"accessor": lambda arguments: _helper.extract_status(arguments['instance'])
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"_comment": "this is result from LLM",
|
|
42
|
+
"attribute": "response",
|
|
43
|
+
"accessor": lambda arguments: _helper.extract_response(arguments['instance'])
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|