opentelemetry-instrumentation-llamaindex 0.9.3__tar.gz → 0.49.1__tar.gz

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.
Files changed (28) hide show
  1. {opentelemetry_instrumentation_llamaindex-0.9.3 → opentelemetry_instrumentation_llamaindex-0.49.1}/PKG-INFO +20 -6
  2. {opentelemetry_instrumentation_llamaindex-0.9.3 → opentelemetry_instrumentation_llamaindex-0.49.1}/README.md +8 -0
  3. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/__init__.py +134 -0
  4. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/base_agent_instrumentor.py +80 -0
  5. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/base_embedding_instrumentor.py +68 -0
  6. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/base_retriever_instrumentor.py +73 -0
  7. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/base_synthesizer_instrumentor.py +72 -0
  8. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/base_tool_instrumentor.py +82 -0
  9. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/config.py +9 -0
  10. {opentelemetry_instrumentation_llamaindex-0.9.3 → opentelemetry_instrumentation_llamaindex-0.49.1}/opentelemetry/instrumentation/llamaindex/custom_llm_instrumentor.py +73 -21
  11. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/dispatcher_wrapper.py +297 -0
  12. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/event_emitter.py +161 -0
  13. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/event_models.py +41 -0
  14. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/llamaparse_instrumentor.py +169 -0
  15. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/query_pipeline_instrumentor.py +80 -0
  16. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/retriever_query_engine_instrumentor.py +81 -0
  17. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/span_utils.py +151 -0
  18. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/utils.py +104 -0
  19. opentelemetry_instrumentation_llamaindex-0.49.1/opentelemetry/instrumentation/llamaindex/version.py +1 -0
  20. opentelemetry_instrumentation_llamaindex-0.49.1/pyproject.toml +67 -0
  21. opentelemetry_instrumentation_llamaindex-0.9.3/opentelemetry/instrumentation/llamaindex/__init__.py +0 -39
  22. opentelemetry_instrumentation_llamaindex-0.9.3/opentelemetry/instrumentation/llamaindex/base_embedding_instrumentor.py +0 -43
  23. opentelemetry_instrumentation_llamaindex-0.9.3/opentelemetry/instrumentation/llamaindex/base_retriever_instrumentor.py +0 -39
  24. opentelemetry_instrumentation_llamaindex-0.9.3/opentelemetry/instrumentation/llamaindex/base_synthesizer_instrumentor.py +0 -39
  25. opentelemetry_instrumentation_llamaindex-0.9.3/opentelemetry/instrumentation/llamaindex/retriever_query_engine_instrumentor.py +0 -48
  26. opentelemetry_instrumentation_llamaindex-0.9.3/opentelemetry/instrumentation/llamaindex/utils.py +0 -27
  27. opentelemetry_instrumentation_llamaindex-0.9.3/opentelemetry/instrumentation/llamaindex/version.py +0 -1
  28. opentelemetry_instrumentation_llamaindex-0.9.3/pyproject.toml +0 -39
@@ -1,21 +1,27 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: opentelemetry-instrumentation-llamaindex
3
- Version: 0.9.3
3
+ Version: 0.49.1
4
4
  Summary: OpenTelemetry LlamaIndex instrumentation
5
5
  License: Apache-2.0
6
6
  Author: Gal Kleinman
7
7
  Author-email: gal@traceloop.com
8
- Requires-Python: >=3.8.1,<4
8
+ Requires-Python: >=3.9,<4
9
9
  Classifier: License :: OSI Approved :: Apache Software License
10
10
  Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.9
12
12
  Classifier: Programming Language :: Python :: 3.10
13
13
  Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Provides-Extra: instruments
18
+ Provides-Extra: llamaparse
15
19
  Requires-Dist: inflection (>=0.5.1,<0.6.0)
