monocle-apptrace 0.3.0b4__tar.gz → 0.3.0b6__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.
Potentially problematic release.
This version of monocle-apptrace might be problematic. Click here for more details.
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/CHANGELOG.md +1 -1
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/PKG-INFO +2 -1
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/pyproject.toml +2 -1
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/__main__.py +19 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/exporters/azure/blob_exporter.py +7 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/exporters/monocle_exporters.py +5 -4
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/exporters/okahu/okahu_exporter.py +1 -1
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/common/constants.py +22 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/common/instrumentor.py +119 -39
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/common/span_handler.py +103 -44
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/common/utils.py +327 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/common/wrapper.py +90 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/common/wrapper_method.py +72 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/botocore/_helper.py +0 -31
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/botocore/handlers/botocore_span_handler.py +25 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/botocore/methods.py +6 -6
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/flask/_helper.py +29 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/flask/methods.py +13 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/haystack/entities/inference.py +1 -1
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/haystack/methods.py +2 -1
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/langchain/_helper.py +4 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/langchain/entities/inference.py +3 -2
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/langchain/methods.py +12 -6
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/langgraph/_helper.py +48 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/langgraph/entities/__init__.py +0 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/langgraph/entities/inference.py +56 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/langgraph/methods.py +14 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/llamaindex/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/llamaindex/_helper.py +37 -19
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/llamaindex/entities/__init__.py +0 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/llamaindex/entities/agent.py +47 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/llamaindex/entities/inference.py +5 -3
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/llamaindex/methods.py +15 -3
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/openai/__init__.py +0 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/openai/_helper.py +112 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/openai/entities/__init__.py +0 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/openai/entities/inference.py +71 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/openai/entities/retrieval.py +43 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/openai/methods.py +45 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/requests/__init__.py +4 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/requests/_helper.py +31 -0
- monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/requests/methods.py +12 -0
- monocle_apptrace-0.3.0b4/src/monocle_apptrace/instrumentation/common/utils.py +0 -171
- monocle_apptrace-0.3.0b4/src/monocle_apptrace/instrumentation/common/wrapper.py +0 -69
- monocle_apptrace-0.3.0b4/src/monocle_apptrace/instrumentation/common/wrapper_method.py +0 -45
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/.gitignore +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/CODEOWNERS.md +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/CODE_OF_CONDUCT.md +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/CONTRIBUTING.md +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/COPYRIGHT.template +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/LICENSE +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/MAINTAINER.md +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/Monocle_User_Guide.md +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/Monocle_committer_guide.md +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/Monocle_contributor_guide.md +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/NOTICE +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/README.md +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/SECURITY.md +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/README.md +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/exporters/aws/s3_exporter.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/exporters/aws/s3_exporter_opendal.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/exporters/azure/blob_exporter_opendal.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/exporters/base_exporter.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/exporters/exporter_processor.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/exporters/file_exporter.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/common/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/botocore/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/botocore/entities/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/botocore/entities/inference.py +0 -0
- {monocle_apptrace-0.3.0b4/src/monocle_apptrace/instrumentation/metamodel/haystack → monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/flask}/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4/src/monocle_apptrace/instrumentation/metamodel/haystack/entities → monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/haystack}/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/haystack/_helper.py +0 -0
- {monocle_apptrace-0.3.0b4/src/monocle_apptrace/instrumentation/metamodel/langchain → monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/haystack/entities}/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/haystack/entities/retrieval.py +0 -0
- {monocle_apptrace-0.3.0b4/src/monocle_apptrace/instrumentation/metamodel/langchain/entities → monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/langchain}/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4/src/monocle_apptrace/instrumentation/metamodel/llamaindex → monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/langchain/entities}/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/langchain/entities/retrieval.py +0 -0
- {monocle_apptrace-0.3.0b4/src/monocle_apptrace/instrumentation/metamodel/llamaindex/entities → monocle_apptrace-0.3.0b6/src/monocle_apptrace/instrumentation/metamodel/langgraph}/__init__.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/src/monocle_apptrace/instrumentation/metamodel/llamaindex/entities/retrieval.py +0 -0
- {monocle_apptrace-0.3.0b4 → monocle_apptrace-0.3.0b6}/tox.ini +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
## Version 0.3.
|
|
1
|
+
## Version 0.3.0b6 (2024-12-10)
|
|
2
2
|
|
|
3
3
|
- Add dev dependency for Mistral AI integration ([#81](https://github.com/monocle2ai/monocle/pull/81))
|
|
4
4
|
- Add VectorStore deployment URL capture support ([#80](https://github.com/monocle2ai/monocle/pull/80))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: monocle_apptrace
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.0b6
|
|
4
4
|
Summary: package with monocle genAI tracing
|
|
5
5
|
Project-URL: Homepage, https://github.com/monocle2ai/monocle
|
|
6
6
|
Project-URL: Issues, https://github.com/monocle2ai/monocle/issues
|
|
@@ -35,6 +35,7 @@ Requires-Dist: langchain-mistralai==0.1.13; extra == 'dev'
|
|
|
35
35
|
Requires-Dist: langchain-openai==0.1.8; extra == 'dev'
|
|
36
36
|
Requires-Dist: langchain==0.2.5; extra == 'dev'
|
|
37
37
|
Requires-Dist: langchainhub==0.1.21; extra == 'dev'
|
|
38
|
+
Requires-Dist: langgraph==0.2.68; extra == 'dev'
|
|
38
39
|
Requires-Dist: llama-index-embeddings-huggingface==0.2.0; extra == 'dev'
|
|
39
40
|
Requires-Dist: llama-index-llms-azure-openai==0.1.9; extra == 'dev'
|
|
40
41
|
Requires-Dist: llama-index-llms-mistralai==0.1.20; extra == 'dev'
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "monocle_apptrace"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.0b6"
|
|
8
8
|
authors = []
|
|
9
9
|
description = "package with monocle genAI tracing"
|
|
10
10
|
readme = "README.md"
|
|
@@ -71,6 +71,7 @@ dev = [
|
|
|
71
71
|
'chromadb==0.4.22',
|
|
72
72
|
'flask',
|
|
73
73
|
'opentelemetry-instrumentation-flask',
|
|
74
|
+
'langgraph==0.2.68',
|
|
74
75
|
'opendal==0.45.14'
|
|
75
76
|
]
|
|
76
77
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import sys, os
|
|
2
|
+
import runpy
|
|
3
|
+
from monocle_apptrace.instrumentation.common.instrumentor import setup_monocle_telemetry
|
|
4
|
+
|
|
5
|
+
def main():
|
|
6
|
+
if len(sys.argv) < 2 or not sys.argv[1].endswith(".py"):
|
|
7
|
+
print("Usage: python -m monocle_apptrace <your-main-module-file> <args>")
|
|
8
|
+
sys.exit(1)
|
|
9
|
+
file_name = os.path.basename(sys.argv[1])
|
|
10
|
+
workflow_name = file_name[:-3]
|
|
11
|
+
setup_monocle_telemetry(workflow_name=workflow_name)
|
|
12
|
+
sys.argv.pop(0)
|
|
13
|
+
|
|
14
|
+
try:
|
|
15
|
+
runpy.run_path(path_name=sys.argv[0], run_name="__main__")
|
|
16
|
+
except Exception as e:
|
|
17
|
+
print(e)
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
main()
|
|
@@ -11,6 +11,7 @@ from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
|
|
|
11
11
|
from typing import Sequence
|
|
12
12
|
from monocle_apptrace.exporters.base_exporter import SpanExporterBase
|
|
13
13
|
import json
|
|
14
|
+
from monocle_apptrace.instrumentation.common.constants import MONOCLE_SDK_VERSION
|
|
14
15
|
logger = logging.getLogger(__name__)
|
|
15
16
|
|
|
16
17
|
class AzureBlobSpanExporter(SpanExporterBase):
|
|
@@ -72,6 +73,12 @@ class AzureBlobSpanExporter(SpanExporterBase):
|
|
|
72
73
|
"""The actual async export logic is run here."""
|
|
73
74
|
# Add spans to the export queue
|
|
74
75
|
for span in spans:
|
|
76
|
+
# Azure blob library has a check to generate it's own span if OpenTelemetry is loaded and Azure trace package is installed (just pip install azure-trace-opentelemetry)
|
|
77
|
+
# With Monocle,OpenTelemetry is always loaded. If the Azure trace package is installed, then it triggers the blob trace generation on every blob operation.
|
|
78
|
+
# Thus, the Monocle span write ends up generating a blob span which again comes back to the exporter .. and would result in an infinite loop.
|
|
79
|
+
# To avoid this, we check if the span has the Monocle SDK version attribute and skip it if it doesn't. That way the blob span genearted by Azure library are not exported.
|
|
80
|
+
if not span.attributes.get(MONOCLE_SDK_VERSION):
|
|
81
|
+
continue # TODO: All exporters to use same base class and check it there
|
|
75
82
|
self.export_queue.append(span)
|
|
76
83
|
if len(self.export_queue) >= self.max_batch_size:
|
|
77
84
|
await self.__export_spans()
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
from typing import Dict, Any, List
|
|
2
2
|
import os
|
|
3
|
-
import
|
|
3
|
+
import logging
|
|
4
4
|
from importlib import import_module
|
|
5
5
|
from opentelemetry.sdk.trace.export import SpanExporter, ConsoleSpanExporter
|
|
6
6
|
from monocle_apptrace.exporters.file_exporter import FileSpanExporter
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
7
8
|
|
|
8
9
|
monocle_exporters: Dict[str, Any] = {
|
|
9
10
|
"s3": {"module": "monocle_apptrace.exporters.aws.s3_exporter", "class": "S3SpanExporter"},
|
|
@@ -25,21 +26,21 @@ def get_monocle_exporter() -> List[SpanExporter]:
|
|
|
25
26
|
try:
|
|
26
27
|
exporter_class_path = monocle_exporters[exporter_name]
|
|
27
28
|
except KeyError:
|
|
28
|
-
|
|
29
|
+
logger.debug(f"Unsupported Monocle span exporter '{exporter_name}', skipping.")
|
|
29
30
|
continue
|
|
30
31
|
try:
|
|
31
32
|
exporter_module = import_module(exporter_class_path["module"])
|
|
32
33
|
exporter_class = getattr(exporter_module, exporter_class_path["class"])
|
|
33
34
|
exporters.append(exporter_class())
|
|
34
35
|
except Exception as ex:
|
|
35
|
-
|
|
36
|
+
logger.debug(
|
|
36
37
|
f"Unable to initialize Monocle span exporter '{exporter_name}', error: {ex}. Using ConsoleSpanExporter as a fallback.")
|
|
37
38
|
exporters.append(ConsoleSpanExporter())
|
|
38
39
|
continue
|
|
39
40
|
|
|
40
41
|
# If no exporters were created, default to FileSpanExporter
|
|
41
42
|
if not exporters:
|
|
42
|
-
|
|
43
|
+
logger.debug("No valid Monocle span exporters configured. Defaulting to FileSpanExporter.")
|
|
43
44
|
exporters.append(FileSpanExporter())
|
|
44
45
|
|
|
45
46
|
return exporters
|
|
@@ -83,7 +83,7 @@ class OkahuSpanExporter(SpanExporter):
|
|
|
83
83
|
result.text,
|
|
84
84
|
)
|
|
85
85
|
return SpanExportResult.FAILURE
|
|
86
|
-
logger.
|
|
86
|
+
logger.debug("spans successfully exported to okahu")
|
|
87
87
|
return SpanExportResult.SUCCESS
|
|
88
88
|
except ReadTimeout as e:
|
|
89
89
|
logger.warning("Trace export timed out: %s", str(e))
|
|
@@ -37,6 +37,20 @@ service_name_map = {
|
|
|
37
37
|
GITHUB_CODESPACE_SERVICE_NAME: GITHUB_CODESPACE_IDENTIFIER_ENV_NAME
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
|
|
41
|
+
llm_type_map = {
|
|
42
|
+
"sagemakerendpoint": "aws_sagemaker",
|
|
43
|
+
"azureopenai": "azure_openai",
|
|
44
|
+
"openai": "openai",
|
|
45
|
+
"chatopenai": "openai",
|
|
46
|
+
"azurechatopenai": "azure_openai",
|
|
47
|
+
"bedrock": "aws_bedrock",
|
|
48
|
+
"sagemakerllm": "aws_sagemaker",
|
|
49
|
+
"chatbedrock": "aws_bedrock",
|
|
50
|
+
"openaigenerator": "openai",
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
MONOCLE_INSTRUMENTOR = "monocle_apptrace"
|
|
40
54
|
WORKFLOW_TYPE_KEY = "workflow_type"
|
|
41
55
|
DATA_INPUT_KEY = "data.input"
|
|
42
56
|
DATA_OUTPUT_KEY = "data.output"
|
|
@@ -47,3 +61,11 @@ RESPONSE = "response"
|
|
|
47
61
|
SESSION_PROPERTIES_KEY = "session"
|
|
48
62
|
INFRA_SERVICE_KEY = "infra_service_name"
|
|
49
63
|
META_DATA = 'metadata'
|
|
64
|
+
MONOCLE_SCOPE_NAME_PREFIX = "monocle.scope."
|
|
65
|
+
SCOPE_METHOD_LIST = 'MONOCLE_SCOPE_METHODS'
|
|
66
|
+
SCOPE_METHOD_FILE = 'monocle_scopes.json'
|
|
67
|
+
SCOPE_CONFIG_PATH = 'MONOCLE_SCOPE_CONFIG_PATH'
|
|
68
|
+
TRACE_PROPOGATION_URLS = "MONOCLE_TRACE_PROPAGATATION_URLS"
|
|
69
|
+
WORKFLOW_TYPE_KEY = "monocle.workflow_type"
|
|
70
|
+
WORKFLOW_TYPE_GENERIC = "workflow.generic"
|
|
71
|
+
MONOCLE_SDK_VERSION = "monocle_apptrace.version"
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import inspect
|
|
2
3
|
from typing import Collection, Dict, List, Union
|
|
3
4
|
import random
|
|
4
5
|
import uuid
|
|
5
6
|
from opentelemetry import trace
|
|
7
|
+
from contextlib import contextmanager
|
|
6
8
|
from opentelemetry.context import attach, get_value, set_value, get_current, detach
|
|
7
9
|
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
|
|
8
10
|
from opentelemetry.instrumentation.utils import unwrap
|
|
@@ -13,14 +15,20 @@ from opentelemetry.sdk.trace import Span, TracerProvider
|
|
|
13
15
|
from opentelemetry.sdk.trace.export import BatchSpanProcessor, SpanProcessor
|
|
14
16
|
from opentelemetry.trace import get_tracer
|
|
15
17
|
from wrapt import wrap_function_wrapper
|
|
16
|
-
from opentelemetry.trace.propagation import set_span_in_context
|
|
18
|
+
from opentelemetry.trace.propagation import set_span_in_context, _SPAN_KEY
|
|
17
19
|
from monocle_apptrace.exporters.monocle_exporters import get_monocle_exporter
|
|
18
20
|
from monocle_apptrace.instrumentation.common.span_handler import SpanHandler
|
|
19
21
|
from monocle_apptrace.instrumentation.common.wrapper_method import (
|
|
20
22
|
DEFAULT_METHODS_LIST,
|
|
21
23
|
WrapperMethod,
|
|
24
|
+
MONOCLE_SPAN_HANDLERS
|
|
22
25
|
)
|
|
23
|
-
|
|
26
|
+
from monocle_apptrace.instrumentation.common.wrapper import scope_wrapper, ascope_wrapper
|
|
27
|
+
from monocle_apptrace.instrumentation.common.utils import (
|
|
28
|
+
set_scope, remove_scope, http_route_handler, load_scopes, async_wrapper, http_async_route_handler
|
|
29
|
+
)
|
|
30
|
+
from monocle_apptrace.instrumentation.common.constants import MONOCLE_INSTRUMENTOR, WORKFLOW_TYPE_KEY
|
|
31
|
+
from functools import wraps
|
|
24
32
|
logger = logging.getLogger(__name__)
|
|
25
33
|
|
|
26
34
|
SESSION_PROPERTIES_KEY = "session"
|
|
@@ -29,8 +37,6 @@ _instruments = ()
|
|
|
29
37
|
|
|
30
38
|
monocle_tracer_provider: TracerProvider = None
|
|
31
39
|
|
|
32
|
-
MONOCLE_INSTRUMENTOR = "monocle_apptrace"
|
|
33
|
-
|
|
34
40
|
class MonocleInstrumentor(BaseInstrumentor):
|
|
35
41
|
workflow_name: str = ""
|
|
36
42
|
user_wrapper_methods: list[Union[dict,WrapperMethod]] = []
|
|
@@ -45,17 +51,36 @@ class MonocleInstrumentor(BaseInstrumentor):
|
|
|
45
51
|
union_with_default_methods: bool = True
|
|
46
52
|
) -> None:
|
|
47
53
|
self.user_wrapper_methods = user_wrapper_methods or []
|
|
48
|
-
self.handlers = handlers
|
|
54
|
+
self.handlers = handlers
|
|
55
|
+
if self.handlers is not None:
|
|
56
|
+
for key, val in MONOCLE_SPAN_HANDLERS.items():
|
|
57
|
+
if key not in self.handlers:
|
|
58
|
+
self.handlers[key] = val
|
|
59
|
+
else:
|
|
60
|
+
self.handlers = MONOCLE_SPAN_HANDLERS
|
|
49
61
|
self.union_with_default_methods = union_with_default_methods
|
|
50
62
|
super().__init__()
|
|
51
63
|
|
|
64
|
+
def get_instrumentor(self, tracer):
|
|
65
|
+
def instrumented_endpoint_invoke(to_wrap,wrapped, span_name, instance,fn):
|
|
66
|
+
@wraps(fn)
|
|
67
|
+
def with_instrumentation(*args, **kwargs):
|
|
68
|
+
handler = SpanHandler()
|
|
69
|
+
with tracer.start_as_current_span(span_name) as span:
|
|
70
|
+
response = fn(*args, **kwargs)
|
|
71
|
+
handler.hydrate_span(to_wrap, wrapped=wrapped, instance=instance, args=args, kwargs=kwargs,
|
|
72
|
+
result=response, span=span)
|
|
73
|
+
return response
|
|
74
|
+
|
|
75
|
+
return with_instrumentation
|
|
76
|
+
return instrumented_endpoint_invoke
|
|
77
|
+
|
|
52
78
|
def instrumentation_dependencies(self) -> Collection[str]:
|
|
53
79
|
return _instruments
|
|
54
80
|
|
|
55
81
|
def _instrument(self, **kwargs):
|
|
56
82
|
tracer_provider: TracerProvider = kwargs.get("tracer_provider")
|
|
57
|
-
|
|
58
|
-
monocle_tracer_provider = tracer_provider
|
|
83
|
+
set_tracer_provider(tracer_provider)
|
|
59
84
|
tracer = get_tracer(instrumenting_module_name=MONOCLE_INSTRUMENTOR, tracer_provider=tracer_provider)
|
|
60
85
|
|
|
61
86
|
final_method_list = []
|
|
@@ -67,6 +92,13 @@ class MonocleInstrumentor(BaseInstrumentor):
|
|
|
67
92
|
final_method_list.append(method)
|
|
68
93
|
elif isinstance(method, WrapperMethod):
|
|
69
94
|
final_method_list.append(method.to_dict())
|
|
95
|
+
|
|
96
|
+
for method in load_scopes():
|
|
97
|
+
if method.get('async', False):
|
|
98
|
+
method['wrapper_method'] = ascope_wrapper
|
|
99
|
+
else:
|
|
100
|
+
method['wrapper_method'] = scope_wrapper
|
|
101
|
+
final_method_list.append(method)
|
|
70
102
|
|
|
71
103
|
for method_config in final_method_list:
|
|
72
104
|
target_package = method_config.get("package", None)
|
|
@@ -77,6 +109,10 @@ class MonocleInstrumentor(BaseInstrumentor):
|
|
|
77
109
|
handler_key = method_config.get("span_handler",'default')
|
|
78
110
|
try:
|
|
79
111
|
handler = self.handlers.get(handler_key)
|
|
112
|
+
if not handler:
|
|
113
|
+
logger.warning("incorrect or empty handler falling back to default handler")
|
|
114
|
+
handler = self.handlers.get('default')
|
|
115
|
+
handler.set_instrumentor(self.get_instrumentor(tracer))
|
|
80
116
|
wrap_function_wrapper(
|
|
81
117
|
target_package,
|
|
82
118
|
f"{target_object}.{target_method}" if target_object else target_method,
|
|
@@ -108,6 +144,14 @@ class MonocleInstrumentor(BaseInstrumentor):
|
|
|
108
144
|
object:{wrap_object},
|
|
109
145
|
method:{wrap_method}""")
|
|
110
146
|
|
|
147
|
+
def set_tracer_provider(tracer_provider: TracerProvider):
|
|
148
|
+
global monocle_tracer_provider
|
|
149
|
+
monocle_tracer_provider = tracer_provider
|
|
150
|
+
|
|
151
|
+
def get_tracer_provider() -> TracerProvider:
|
|
152
|
+
global monocle_tracer_provider
|
|
153
|
+
return monocle_tracer_provider
|
|
154
|
+
|
|
111
155
|
def setup_monocle_telemetry(
|
|
112
156
|
workflow_name: str,
|
|
113
157
|
span_processors: List[SpanProcessor] = None,
|
|
@@ -119,7 +163,7 @@ def setup_monocle_telemetry(
|
|
|
119
163
|
})
|
|
120
164
|
exporters = get_monocle_exporter()
|
|
121
165
|
span_processors = span_processors or [BatchSpanProcessor(exporter) for exporter in exporters]
|
|
122
|
-
|
|
166
|
+
set_tracer_provider(TracerProvider(resource=resource))
|
|
123
167
|
attach(set_value("workflow_name", workflow_name))
|
|
124
168
|
tracer_provider_default = trace.get_tracer_provider()
|
|
125
169
|
provider_type = type(tracer_provider_default).__name__
|
|
@@ -129,14 +173,14 @@ def setup_monocle_telemetry(
|
|
|
129
173
|
if not is_proxy_provider:
|
|
130
174
|
tracer_provider_default.add_span_processor(processor)
|
|
131
175
|
else:
|
|
132
|
-
|
|
176
|
+
get_tracer_provider().add_span_processor(processor)
|
|
133
177
|
if is_proxy_provider:
|
|
134
|
-
trace.set_tracer_provider(
|
|
178
|
+
trace.set_tracer_provider(get_tracer_provider())
|
|
135
179
|
instrumentor = MonocleInstrumentor(user_wrapper_methods=wrapper_methods or [],
|
|
136
180
|
handlers=span_handlers, union_with_default_methods = union_with_default_methods)
|
|
137
181
|
# instrumentor.app_name = workflow_name
|
|
138
182
|
if not instrumentor.is_instrumented_by_opentelemetry:
|
|
139
|
-
instrumentor.instrument(trace_provider=
|
|
183
|
+
instrumentor.instrument(trace_provider=get_tracer_provider())
|
|
140
184
|
|
|
141
185
|
return instrumentor
|
|
142
186
|
|
|
@@ -151,40 +195,30 @@ def on_processor_start(span: Span, parent_context):
|
|
|
151
195
|
def set_context_properties(properties: dict) -> None:
|
|
152
196
|
attach(set_value(SESSION_PROPERTIES_KEY, properties))
|
|
153
197
|
|
|
154
|
-
|
|
155
|
-
def propagate_trace_id(traceId = "", use_trace_context = False):
|
|
198
|
+
def start_trace():
|
|
156
199
|
try:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
tracer.id_generator = FixedIdGenerator(uuid.UUID(traceId).int)
|
|
164
|
-
|
|
165
|
-
span = tracer.start_span(name = "parent_placeholder_span", context= _parent_span_context)
|
|
166
|
-
updated_span_context = set_span_in_context(span=span, context= _parent_span_context)
|
|
167
|
-
updated_span_context = set_value("root_span_id", span.get_span_context().span_id, updated_span_context)
|
|
168
|
-
token = attach(updated_span_context)
|
|
169
|
-
|
|
170
|
-
span.end()
|
|
171
|
-
tracer.id_generator = initial_id_generator
|
|
200
|
+
tracer = get_tracer(instrumenting_module_name= MONOCLE_INSTRUMENTOR, tracer_provider= get_tracer_provider())
|
|
201
|
+
span = tracer.start_span(name = "workflow")
|
|
202
|
+
updated_span_context = set_span_in_context(span=span)
|
|
203
|
+
SpanHandler.set_default_monocle_attributes(span)
|
|
204
|
+
SpanHandler.set_workflow_properties(span)
|
|
205
|
+
token = SpanHandler.attach_workflow_type(context=updated_span_context)
|
|
172
206
|
return token
|
|
173
207
|
except:
|
|
174
|
-
logger.warning("Failed to
|
|
175
|
-
|
|
208
|
+
logger.warning("Failed to start trace")
|
|
209
|
+
return None
|
|
176
210
|
|
|
177
|
-
|
|
178
|
-
def propagate_trace_id_from_traceparent():
|
|
179
|
-
propagate_trace_id(use_trace_context = True)
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
def stop_propagate_trace_id(token) -> None:
|
|
211
|
+
def stop_trace(token) -> None:
|
|
183
212
|
try:
|
|
184
|
-
|
|
213
|
+
_parent_span_context = get_current()
|
|
214
|
+
if _parent_span_context is not None:
|
|
215
|
+
parent_span: Span = _parent_span_context.get(_SPAN_KEY, None)
|
|
216
|
+
if parent_span is not None:
|
|
217
|
+
parent_span.end()
|
|
218
|
+
if token is not None:
|
|
219
|
+
SpanHandler.detach_workflow_type(token)
|
|
185
220
|
except:
|
|
186
|
-
logger.warning("Failed to stop
|
|
187
|
-
|
|
221
|
+
logger.warning("Failed to stop trace")
|
|
188
222
|
|
|
189
223
|
def is_valid_trace_id_uuid(traceId: str) -> bool:
|
|
190
224
|
try:
|
|
@@ -194,6 +228,52 @@ def is_valid_trace_id_uuid(traceId: str) -> bool:
|
|
|
194
228
|
pass
|
|
195
229
|
return False
|
|
196
230
|
|
|
231
|
+
def start_scope(scope_name: str, scope_value:str = None) -> object:
|
|
232
|
+
return set_scope(scope_name, scope_value)
|
|
233
|
+
|
|
234
|
+
def stop_scope(token:object) -> None:
|
|
235
|
+
remove_scope(token)
|
|
236
|
+
return
|
|
237
|
+
|
|
238
|
+
@contextmanager
|
|
239
|
+
def monocle_trace_scope(scope_name: str, scope_value:str = None):
|
|
240
|
+
token = start_scope(scope_name, scope_value)
|
|
241
|
+
try:
|
|
242
|
+
yield
|
|
243
|
+
finally:
|
|
244
|
+
stop_scope(token)
|
|
245
|
+
|
|
246
|
+
def monocle_trace_scope_method(scope_name: str):
|
|
247
|
+
def decorator(func):
|
|
248
|
+
if inspect.iscoroutinefunction(func):
|
|
249
|
+
@wraps(func)
|
|
250
|
+
async def wrapper(*args, **kwargs):
|
|
251
|
+
result = async_wrapper(func, scope_name, None, *args, **kwargs)
|
|
252
|
+
return result
|
|
253
|
+
return wrapper
|
|
254
|
+
else:
|
|
255
|
+
@wraps(func)
|
|
256
|
+
def wrapper(*args, **kwargs):
|
|
257
|
+
token = start_scope(scope_name)
|
|
258
|
+
try:
|
|
259
|
+
result = func(*args, **kwargs)
|
|
260
|
+
return result
|
|
261
|
+
finally:
|
|
262
|
+
stop_scope(token)
|
|
263
|
+
return wrapper
|
|
264
|
+
return decorator
|
|
265
|
+
|
|
266
|
+
def monocle_trace_http_route(func):
|
|
267
|
+
if inspect.iscoroutinefunction(func):
|
|
268
|
+
@wraps(func)
|
|
269
|
+
async def wrapper(*args, **kwargs):
|
|
270
|
+
return http_async_route_handler(func, *args, **kwargs)
|
|
271
|
+
return wrapper
|
|
272
|
+
else:
|
|
273
|
+
@wraps(func)
|
|
274
|
+
def wrapper(*args, **kwargs):
|
|
275
|
+
return http_route_handler(func, *args, **kwargs)
|
|
276
|
+
return wrapper
|
|
197
277
|
|
|
198
278
|
class FixedIdGenerator(id_generator.IdGenerator):
|
|
199
279
|
def __init__(
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import os
|
|
3
3
|
from importlib.metadata import version
|
|
4
|
-
from opentelemetry.context import
|
|
5
|
-
from opentelemetry.context import get_value
|
|
4
|
+
from opentelemetry.context import get_value, set_value, attach, detach
|
|
6
5
|
from opentelemetry.sdk.trace import Span
|
|
7
6
|
|
|
8
7
|
from monocle_apptrace.instrumentation.common.constants import (
|
|
9
8
|
QUERY,
|
|
10
9
|
service_name_map,
|
|
11
10
|
service_type_map,
|
|
11
|
+
MONOCLE_SDK_VERSION
|
|
12
12
|
)
|
|
13
|
-
from monocle_apptrace.instrumentation.common.utils import set_attribute
|
|
13
|
+
from monocle_apptrace.instrumentation.common.utils import set_attribute, get_scopes
|
|
14
|
+
from monocle_apptrace.instrumentation.common.constants import WORKFLOW_TYPE_KEY, WORKFLOW_TYPE_GENERIC
|
|
14
15
|
|
|
15
16
|
logger = logging.getLogger(__name__)
|
|
16
17
|
|
|
@@ -20,41 +21,61 @@ WORKFLOW_TYPE_MAP = {
|
|
|
20
21
|
"haystack": "workflow.haystack"
|
|
21
22
|
}
|
|
22
23
|
|
|
24
|
+
class SpanHandler:
|
|
23
25
|
|
|
26
|
+
def __init__(self,instrumentor=None):
|
|
27
|
+
self.instrumentor=instrumentor
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
def set_instrumentor(self, instrumentor):
|
|
30
|
+
self.instrumentor = instrumentor
|
|
26
31
|
|
|
27
32
|
def validate(self, to_wrap, wrapped, instance, args, kwargs):
|
|
28
33
|
pass
|
|
29
34
|
|
|
30
|
-
def
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
def pre_tracing(self, to_wrap, wrapped, instance, args, kwargs):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
def post_tracing(self, to_wrap, wrapped, instance, args, kwargs, return_value):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
def skip_span(self, to_wrap, wrapped, instance, args, kwargs) -> bool:
|
|
42
|
+
# If this is a workflow span type and a workflow span is already generated, then skip generating this span
|
|
43
|
+
if to_wrap.get('span_type') == "workflow" and self.is_workflow_span_active():
|
|
44
|
+
return True
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
def pre_task_processing(self, to_wrap, wrapped, instance, args,kwargs, span):
|
|
37
48
|
if "pipeline" in to_wrap['package']:
|
|
38
49
|
set_attribute(QUERY, args[0]['prompt_builder']['question'])
|
|
39
50
|
|
|
51
|
+
@staticmethod
|
|
52
|
+
def set_default_monocle_attributes(span: Span):
|
|
53
|
+
""" Set default monocle attributes for all spans """
|
|
54
|
+
try:
|
|
55
|
+
sdk_version = version("monocle_apptrace")
|
|
56
|
+
span.set_attribute(MONOCLE_SDK_VERSION, sdk_version)
|
|
57
|
+
except Exception as e:
|
|
58
|
+
logger.warning("Exception finding monocle-apptrace version.")
|
|
59
|
+
for scope_key, scope_value in get_scopes().items():
|
|
60
|
+
span.set_attribute(f"scope.{scope_key}", scope_value)
|
|
40
61
|
|
|
62
|
+
@staticmethod
|
|
63
|
+
def set_workflow_properties(span: Span, to_wrap = None):
|
|
64
|
+
""" Set attributes of workflow if this is a root span"""
|
|
65
|
+
SpanHandler.set_workflow_attributes(to_wrap, span)
|
|
66
|
+
SpanHandler.set_app_hosting_identifier_attribute(span)
|
|
41
67
|
|
|
42
68
|
def post_task_processing(self, to_wrap, wrapped, instance, args, kwargs, result, span):
|
|
43
69
|
pass
|
|
44
70
|
|
|
45
|
-
def set_context_properties(self, to_wrap, wrapped, instance, args, kwargs):
|
|
46
|
-
pass
|
|
47
|
-
|
|
48
71
|
def hydrate_span(self, to_wrap, wrapped, instance, args, kwargs, result, span):
|
|
49
72
|
self.hydrate_attributes(to_wrap, wrapped, instance, args, kwargs, result, span)
|
|
50
73
|
self.hydrate_events(to_wrap, wrapped, instance, args, kwargs, result, span)
|
|
51
74
|
|
|
52
75
|
def hydrate_attributes(self, to_wrap, wrapped, instance, args, kwargs, result, span):
|
|
53
76
|
span_index = 0
|
|
54
|
-
if
|
|
55
|
-
span_index
|
|
56
|
-
span_index += self.set_app_hosting_identifier_attribute(span, span_index+1)
|
|
57
|
-
|
|
77
|
+
if SpanHandler.is_root_span(span):
|
|
78
|
+
span_index = 2 # root span will have workflow and hosting entities pre-populated
|
|
58
79
|
if 'output_processor' in to_wrap and to_wrap["output_processor"] is not None:
|
|
59
80
|
output_processor=to_wrap['output_processor']
|
|
60
81
|
if 'type' in output_processor:
|
|
@@ -72,16 +93,21 @@ class SpanHandler:
|
|
|
72
93
|
try:
|
|
73
94
|
arguments = {"instance":instance, "args":args, "kwargs":kwargs, "result":result}
|
|
74
95
|
result = accessor(arguments)
|
|
75
|
-
if result and isinstance(result, str):
|
|
96
|
+
if result and isinstance(result, (str, list)):
|
|
76
97
|
span.set_attribute(attribute_name, result)
|
|
77
98
|
except Exception as e:
|
|
78
99
|
logger.debug(f"Error processing accessor: {e}")
|
|
79
100
|
else:
|
|
80
|
-
logger.
|
|
101
|
+
logger.debug(f"{' and '.join([key for key in ['attribute', 'accessor'] if not processor.get(key)])} not found or incorrect in entity JSON")
|
|
81
102
|
span_index += 1
|
|
82
103
|
else:
|
|
83
|
-
logger.
|
|
104
|
+
logger.debug("attributes not found or incorrect written in entity json")
|
|
84
105
|
|
|
106
|
+
# set scopes as attributes by calling get_scopes()
|
|
107
|
+
# scopes is a Mapping[str:object], iterate directly with .items()
|
|
108
|
+
for scope_key, scope_value in get_scopes().items():
|
|
109
|
+
span.set_attribute(f"scope.{scope_key}", scope_value)
|
|
110
|
+
|
|
85
111
|
if span_index > 0:
|
|
86
112
|
span.set_attribute("entity.count", span_index)
|
|
87
113
|
|
|
@@ -109,46 +135,79 @@ class SpanHandler:
|
|
|
109
135
|
logger.debug(f"Error evaluating accessor for attribute '{attribute_key}': {e}")
|
|
110
136
|
span.add_event(name=event_name, attributes=event_attributes)
|
|
111
137
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
workflow_name = self.get_workflow_name(span=span)
|
|
138
|
+
@staticmethod
|
|
139
|
+
def set_workflow_attributes(to_wrap, span: Span):
|
|
140
|
+
span_index = 1
|
|
141
|
+
workflow_name = SpanHandler.get_workflow_name(span=span)
|
|
117
142
|
if workflow_name:
|
|
118
143
|
span.set_attribute("span.type", "workflow")
|
|
119
144
|
span.set_attribute(f"entity.{span_index}.name", workflow_name)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
if not
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
145
|
+
workflow_type = SpanHandler.get_workflow_type(to_wrap)
|
|
146
|
+
span.set_attribute(f"entity.{span_index}.type", workflow_type)
|
|
147
|
+
|
|
148
|
+
@staticmethod
|
|
149
|
+
def get_workflow_type(to_wrap):
|
|
150
|
+
# workflow type
|
|
151
|
+
workflow_type = WORKFLOW_TYPE_GENERIC
|
|
152
|
+
if to_wrap is not None:
|
|
153
|
+
package_name = to_wrap.get('package')
|
|
154
|
+
for (package, framework_workflow_type) in WORKFLOW_TYPE_MAP.items():
|
|
155
|
+
if (package_name is not None and package in package_name):
|
|
156
|
+
workflow_type = framework_workflow_type
|
|
157
|
+
break
|
|
158
|
+
return workflow_type
|
|
159
|
+
|
|
160
|
+
def set_app_hosting_identifier_attribute(span):
|
|
161
|
+
span_index = 2
|
|
133
162
|
# Search env to indentify the infra service type, if found check env for service name if possible
|
|
163
|
+
span.set_attribute(f"entity.{span_index}.type", f"app_hosting.generic")
|
|
164
|
+
span.set_attribute(f"entity.{span_index}.name", "generic")
|
|
134
165
|
for type_env, type_name in service_type_map.items():
|
|
135
166
|
if type_env in os.environ:
|
|
136
|
-
return_value = 1
|
|
137
167
|
span.set_attribute(f"entity.{span_index}.type", f"app_hosting.{type_name}")
|
|
138
168
|
entity_name_env = service_name_map.get(type_name, "unknown")
|
|
139
169
|
span.set_attribute(f"entity.{span_index}.name", os.environ.get(entity_name_env, "generic"))
|
|
140
|
-
return return_value
|
|
141
170
|
|
|
142
|
-
|
|
171
|
+
@staticmethod
|
|
172
|
+
def get_workflow_name(span: Span) -> str:
|
|
143
173
|
try:
|
|
144
174
|
return get_value("workflow_name") or span.resource.attributes.get("service.name")
|
|
145
175
|
except Exception as e:
|
|
146
176
|
logger.exception(f"Error getting workflow name: {e}")
|
|
147
177
|
return None
|
|
148
178
|
|
|
149
|
-
|
|
179
|
+
@staticmethod
|
|
180
|
+
def is_root_span(curr_span: Span) -> bool:
|
|
150
181
|
try:
|
|
151
182
|
if curr_span is not None and hasattr(curr_span, "parent"):
|
|
152
|
-
return curr_span.parent is None
|
|
183
|
+
return curr_span.parent is None
|
|
153
184
|
except Exception as e:
|
|
154
185
|
logger.warning(f"Error finding root span: {e}")
|
|
186
|
+
|
|
187
|
+
def is_non_workflow_root_span(self, curr_span: Span, to_wrap) -> bool:
|
|
188
|
+
return SpanHandler.is_root_span(curr_span) and to_wrap.get("span_type") != "workflow"
|
|
189
|
+
|
|
190
|
+
def is_workflow_span_active(self):
|
|
191
|
+
return get_value(WORKFLOW_TYPE_KEY) is not None
|
|
192
|
+
|
|
193
|
+
@staticmethod
|
|
194
|
+
def attach_workflow_type(to_wrap=None, context=None):
|
|
195
|
+
token = None
|
|
196
|
+
if to_wrap:
|
|
197
|
+
if to_wrap.get('span_type') == "workflow":
|
|
198
|
+
token = attach(set_value(WORKFLOW_TYPE_KEY,
|
|
199
|
+
SpanHandler.get_workflow_type(to_wrap), context))
|
|
200
|
+
else:
|
|
201
|
+
token = attach(set_value(WORKFLOW_TYPE_KEY, WORKFLOW_TYPE_GENERIC, context))
|
|
202
|
+
return token
|
|
203
|
+
|
|
204
|
+
@staticmethod
|
|
205
|
+
def detach_workflow_type(token):
|
|
206
|
+
if token:
|
|
207
|
+
return detach(token)
|
|
208
|
+
|
|
209
|
+
class NonFrameworkSpanHandler(SpanHandler):
|
|
210
|
+
|
|
211
|
+
# If the language framework is being executed, then skip generating direct openAI spans
|
|
212
|
+
def skip_span(self, to_wrap, wrapped, instance, args, kwargs) -> bool:
|
|
213
|
+
return get_value(WORKFLOW_TYPE_KEY) in WORKFLOW_TYPE_MAP.values()
|