16
- Requires-Dist: opentelemetry-api (>=1.22.0,<2.0.0)
17
- Requires-Dist: opentelemetry-instrumentation (==0.43b0)
18
- Requires-Dist: opentelemetry-semantic-conventions-ai (>=0.0.14,<0.0.15)
20
+ Requires-Dist: opentelemetry-api (>=1.38.0,<2.0.0)
21
+ Requires-Dist: opentelemetry-instrumentation (>=0.59b0)
22
+ Requires-Dist: opentelemetry-semantic-conventions (>=0.59b0)
23
+ Requires-Dist: opentelemetry-semantic-conventions-ai (>=0.4.13,<0.5.0)
24
+ Project-URL: Repository, https://github.com/traceloop/openllmetry/tree/main/packages/opentelemetry-instrumentation-llamaindex
19
25
  Description-Content-Type: text/markdown
20
26
 
21
27
  # OpenTelemetry LlamaIndex Instrumentation
@@ -32,6 +38,14 @@ This library allows tracing complete LLM applications built with [LlamaIndex](ht
32
38
  pip install opentelemetry-instrumentation-llamaindex
33
39
  ```
34
40
 
41
+ ## Example usage
42
+
43
+ ```python
44
+ from opentelemetry.instrumentation.llamaindex import LlamaIndexInstrumentor
45
+
46
+ LlamaIndexInstrumentor().instrument()
47
+ ```
48
+
35
49
  ## Privacy
36
50
 
37
51
  **By default, this instrumentation logs prompts, completions, and embeddings to span attributes**. This gives you a clear visibility into how your LLM application is working, and can make it easy to debug and evaluate the quality of the outputs.
@@ -12,6 +12,14 @@ This library allows tracing complete LLM applications built with [LlamaIndex](ht
12
12
  pip install opentelemetry-instrumentation-llamaindex
13
13
  ```
14
14
 
15
+ ## Example usage
16
+
17
+ ```python
18
+ from opentelemetry.instrumentation.llamaindex import LlamaIndexInstrumentor
19
+
20
+ LlamaIndexInstrumentor().instrument()
21
+ ```
22
+
15
23
  ## Privacy
16
24
 
17
25
  **By default, this instrumentation logs prompts, completions, and embeddings to span attributes**. This gives you a clear visibility into how your LLM application is working, and can make it easy to debug and evaluate the quality of the outputs.
@@ -0,0 +1,134 @@
1
+ """OpenTelemetry LlamaIndex instrumentation"""
2
+
3
+ import logging
4
+ from importlib.metadata import version as import_version
5
+ from typing import Collection
6
+
7
+ from opentelemetry._logs import get_logger
8
+ from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
9
+ from opentelemetry.instrumentation.llamaindex.base_agent_instrumentor import (
10
+ BaseAgentInstrumentor,
11
+ )
12
+ from opentelemetry.instrumentation.llamaindex.base_embedding_instrumentor import (
13
+ BaseEmbeddingInstrumentor,
14
+ )
15
+ from opentelemetry.instrumentation.llamaindex.base_retriever_instrumentor import (
16
+ BaseRetrieverInstrumentor,
17
+ )
18
+ from opentelemetry.instrumentation.llamaindex.base_synthesizer_instrumentor import (
19
+ BaseSynthesizerInstrumentor,
20
+ )
21
+ from opentelemetry.instrumentation.llamaindex.base_tool_instrumentor import (
22
+ BaseToolInstrumentor,
23
+ )
24
+ from opentelemetry.instrumentation.llamaindex.config import Config
25
+ from opentelemetry.instrumentation.llamaindex.custom_llm_instrumentor import (
26
+ CustomLLMInstrumentor,
27
+ )
28
+ from opentelemetry.instrumentation.llamaindex.dispatcher_wrapper import (
29
+ instrument_with_dispatcher,
30
+ )
31
+ from opentelemetry.instrumentation.llamaindex.llamaparse_instrumentor import (
32
+ LlamaParseInstrumentor,
33
+ )
34
+ from opentelemetry.instrumentation.llamaindex.query_pipeline_instrumentor import (
35
+ QueryPipelineInstrumentor,
36
+ )
37
+ from opentelemetry.instrumentation.llamaindex.retriever_query_engine_instrumentor import (
38
+ RetrieverQueryEngineInstrumentor,
39
+ )
40
+ from opentelemetry.instrumentation.llamaindex.version import __version__
41
+ from opentelemetry.trace import get_tracer
42
+
43
+ logger = logging.getLogger(__name__)
44
+
45
+ _core_instruments = ("llama-index-core >= 0.7.0",)
46
+ _full_instruments = ("llama-index >= 0.7.0",)
47
+
48
+
49
+ class LlamaIndexInstrumentor(BaseInstrumentor):
50
+ """An instrumentor for both: core and legacy LlamaIndex SDK."""
51
+
52
+ def __init__(self, exception_logger=None, use_legacy_attributes=True):
53
+ self.legacy = LlamaIndexInstrumentorFull(exception_logger)
54
+ self.core = LlamaIndexInstrumentorCore(exception_logger)
55
+ Config.use_legacy_attributes = use_legacy_attributes
56
+
57
+ def instrumentation_dependencies(self) -> Collection[str]:
58
+ return ()
59
+
60
+ def _instrument(self, **kwargs):
61
+ # Try to use the legacy entry point for instrumentation
62
+ if self.legacy._check_dependency_conflicts() is None:
63
+ self.legacy.instrument(**kwargs)
64
+ if not self.legacy._is_instrumented_by_opentelemetry:
65
+ # it didn't work -> try the new package
66
+ if self.core._check_dependency_conflicts() is None:
67
+ self.core.instrument(**kwargs)
68
+
69
+ def _uninstrument(self, **kwargs):
70
+ self.legacy.uninstrument(**kwargs)
71
+ self.core.uninstrument(**kwargs)
72
+
73
+ @staticmethod
74
+ def apply_instrumentation(name, **kwargs):
75
+ tracer_provider = kwargs.get("tracer_provider")
76
+ tracer = get_tracer(__name__, __version__, tracer_provider)
77
+
78
+ if not Config.use_legacy_attributes:
79
+ logger_provider = kwargs.get("logger_provider")
80
+ Config.event_logger = get_logger(
81
+ __name__, __version__, logger_provider=logger_provider
82
+ )
83
+
84
+ if import_version(name) >= "0.10.20":
85
+ instrument_with_dispatcher(tracer)
86
+ else:
87
+ RetrieverQueryEngineInstrumentor(tracer).instrument()
88
+ BaseRetrieverInstrumentor(tracer).instrument()
89
+ BaseSynthesizerInstrumentor(tracer).instrument()
90
+ BaseEmbeddingInstrumentor(tracer).instrument()
91
+ CustomLLMInstrumentor(tracer).instrument()
92
+ QueryPipelineInstrumentor(tracer).instrument()
93
+ BaseAgentInstrumentor(tracer).instrument()
94
+ BaseToolInstrumentor(tracer).instrument()
95
+
96
+ # LlamaParse instrumentation doesn't work for all versions
97
+ try:
98
+ LlamaParseInstrumentor(tracer).instrument()
99
+ except Exception:
100
+ pass
101
+
102
+
103
+ class LlamaIndexInstrumentorCore(BaseInstrumentor):
104
+ """An instrumentor for core LlamaIndex SDK."""
105
+
106
+ def __init__(self, exception_logger=None):
107
+ super().__init__()
108
+ Config.exception_logger = exception_logger
109
+
110
+ def instrumentation_dependencies(self) -> Collection[str]:
111
+ return _core_instruments
112
+
113
+ def _instrument(self, **kwargs):
114
+ LlamaIndexInstrumentor.apply_instrumentation("llama-index-core", **kwargs)
115
+
116
+ def _uninstrument(self, **kwargs):
117
+ pass
118
+
119
+
120
+ class LlamaIndexInstrumentorFull(BaseInstrumentor):
121
+ """An instrumentor for legacy LlamaIndex SDK."""
122
+
123
+ def __init__(self, exception_logger=None):
124
+ super().__init__()
125
+ Config.exception_logger = exception_logger
126
+
127
+ def instrumentation_dependencies(self) -> Collection[str]:
128
+ return _full_instruments
129
+
130
+ def _instrument(self, **kwargs):
131
+ LlamaIndexInstrumentor.apply_instrumentation("llama-index", **kwargs)
132
+
133
+ def _uninstrument(self, **kwargs):
134
+ pass
@@ -0,0 +1,80 @@
1
+ from importlib.metadata import version as package_version, PackageNotFoundError
2
+
3
+ from wrapt import wrap_function_wrapper
4
+
5
+ from opentelemetry.instrumentation.llamaindex.utils import (
6
+ _with_tracer_wrapper,
7
+ process_request,
8
+ process_response,
9
+ start_as_current_span_async,
10
+ )
11
+ from opentelemetry.semconv_ai import SpanAttributes, TraceloopSpanKindValues
12
+
13
+
14
+ TO_INSTRUMENT = [
15
+ {
16
+ "class": "AgentRunner",
17
+ "v10_module": "llama_index.core.agent.runner.base",
18
+ "v10_legacy_module": "llama_index.legacy.agent.runner.base",
19
+ },
20
+ {
21
+ "class": "OpenAIAssistantAgent",
22
+ "v10_module": "llama_index.agent.openai.openai_assistant_agent",
23
+ "v10_legacy_module": "llama_index.legacy.agent.openai_assistant_agent",
24
+ },
25
+ ]
26
+
27
+
28
+ class BaseAgentInstrumentor:
29
+ def __init__(self, tracer):
30
+ self._tracer = tracer
31
+
32
+ def instrument(self):
33
+ for module in TO_INSTRUMENT:
34
+ try:
35
+ package_version("llama-index-core")
36
+ self._instrument_module(module["v10_module"], module["class"])
37
+ self._instrument_module(module["v10_legacy_module"], module["class"])
38
+
39
+ except PackageNotFoundError:
40
+ pass # not supported before v10
41
+
42
+ def _instrument_module(self, module_name, class_name):
43
+ wrap_function_wrapper(
44
+ module_name, f"{class_name}.chat", query_wrapper(self._tracer)
45
+ )
46
+ wrap_function_wrapper(
47
+ module_name, f"{class_name}.achat", aquery_wrapper(self._tracer)
48
+ )
49
+
50
+
51
+ @_with_tracer_wrapper
52
+ def query_wrapper(tracer, wrapped, instance, args, kwargs):
53
+ name = instance.__class__.__name__
54
+ with tracer.start_as_current_span(f"{name}.agent") as span:
55
+ span.set_attribute(
56
+ SpanAttributes.TRACELOOP_SPAN_KIND,
57
+ TraceloopSpanKindValues.AGENT.value,
58
+ )
59
+ span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_NAME, name)
60
+
61
+ process_request(span, args, kwargs)
62
+ res = wrapped(*args, **kwargs)
63
+ process_response(span, res)
64
+ return res
65
+
66
+
67
+ @_with_tracer_wrapper
68
+ async def aquery_wrapper(tracer, wrapped, instance, args, kwargs):
69
+ name = instance.__class__.__name__
70
+ async with start_as_current_span_async(tracer=tracer, name=f"{name}.agent") as span:
71
+ span.set_attribute(
72
+ SpanAttributes.TRACELOOP_SPAN_KIND,
73
+ TraceloopSpanKindValues.AGENT.value,
74
+ )
75
+ span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_NAME, name)
76
+
77
+ process_request(span, args, kwargs)
78
+ res = await wrapped(*args, **kwargs)
79
+ process_response(span, res)
80
+ return res
@@ -0,0 +1,68 @@
1
+ from importlib.metadata import version as package_version, PackageNotFoundError
2
+
3
+ from wrapt import wrap_function_wrapper
4
+
5
+ from opentelemetry.instrumentation.llamaindex.utils import (
6
+ _with_tracer_wrapper,
7
+ start_as_current_span_async,
8
+ )
9
+ from opentelemetry.semconv_ai import SpanAttributes, TraceloopSpanKindValues
10
+
11
+ V9_MODULE_NAME = "llama_index.embeddings.base"
12
+ V10_MODULE_NAME = "llama_index.core.embeddings"
13
+ V10_LEGACY_MODULE_NAME = "llama_index.legacy.embeddings.base"
14
+
15
+ CLASS_NAME = "BaseEmbedding"
16
+ TASK_NAME = "get_query_embedding"
17
+
18
+
19
+ class BaseEmbeddingInstrumentor:
20
+ def __init__(self, tracer):
21
+ self._tracer = tracer
22
+
23
+ def instrument(self):
24
+ try:
25
+ package_version("llama-index-core")
26
+ self._instrument_module(V10_MODULE_NAME)
27
+ self._instrument_module(V10_LEGACY_MODULE_NAME)
28
+
29
+ except PackageNotFoundError:
30
+ self._instrument_module(V9_MODULE_NAME)
31
+
32
+ def _instrument_module(self, module_name):
33
+ wrap_function_wrapper(
34
+ module_name,
35
+ f"{CLASS_NAME}.get_query_embedding",
36
+ get_query_embedding_wrapper(self._tracer),
37
+ )
38
+ wrap_function_wrapper(
39
+ module_name,
40
+ f"{CLASS_NAME}.aget_query_embedding",
41
+ aget_query_embedding_wrapper(self._tracer),
42
+ )
43
+
44
+
45
+ @_with_tracer_wrapper
46
+ def get_query_embedding_wrapper(tracer, wrapped, instance, args, kwargs):
47
+ with tracer.start_as_current_span(f"{TASK_NAME}.task") as span:
48
+ span.set_attribute(
49
+ SpanAttributes.TRACELOOP_SPAN_KIND,
50
+ TraceloopSpanKindValues.TASK.value,
51
+ )
52
+ span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_NAME, TASK_NAME)
53
+
54
+ return wrapped(*args, **kwargs)
55
+
56
+
57
+ @_with_tracer_wrapper
58
+ async def aget_query_embedding_wrapper(tracer, wrapped, instance, args, kwargs):
59
+ async with start_as_current_span_async(
60
+ tracer=tracer, name=f"{TASK_NAME}.task"
61
+ ) as span:
62
+ span.set_attribute(
63
+ SpanAttributes.TRACELOOP_SPAN_KIND,
64
+ TraceloopSpanKindValues.TASK.value,
65
+ )
66
+ span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_NAME, TASK_NAME)
67
+
68
+ return await wrapped(*args, **kwargs)
@@ -0,0 +1,73 @@
1
+ from importlib.metadata import version as package_version, PackageNotFoundError
2
+
3
+ from wrapt import wrap_function_wrapper
4
+
5
+ from opentelemetry.instrumentation.llamaindex.utils import (
6
+ _with_tracer_wrapper,
7
+ process_request,
8
+ process_response,
9
+ start_as_current_span_async,
10
+ )
11
+ from opentelemetry.semconv_ai import SpanAttributes, TraceloopSpanKindValues
12
+
13
+
14
+ V9_MODULE_NAME = "llama_index.indices.base_retriever"
15
+ V10_MODULE_NAME = "llama_index.core.indices.base_retriever"
16
+ V10_LEGACY_MODULE_NAME = "llama_index.legacy.indices.base_retriever"
17
+
18
+ CLASS_NAME = "BaseRetriever"
19
+ TASK_NAME = "retrieve"
20
+
21
+
22
+ class BaseRetrieverInstrumentor:
23
+ def __init__(self, tracer):
24
+ self._tracer = tracer
25
+
26
+ def instrument(self):
27
+ try:
28
+ package_version("llama-index-core")
29
+ self._instrument_module(V10_MODULE_NAME)
30
+ self._instrument_module(V10_LEGACY_MODULE_NAME)
31
+
32
+ except PackageNotFoundError:
33
+ self._instrument_module(V9_MODULE_NAME)
34
+
35
+ def _instrument_module(self, module_name):
36
+ wrap_function_wrapper(
37
+ module_name, f"{CLASS_NAME}.retrieve", retrieve_wrapper(self._tracer)
38
+ )
39
+ wrap_function_wrapper(
40
+ module_name, f"{CLASS_NAME}.aretrieve", aretrieve_wrapper(self._tracer)
41
+ )
42
+
43
+
44
+ @_with_tracer_wrapper
45
+ def retrieve_wrapper(tracer, wrapped, instance, args, kwargs):
46
+ with tracer.start_as_current_span(f"{TASK_NAME}.task") as span:
47
+ span.set_attribute(
48
+ SpanAttributes.TRACELOOP_SPAN_KIND,
49
+ TraceloopSpanKindValues.TASK.value,
50
+ )
51
+ span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_NAME, TASK_NAME)
52
+
53
+ process_request(span, args, kwargs)
54
+ res = wrapped(*args, **kwargs)
55
+ process_response(span, res)
56
+ return res
57
+
58
+
59
+ @_with_tracer_wrapper
60
+ async def aretrieve_wrapper(tracer, wrapped, instance, args, kwargs):
61
+ async with start_as_current_span_async(
62
+ tracer=tracer, name=f"{TASK_NAME}.task"
63
+ ) as span:
64
+ span.set_attribute(
65
+ SpanAttributes.TRACELOOP_SPAN_KIND,
66
+ TraceloopSpanKindValues.TASK.value,
67
+ )
68
+ span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_NAME, TASK_NAME)
69
+
70
+ process_request(span, args, kwargs)
71
+ res = await wrapped(*args, **kwargs)
72
+ process_response(span, res)
73
+ return res
@@ -0,0 +1,72 @@
1
+ from importlib.metadata import version as package_version, PackageNotFoundError
2
+
3
+ from wrapt import wrap_function_wrapper
4
+
5
+ from opentelemetry.instrumentation.llamaindex.utils import (
6
+ _with_tracer_wrapper,
7
+ process_request,
8
+ process_response,
9
+ start_as_current_span_async,
10
+ )
11
+ from opentelemetry.semconv_ai import SpanAttributes, TraceloopSpanKindValues
12
+
13
+ V9_MODULE_NAME = "llama_index.response_synthesizers"
14
+ V10_MODULE_NAME = "llama_index.core.response_synthesizers"
15
+ V10_LEGACY_MODULE_NAME = "llama_index.legacy.response_synthesizers.base"
16
+
17
+ CLASS_NAME = "BaseSynthesizer"
18
+ TASK_NAME = "synthesize"
19
+
20
+
21
+ class BaseSynthesizerInstrumentor:
22
+ def __init__(self, tracer):
23
+ self._tracer = tracer
24
+
25
+ def instrument(self):
26
+ try:
27
+ package_version("llama-index-core")
28
+ self._instrument_module(V10_MODULE_NAME)
29
+ self._instrument_module(V10_LEGACY_MODULE_NAME)
30
+
31
+ except PackageNotFoundError:
32
+ self._instrument_module(V9_MODULE_NAME)
33
+
34
+ def _instrument_module(self, module_name):
35
+ wrap_function_wrapper(
36
+ module_name, f"{CLASS_NAME}.synthesize", synthesize_wrapper(self._tracer)
37
+ )
38
+ wrap_function_wrapper(
39
+ module_name, f"{CLASS_NAME}.asynthesize", asynthesize_wrapper(self._tracer)
40
+ )
41
+
42
+
43
+ @_with_tracer_wrapper
44
+ def synthesize_wrapper(tracer, wrapped, instance, args, kwargs):
45
+ with tracer.start_as_current_span(f"{TASK_NAME}.task") as span:
46
+ span.set_attribute(
47
+ SpanAttributes.TRACELOOP_SPAN_KIND,
48
+ TraceloopSpanKindValues.TASK.value,
49
+ )
50
+ span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_NAME, TASK_NAME)
51
+
52
+ process_request(span, args, kwargs)
53
+ res = wrapped(*args, **kwargs)
54
+ process_response(span, res)
55
+ return res
56
+
57
+
58
+ @_with_tracer_wrapper
59
+ async def asynthesize_wrapper(tracer, wrapped, instance, args, kwargs):
60
+ async with start_as_current_span_async(
61
+ tracer=tracer, name=f"{TASK_NAME}.task"
62
+ ) as span:
63
+ span.set_attribute(
64
+ SpanAttributes.TRACELOOP_SPAN_KIND,
65
+ TraceloopSpanKindValues.TASK.value,
66
+ )
67
+ span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_NAME, TASK_NAME)
68
+
69
+ process_request(span, args, kwargs)
70
+ res = await wrapped(*args, **kwargs)
71
+ process_response(span, res)
72
+ return res
@@ -0,0 +1,82 @@
1
+ from importlib.metadata import version as package_version, PackageNotFoundError
2
+
3
+ from wrapt import wrap_function_wrapper
4
+
5
+ from opentelemetry.instrumentation.llamaindex.utils import (
6
+ _with_tracer_wrapper,
7
+ process_request,
8
+ process_response,
9
+ start_as_current_span_async,
10
+ )
11
+ from opentelemetry.semconv_ai import SpanAttributes, TraceloopSpanKindValues
12
+
13
+
14
+ TO_INSTRUMENT = [
15
+ {
16
+ "class": "FunctionTool",
17
+ "v9_module": "llama_index.tools.function_tool",
18
+ "v10_module": "llama_index.core.tools.function_tool",
19
+ "v10_legacy_module": "llama_index.legacy.tools.function_tool",
20
+ },
21
+ {
22
+ "class": "QueryEngineTool",
23
+ "v9_module": "llama_index.tools.query_engine",
24
+ "v10_module": "llama_index.core.tools.query_engine",
25
+ "v10_legacy_module": "llama_index.legacy.tools.query_engine",
26
+ },
27
+ ]
28
+
29
+
30
+ class BaseToolInstrumentor:
31
+ def __init__(self, tracer):
32
+ self._tracer = tracer
33
+
34
+ def instrument(self):
35
+ for module in TO_INSTRUMENT:
36
+ try:
37
+ package_version("llama-index-core")
38
+ self._instrument_module(module["v10_module"], module["class"])
39
+ self._instrument_module(module["v10_legacy_module"], module["class"])
40
+
41
+ except PackageNotFoundError:
42
+ self._instrument_module(module["v9_module"], module["class"])
43
+
44
+ def _instrument_module(self, module_name, class_name):
45
+ wrap_function_wrapper(
46
+ module_name, f"{class_name}.call", query_wrapper(self._tracer)
47
+ )
48
+ wrap_function_wrapper(
49
+ module_name, f"{class_name}.acall", aquery_wrapper(self._tracer)
50
+ )
51
+
52
+
53
+ @_with_tracer_wrapper
54
+ def query_wrapper(tracer, wrapped, instance, args, kwargs):
55
+ name = instance.__class__.__name__
56
+ with tracer.start_as_current_span(f"{name}.tool") as span:
57
+ span.set_attribute(
58
+ SpanAttributes.TRACELOOP_SPAN_KIND,
59
+ TraceloopSpanKindValues.TOOL.value,
60
+ )
61
+ span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_NAME, name)
62
+
63
+ process_request(span, args, kwargs)
64
+ res = wrapped(*args, **kwargs)
65
+ process_response(span, res)
66
+ return res
67
+
68
+
69
+ @_with_tracer_wrapper
70
+ async def aquery_wrapper(tracer, wrapped, instance, args, kwargs):
71
+ name = instance.__class__.__name__
72
+ async with start_as_current_span_async(tracer=tracer, name=f"{name}.tool") as span:
73
+ span.set_attribute(
74
+ SpanAttributes.TRACELOOP_SPAN_KIND,
75
+ TraceloopSpanKindValues.TOOL.value,
76
+ )
77
+ span.set_attribute(SpanAttributes.TRACELOOP_ENTITY_NAME, name)
78
+
79
+ process_request(span, args, kwargs)
80
+ res = await wrapped(*args, **kwargs)
81
+ process_response(span, res)
82
+ return res
@@ -0,0 +1,9 @@
1
+ from typing import Optional
2
+
3
+ from opentelemetry._logs import Logger
4
+
5
+
6
+ class Config:
7
+ exception_logger = None
8
+ use_legacy_attributes = True
9
+ event_logger: Optional[Logger] = None