cavisson-pythonagent 0.0.1__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.
- cavisson_pythonagent-0.0.1.dist-info/METADATA +32 -0
- cavisson_pythonagent-0.0.1.dist-info/RECORD +180 -0
- cavisson_pythonagent-0.0.1.dist-info/WHEEL +5 -0
- cavisson_pythonagent-0.0.1.dist-info/licenses/LICENSE +19 -0
- cavisson_pythonagent-0.0.1.dist-info/top_level.txt +1 -0
- pythonagent/__init__.py +22 -0
- pythonagent/agent/__init__.py +219 -0
- pythonagent/agent/internal/__init__.py +1 -0
- pythonagent/agent/internal/agent.py +1651 -0
- pythonagent/agent/internal/framesinfo.py +152 -0
- pythonagent/agent/internal/heap_dump.py +39 -0
- pythonagent/agent/internal/intercept_module.py +70 -0
- pythonagent/agent/internal/logs.py +122 -0
- pythonagent/agent/internal/metadata/__init__.py +0 -0
- pythonagent/agent/internal/metadata/agent_meta_data.py +276 -0
- pythonagent/agent/internal/proc_compat.py +75 -0
- pythonagent/agent/internal/profile.py +47 -0
- pythonagent/agent/internal/provider.py +83 -0
- pythonagent/agent/internal/thread_dump.py +85 -0
- pythonagent/agent/internal/udp.py +245 -0
- pythonagent/agent/internal/udp_message.py +800 -0
- pythonagent/agent/probes/Instrumentation/__init__.py +340 -0
- pythonagent/agent/probes/Instrumentation/find.py +243 -0
- pythonagent/agent/probes/Instrumentation/module_version_resolver.py +155 -0
- pythonagent/agent/probes/Instrumentation/new_parser.py +64 -0
- pythonagent/agent/probes/Instrumentation/parser.py +129 -0
- pythonagent/agent/probes/__init__.py +219 -0
- pythonagent/agent/probes/base.py +303 -0
- pythonagent/agent/probes/cache/__init__.py +51 -0
- pythonagent/agent/probes/cache/redis.py +119 -0
- pythonagent/agent/probes/cache/redis_asyncio.py +83 -0
- pythonagent/agent/probes/coroutines/__init__.py +1 -0
- pythonagent/agent/probes/coroutines/asyncio.py +63 -0
- pythonagent/agent/probes/elasticdb/__init__.py +7 -0
- pythonagent/agent/probes/elasticdb/aelastic.py +54 -0
- pythonagent/agent/probes/frameworks/__init__.py +27 -0
- pythonagent/agent/probes/frameworks/agentprofiler.py +105 -0
- pythonagent/agent/probes/frameworks/aiohttp_web.py +155 -0
- pythonagent/agent/probes/frameworks/aisess.py +151 -0
- pythonagent/agent/probes/frameworks/asgi.py +340 -0
- pythonagent/agent/probes/frameworks/bottle.py +27 -0
- pythonagent/agent/probes/frameworks/cherry.py +25 -0
- pythonagent/agent/probes/frameworks/django.py +128 -0
- pythonagent/agent/probes/frameworks/falcon.py +21 -0
- pythonagent/agent/probes/frameworks/fastapi.py +35 -0
- pythonagent/agent/probes/frameworks/flask.py +30 -0
- pythonagent/agent/probes/frameworks/pyramid.py +56 -0
- pythonagent/agent/probes/frameworks/test.py +108 -0
- pythonagent/agent/probes/frameworks/tornado_async_web.py +117 -0
- pythonagent/agent/probes/frameworks/tornado_web.py +133 -0
- pythonagent/agent/probes/frameworks/wsgi.py +353 -0
- pythonagent/agent/probes/grpc/__init__.py +76 -0
- pythonagent/agent/probes/grpc/client_interceptor.py +132 -0
- pythonagent/agent/probes/grpc/server_interceptor.py +129 -0
- pythonagent/agent/probes/havoc/__init__.py +0 -0
- pythonagent/agent/probes/havoc/custom_memory_stress.py +186 -0
- pythonagent/agent/probes/havoc/custom_thread_stress.py +187 -0
- pythonagent/agent/probes/havoc/havoc_constants.py +218 -0
- pythonagent/agent/probes/havoc/havoc_manager.py +981 -0
- pythonagent/agent/probes/http/__init__.py +49 -0
- pythonagent/agent/probes/http/aiohttp_client.py +59 -0
- pythonagent/agent/probes/http/boto.py +12 -0
- pythonagent/agent/probes/http/httplib.py +110 -0
- pythonagent/agent/probes/http/httpx_client.py +116 -0
- pythonagent/agent/probes/http/requests.py +15 -0
- pythonagent/agent/probes/http/tornado_httpclient.py +85 -0
- pythonagent/agent/probes/http/urllib3.py +16 -0
- pythonagent/agent/probes/langchain/__init__.py +21 -0
- pythonagent/agent/probes/langchain/base_tool.py +95 -0
- pythonagent/agent/probes/langchain/langchain_community.py +136 -0
- pythonagent/agent/probes/langchain/langchain_core.py +32 -0
- pythonagent/agent/probes/langchain/langchain_openai.py +110 -0
- pythonagent/agent/probes/logging/__init__.py +106 -0
- pythonagent/agent/probes/message_brokers/__init__.py +4 -0
- pythonagent/agent/probes/message_brokers/pika.py +126 -0
- pythonagent/agent/probes/mongodb/__init__.py +6 -0
- pythonagent/agent/probes/mongodb/pymongo.py +286 -0
- pythonagent/agent/probes/openai/__init__.py +3 -0
- pythonagent/agent/probes/openai/openai.py +797 -0
- pythonagent/agent/probes/span.py +101 -0
- pythonagent/agent/probes/sql/__init__.py +13 -0
- pythonagent/agent/probes/sql/botocores3.py +51 -0
- pythonagent/agent/probes/sql/dbapi.py +285 -0
- pythonagent/agent/probes/sql/dynamodb.py +90 -0
- pythonagent/agent/probes/sql/mysql_connector.py +24 -0
- pythonagent/agent/probes/sql/mysql_connector_cext.py +24 -0
- pythonagent/agent/probes/sql/mysqldb.py +43 -0
- pythonagent/agent/probes/sql/psycopg2.py +174 -0
- pythonagent/agent/probes/sql/pymysql.py +25 -0
- pythonagent/bootstrap/__init__.py +0 -0
- pythonagent/bootstrap/cav_gunicorn.py +26 -0
- pythonagent/bootstrap/cavagent_lambda_wrapper.py +291 -0
- pythonagent/bootstrap/run.py +47 -0
- pythonagent/bootstrap/sitecustomize.py +287 -0
- pythonagent/cavisson/netdiagnostics/CavAgent/instrumentationprofile.json +26 -0
- pythonagent/cavisson/netdiagnostics/CavAgent/interceptor_points.txt +29 -0
- pythonagent/cavisson/netdiagnostics/python/CavAgent/instrumentationprofile.json +42 -0
- pythonagent/cavisson/netdiagnostics/python/CavAgent/interceptor_points.txt +29 -0
- pythonagent/cavisson/netdiagnostics/python/config/ndsettings.conf +6 -0
- pythonagent/config.py +279 -0
- pythonagent/find.py +72 -0
- pythonagent/find_mod_cls_name.py +54 -0
- pythonagent/lang.py +131 -0
- pythonagent/lib.py +91 -0
- pythonagent/main/__init__.py +0 -0
- pythonagent/main/pytrace/__init__.py +79 -0
- pythonagent/main/pytrace/commands/__init__.py +0 -0
- pythonagent/main/pytrace/commands/auto_discovery.py +25 -0
- pythonagent/main/pytrace/commands/run.py +401 -0
- pythonagent/main/pytrace/pytrace.py +133 -0
- pythonagent/main/wsgi.py +6 -0
- pythonagent/main.py +27 -0
- pythonagent/run.py +46 -0
- pythonagent/sqins.py +8 -0
- pythonagent/test.py +73 -0
- pythonagent/utils.py +168 -0
- pythonagent/vendor/__init__.py +0 -0
- pythonagent/vendor/pympler/__init__.py +1 -0
- pythonagent/vendor/pympler/asizeof.py +2810 -0
- pythonagent/vendor/pympler/charts.py +62 -0
- pythonagent/vendor/pympler/classtracker.py +590 -0
- pythonagent/vendor/pympler/classtracker_stats.py +780 -0
- pythonagent/vendor/pympler/garbagegraph.py +80 -0
- pythonagent/vendor/pympler/mprofile.py +97 -0
- pythonagent/vendor/pympler/muppy.py +275 -0
- pythonagent/vendor/pympler/panels.py +115 -0
- pythonagent/vendor/pympler/process.py +238 -0
- pythonagent/vendor/pympler/py.typed +0 -0
- pythonagent/vendor/pympler/refbrowser.py +451 -0
- pythonagent/vendor/pympler/refgraph.py +350 -0
- pythonagent/vendor/pympler/summary.py +321 -0
- pythonagent/vendor/pympler/tracker.py +267 -0
- pythonagent/vendor/pympler/util/__init__.py +0 -0
- pythonagent/vendor/pympler/util/bottle.py +3809 -0
- pythonagent/vendor/pympler/util/compat.py +23 -0
- pythonagent/vendor/pympler/util/stringutils.py +77 -0
- pythonagent/vendor/pympler/web.py +346 -0
- pythonagent/vendor/werkzeug/__init__.py +20 -0
- pythonagent/vendor/werkzeug/_compat.py +228 -0
- pythonagent/vendor/werkzeug/_internal.py +473 -0
- pythonagent/vendor/werkzeug/_reloader.py +341 -0
- pythonagent/vendor/werkzeug/datastructures.py +3120 -0
- pythonagent/vendor/werkzeug/debug/__init__.py +498 -0
- pythonagent/vendor/werkzeug/debug/console.py +218 -0
- pythonagent/vendor/werkzeug/debug/repr.py +297 -0
- pythonagent/vendor/werkzeug/debug/tbtools.py +628 -0
- pythonagent/vendor/werkzeug/exceptions.py +829 -0
- pythonagent/vendor/werkzeug/filesystem.py +64 -0
- pythonagent/vendor/werkzeug/formparser.py +584 -0
- pythonagent/vendor/werkzeug/http.py +1307 -0
- pythonagent/vendor/werkzeug/local.py +420 -0
- pythonagent/vendor/werkzeug/middleware/__init__.py +25 -0
- pythonagent/vendor/werkzeug/middleware/dispatcher.py +66 -0
- pythonagent/vendor/werkzeug/middleware/http_proxy.py +219 -0
- pythonagent/vendor/werkzeug/middleware/lint.py +408 -0
- pythonagent/vendor/werkzeug/middleware/profiler.py +132 -0
- pythonagent/vendor/werkzeug/middleware/proxy_fix.py +169 -0
- pythonagent/vendor/werkzeug/middleware/shared_data.py +293 -0
- pythonagent/vendor/werkzeug/posixemulation.py +117 -0
- pythonagent/vendor/werkzeug/routing.py +2210 -0
- pythonagent/vendor/werkzeug/security.py +249 -0
- pythonagent/vendor/werkzeug/serving.py +1117 -0
- pythonagent/vendor/werkzeug/test.py +1123 -0
- pythonagent/vendor/werkzeug/testapp.py +241 -0
- pythonagent/vendor/werkzeug/urls.py +1138 -0
- pythonagent/vendor/werkzeug/useragents.py +202 -0
- pythonagent/vendor/werkzeug/utils.py +778 -0
- pythonagent/vendor/werkzeug/wrappers/__init__.py +36 -0
- pythonagent/vendor/werkzeug/wrappers/accept.py +50 -0
- pythonagent/vendor/werkzeug/wrappers/auth.py +33 -0
- pythonagent/vendor/werkzeug/wrappers/base_request.py +673 -0
- pythonagent/vendor/werkzeug/wrappers/base_response.py +700 -0
- pythonagent/vendor/werkzeug/wrappers/common_descriptors.py +341 -0
- pythonagent/vendor/werkzeug/wrappers/cors.py +100 -0
- pythonagent/vendor/werkzeug/wrappers/etag.py +304 -0
- pythonagent/vendor/werkzeug/wrappers/json.py +145 -0
- pythonagent/vendor/werkzeug/wrappers/request.py +49 -0
- pythonagent/vendor/werkzeug/wrappers/response.py +84 -0
- pythonagent/vendor/werkzeug/wrappers/user_agent.py +14 -0
- pythonagent/vendor/werkzeug/wsgi.py +1000 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
|
|
2
|
+
from ..base import ExitCallInterceptor
|
|
3
|
+
from ..span import RetrievalSpan
|
|
4
|
+
from pythonagent.utils import get_current_timestamp_in_us, get_validated_duration, split_fp_topo
|
|
5
|
+
import logging
|
|
6
|
+
#from .constants import text_embedding_models, vectorstore_classes
|
|
7
|
+
MAX_LENGTH = 100
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
A wrapper class to log and monitor retrieval calls
|
|
11
|
+
made to vector databases.It wraps Langchain Community
|
|
12
|
+
retrievers to intercept _similarity_search calls.
|
|
13
|
+
Tracks input queries and number of documents returned.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
class LangChainCommunityVectorStoreInterceptor(ExitCallInterceptor):
|
|
17
|
+
|
|
18
|
+
def __init__(self, agent, cls, vectordb_type):
|
|
19
|
+
super().__init__(agent, cls)
|
|
20
|
+
self.vectordb_type = vectordb_type
|
|
21
|
+
|
|
22
|
+
def _similarity_search(self, similarity_search, *args, **kwargs):
|
|
23
|
+
|
|
24
|
+
start_time, exit_call, bt, fqm, host_name_str, context = 0, 0, None, None, None, None
|
|
25
|
+
test_run, fpi, entry_fpi, nd_session_id, nv_session_id, page_id, full_fp = None, None, None, None, None, None, None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
bt, callout_type, db = self.bt, "VECTORDB", self.vectordb_type
|
|
30
|
+
host, port, query, username, query_params = "NA", "NA", "NA", "NA", None
|
|
31
|
+
fqm = f"{similarity_search.__module__}.{similarity_search.__qualname__}"
|
|
32
|
+
host_name_str = f"NA|{host}|{port}|NA|{callout_type}|{db}|NA|NA|NA|{username}|NA"
|
|
33
|
+
context = self.agent.get_transaction_context()
|
|
34
|
+
if context:
|
|
35
|
+
context.host_str = host_name_str
|
|
36
|
+
context.entry_point_fqm = fqm
|
|
37
|
+
|
|
38
|
+
start_time = get_current_timestamp_in_us()
|
|
39
|
+
if self.agent.logger.isEnabledFor(logging.INFO):
|
|
40
|
+
self.agent.logger.info("langchain community vectorstore db call begin bt {} host {} query {} query_params {} start_time {}".format(bt, host, query, query_params, start_time))
|
|
41
|
+
exit_call = self.db_call_begin(bt, host, query, query_params, start_time)
|
|
42
|
+
|
|
43
|
+
except Exception as e:
|
|
44
|
+
self.agent.logger.exception("Exception in langchain community vectorstore db call begin {}".format(e))
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
result = similarity_search(*args, **kwargs)
|
|
48
|
+
except Exception as e:
|
|
49
|
+
self.agent.logger.exception("Error in application: {}".format(e))
|
|
50
|
+
try:
|
|
51
|
+
end_time = get_current_timestamp_in_us()
|
|
52
|
+
duration = get_validated_duration(start_time, end_time, "langchain_community_vectorstore")
|
|
53
|
+
if context:
|
|
54
|
+
context.status_code = 500
|
|
55
|
+
context.db_callout_time = 0
|
|
56
|
+
if self.agent.logger.isEnabledFor(logging.INFO):
|
|
57
|
+
self.agent.logger.info(
|
|
58
|
+
"langchain_community_vectorstore db call end bt {} exit_call {} duration {} start_time {} fqm {}host_name_str {}".format(
|
|
59
|
+
bt, exit_call, duration, start_time, fqm, host_name_str))
|
|
60
|
+
self.db_call_end(bt, exit_call, duration, start_time, fqm, host_name_str)
|
|
61
|
+
except Exception as e:
|
|
62
|
+
self.agent.logger.exception("Exception in Original Method DB Call End {}".format(e))
|
|
63
|
+
|
|
64
|
+
raise
|
|
65
|
+
|
|
66
|
+
try:
|
|
67
|
+
end_time = get_current_timestamp_in_us()
|
|
68
|
+
duration = get_validated_duration(start_time, end_time, "langchain_community_vectorstore")
|
|
69
|
+
if context:
|
|
70
|
+
context.status_code = 200
|
|
71
|
+
context.db_callout_time = 0
|
|
72
|
+
if self.agent.logger.isEnabledFor(logging.INFO):
|
|
73
|
+
self.agent.logger.info("langchain community vectordb db call end bt {} exit_call {} duration {} start_time {} fqm {}host_name_str {}".format(bt, exit_call, duration, start_time, fqm, host_name_str))
|
|
74
|
+
self.db_call_end(bt, exit_call, duration, start_time, fqm, host_name_str)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
if self.agent.nf_enabled:
|
|
78
|
+
# Capturing input prompt and output response, formatting it
|
|
79
|
+
output_docs = []
|
|
80
|
+
for document in result:
|
|
81
|
+
doc_info = {
|
|
82
|
+
"source": document.metadata["source"],
|
|
83
|
+
"content": document.page_content[:MAX_LENGTH]
|
|
84
|
+
}
|
|
85
|
+
output_docs.append(doc_info)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
vectorstore_object = args[0]
|
|
89
|
+
query = args[1]
|
|
90
|
+
|
|
91
|
+
meta = {
|
|
92
|
+
"span_kind": "retrieval",
|
|
93
|
+
"input": str(query),
|
|
94
|
+
"output": {
|
|
95
|
+
"num_of_docs": len(result),
|
|
96
|
+
"doc_sample": output_docs
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if context:
|
|
101
|
+
fp_topo = context.fp_topo
|
|
102
|
+
test_run, fpi, entry_fpi, nd_session_id, nv_session_id, page_id, full_fp = split_fp_topo(fp_topo)
|
|
103
|
+
|
|
104
|
+
retrieval_span = RetrievalSpan(fqm, start_time, duration, "ok", meta, test_run, fpi, entry_fpi, nd_session_id, nv_session_id, page_id, full_fp)
|
|
105
|
+
retrieval_span_json = retrieval_span.create_span_json()
|
|
106
|
+
|
|
107
|
+
# SDK API call to send logs to NF
|
|
108
|
+
if self.agent.logger.isEnabledFor(logging.INFO):
|
|
109
|
+
self.agent.logger.info("langchain community vectordb sending vectordb span {}".format(retrieval_span_json))
|
|
110
|
+
self.agent.dump_log_message(bt, retrieval_span_json)
|
|
111
|
+
|
|
112
|
+
except Exception as e:
|
|
113
|
+
self.agent.logger.exception("Exception in langchain community vectorstore db call end {}".format(e))
|
|
114
|
+
|
|
115
|
+
return result
|
|
116
|
+
|
|
117
|
+
class LangChainCommunityEmbeddingsInterceptor(ExitCallInterceptor):
|
|
118
|
+
def _embed_query(self, embed_query, *args, **kwargs):
|
|
119
|
+
result = embed_query(*args, **kwargs)
|
|
120
|
+
return result
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def intercept_langchain_community_vectorstores(agent, mod):
|
|
124
|
+
agent.logger.warning("Instrument module: langchain_community.vectorstores{}".format(", mod: {}".format(mod) if mod else ""))
|
|
125
|
+
|
|
126
|
+
LangChainCommunityVectorStoreInterceptor(agent, mod.Chroma, "Chroma").attach("similarity_search")
|
|
127
|
+
|
|
128
|
+
#for vectorstore_class in vectorstore_classes:
|
|
129
|
+
# LangChainCommunityVectorStoreInterceptor(agent, mod.vectorstore_class).attach("similarity_search")
|
|
130
|
+
|
|
131
|
+
def intercept_langchain_community_embeddings(agent, mod):
|
|
132
|
+
agent.logger.warning("Instrument module: langchain_community.embeddings{}".format(", mod: {}".format(mod) if mod else ""))
|
|
133
|
+
pass
|
|
134
|
+
|
|
135
|
+
#for text_embedding_model in text_embedding_models:
|
|
136
|
+
# LangChainCommunityVectorStoreInterceptor(agent, mod.text_embedding_model).attach("embed_query")
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
from logging import exception
|
|
2
|
+
|
|
3
|
+
from click import prompt
|
|
4
|
+
|
|
5
|
+
from ..base import ExitCallInterceptor
|
|
6
|
+
from pythonagent.utils import get_current_timestamp_in_us, get_validated_duration
|
|
7
|
+
|
|
8
|
+
#from .base_llm import LangChainBaseLLMInterceptor
|
|
9
|
+
#from .base_chat_model import LangChainBaseChatModelInterceptor
|
|
10
|
+
#from .langchain_runnable_sequence import LangChainRunnableSequenceInterceptor
|
|
11
|
+
from .base_tool import LangChainBaseToolInterceptor
|
|
12
|
+
|
|
13
|
+
"""
|
|
14
|
+
# Interceptor API for instrument langchain_core.language_models module
|
|
15
|
+
def intercept_langchain_core_language_models(agent, mod):
|
|
16
|
+
langchain_base_llm_interceptor = LangChainBaseLLMInterceptor(agent, mod.llms.BaseLLM)
|
|
17
|
+
langchain_base_llm_interceptor.attach(["invoke", "generate", "stream"])
|
|
18
|
+
|
|
19
|
+
langchain_base_chat_model_interceptor = LangChainBaseChatModelInterceptor(agent, mod.chat_models.BaseChatModel)
|
|
20
|
+
langchain_base_chat_model_interceptor.attach(["invoke", "generate", "stream"])
|
|
21
|
+
|
|
22
|
+
# Interceptor API for instrument langchain_core.runnables module
|
|
23
|
+
def intercept_langchain_core_runnables(agent, mod):
|
|
24
|
+
langchain_runnable_sequence_interceptor = LangChainRunnableSequenceInterceptor(agent, mod.base.RunnableSequence)
|
|
25
|
+
langchain_runnable_sequence_interceptor.attach(["invoke", "batch", "stream"])
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
# Interceptor API for instrument langchain_core.tools module
|
|
29
|
+
def intercept_langchain_core_tools(agent, mod):
|
|
30
|
+
agent.logger.warning("Instrument module: langchain_core.tools{}".format(", mod: {}".format(mod) if mod else ""))
|
|
31
|
+
langchain_base_tool_interceptor = LangChainBaseToolInterceptor(agent, mod.base.BaseTool)
|
|
32
|
+
langchain_base_tool_interceptor.attach("invoke")
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
from ..base import ExitCallInterceptor
|
|
2
|
+
from ..span import EmbeddingSpan
|
|
3
|
+
from pythonagent.utils import get_current_timestamp_in_us, get_validated_duration, split_fp_topo
|
|
4
|
+
import logging
|
|
5
|
+
SAMPLE_LEN = 3
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
A wrapper class to monitor calls to OpenAI Embeddings in LangChain.
|
|
9
|
+
Intercepts _embed_query requests for logging or metrics.
|
|
10
|
+
Tracks input, outputs, embedding model name and provider
|
|
11
|
+
vector length, vector sample,.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class LangChainOpenAIEmbeddingsInterceptor(ExitCallInterceptor):
|
|
16
|
+
def _embed_query(self, embed_query, *args, **kwargs):
|
|
17
|
+
|
|
18
|
+
start_time, exit_call, bt, embeddings_model, context, fqm, host_name_str = 0, 0, None, None, None, None, None
|
|
19
|
+
test_run, fpi, entry_fpi, nd_session_id, nv_session_id, page_id, full_fp = None, None, None, None, None, None, None
|
|
20
|
+
try:
|
|
21
|
+
bt, callout_type, provider = self.bt, "EMBEDDINGS", "OpenAI"
|
|
22
|
+
host, port, query, username, query_params = "NA", "NA", "NA", "NA", None
|
|
23
|
+
|
|
24
|
+
openai_embeddings_object = args[0]
|
|
25
|
+
embeddings_model = openai_embeddings_object.model
|
|
26
|
+
|
|
27
|
+
db = provider + "_" + embeddings_model
|
|
28
|
+
|
|
29
|
+
fqm = f"{embed_query.__module__}.{embed_query.__qualname__}"
|
|
30
|
+
host_name_str = f"NA|{host}|{port}|NA|{callout_type}|{db}|NA|NA|NA|{username}|NA"
|
|
31
|
+
|
|
32
|
+
context = self.agent.get_transaction_context()
|
|
33
|
+
if context:
|
|
34
|
+
context.host_str = host_name_str
|
|
35
|
+
context.entry_point_fqm = fqm
|
|
36
|
+
|
|
37
|
+
start_time = get_current_timestamp_in_us()
|
|
38
|
+
if self.agent.logger.isEnabledFor(logging.INFO):
|
|
39
|
+
self.agent.logger.info("langchain openai embeddings db call begin bt {} host {} query {} query_params {} start_time {}".format(bt, host, query, query_params, start_time))
|
|
40
|
+
|
|
41
|
+
exit_call = self.db_call_begin(bt, host, query, query_params, start_time)
|
|
42
|
+
|
|
43
|
+
except Exception as e:
|
|
44
|
+
self.agent.logger.exception("langchain openai embeddings db call begin {}".format(e))
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
result = embed_query(*args, **kwargs)
|
|
48
|
+
except Exception as e:
|
|
49
|
+
self.agent.logger.exception("Error in application: {}".format(e))
|
|
50
|
+
try:
|
|
51
|
+
end_time = get_current_timestamp_in_us()
|
|
52
|
+
duration = get_validated_duration(start_time, end_time, "LangchainOpenAI Embeddings")
|
|
53
|
+
if context:
|
|
54
|
+
context.status_code = 500
|
|
55
|
+
context.db_callout_time = 0
|
|
56
|
+
if self.agent.logger.isEnabledFor(logging.INFO):
|
|
57
|
+
self.agent.logger.info("langchain openai embeddings db call end bt {} exit_call {} duration {} start_time {} fqm {}host_name_str {}".format(bt, exit_call, duration, start_time, fqm, host_name_str))
|
|
58
|
+
self.db_call_end(bt, exit_call, duration, start_time, fqm, host_name_str)
|
|
59
|
+
except Exception as e:
|
|
60
|
+
self.agent.logger.exception("Exception in Original Method langchain openai embeddings {}".format(e))
|
|
61
|
+
|
|
62
|
+
raise
|
|
63
|
+
|
|
64
|
+
try:
|
|
65
|
+
end_time = get_current_timestamp_in_us()
|
|
66
|
+
duration = get_validated_duration(start_time, end_time, "LangchainOpenAI Embeddings")
|
|
67
|
+
if context:
|
|
68
|
+
context.status_code = 200
|
|
69
|
+
context.db_callout_time = 0
|
|
70
|
+
if self.agent.logger.isEnabledFor(logging.INFO):
|
|
71
|
+
self.agent.logger.info(
|
|
72
|
+
"langchain openai embeddings db call end bt {} exit_call {} duration {} start_time {} fqm {}host_name_str {}".format(
|
|
73
|
+
bt, exit_call, duration, start_time, fqm, host_name_str))
|
|
74
|
+
self.db_call_end(bt, exit_call, duration, start_time, fqm, host_name_str)
|
|
75
|
+
|
|
76
|
+
if self.agent.nf_enabled:
|
|
77
|
+
# Capturing input prompt and output response, formatting it
|
|
78
|
+
meta = {"span_kind": "embedding",
|
|
79
|
+
"input": args[1],
|
|
80
|
+
"output": {"vector_length": len(result),
|
|
81
|
+
"vector_sample": result[:SAMPLE_LEN],
|
|
82
|
+
"model_name": embeddings_model,
|
|
83
|
+
"model_provider": "OpenAI"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if context:
|
|
88
|
+
fp_topo = context.fp_topo
|
|
89
|
+
test_run, fpi, entry_fpi, nd_session_id, nv_session_id, page_id, full_fp = split_fp_topo(fp_topo)
|
|
90
|
+
|
|
91
|
+
embedding_span = EmbeddingSpan(fqm, start_time, duration, "ok", meta, test_run, fpi, entry_fpi, nd_session_id, nv_session_id, page_id, full_fp)
|
|
92
|
+
embedding_span_json = embedding_span.create_span_json()
|
|
93
|
+
|
|
94
|
+
# SDK API call to send logs to NF
|
|
95
|
+
if self.agent.logger.isEnabledFor(logging.INFO):
|
|
96
|
+
self.agent.logger.info("langchain openai embeddings sending embeddings span {}".format(embedding_span_json))
|
|
97
|
+
self.agent.dump_log_message(bt, embedding_span_json)
|
|
98
|
+
|
|
99
|
+
except Exception as e:
|
|
100
|
+
self.agent.logger.exception("langchain openai embeddings db call end {}".format(e))
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
return result
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# Interceptor API to instrument langchain_openai module
|
|
108
|
+
def intercept_langchain_openai(agent, mod):
|
|
109
|
+
agent.logger.warning("Instrument module: langchain_openai{}".format(", mod: {}".format(mod) if mod else ""))
|
|
110
|
+
LangChainOpenAIEmbeddingsInterceptor(agent, mod.embeddings.OpenAIEmbeddings).attach("embed_query")
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
|
|
2
|
+
"""Intercept the Python logging module.
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
import sys
|
|
8
|
+
import time
|
|
9
|
+
import traceback
|
|
10
|
+
|
|
11
|
+
from ..base import BaseInterceptor
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class LoggingInterceptor(BaseInterceptor):
|
|
15
|
+
|
|
16
|
+
def _callHandlers(self, callHandlers, logger, record):
|
|
17
|
+
|
|
18
|
+
if record.name.startswith('pythonagent.agent'):
|
|
19
|
+
return callHandlers(logger, record)
|
|
20
|
+
|
|
21
|
+
#self.agent.application_loggers.add(logger)
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
self.agent.logger.info("error message as {}".format(record.getMessage()))
|
|
25
|
+
self.add_logged_error(record)
|
|
26
|
+
|
|
27
|
+
if type(record.msg) is not str:
|
|
28
|
+
record.msg = str(record.msg)
|
|
29
|
+
|
|
30
|
+
context = self.agent.get_transaction_context()
|
|
31
|
+
if context:
|
|
32
|
+
if context.aws_request_id:
|
|
33
|
+
record.msg = f"[AWS Lambda Request ID: {context.aws_request_id}] " + record.msg
|
|
34
|
+
if context.fp_topo:
|
|
35
|
+
record.msg = record.msg + str(context.fp_topo)
|
|
36
|
+
self.agent.logger.debug("Modified log message {}".format(record.msg))
|
|
37
|
+
|
|
38
|
+
else:
|
|
39
|
+
self.agent.logger.info("Transaction context not found while appending application log in logging.__init__")
|
|
40
|
+
|
|
41
|
+
except Exception as e:
|
|
42
|
+
self.agent.logger.exception("Error in logging.__init__ _callHandlers {}".format(e))
|
|
43
|
+
|
|
44
|
+
callHandlers(logger, record)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def add_logged_error(self, record):
|
|
48
|
+
"""Add an error to the BT if the log record should trigger an error.
|
|
49
|
+
|
|
50
|
+
If the level is greater or equal than the threshold and the message is
|
|
51
|
+
not ignored, create an ErrorInfo object and add it to the BT.
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
if record.levelno < 40:
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
start_time = round(time.time() * 1000)
|
|
59
|
+
exception_class = ''
|
|
60
|
+
exception_cause = ''
|
|
61
|
+
exception_message = ''
|
|
62
|
+
file_name = ''
|
|
63
|
+
line_number = ''
|
|
64
|
+
throwing_method = ''
|
|
65
|
+
stack_trace_str = ''
|
|
66
|
+
|
|
67
|
+
if record.exc_info:
|
|
68
|
+
exception_class_type, exception_message, traceback_object = record.exc_info
|
|
69
|
+
|
|
70
|
+
exception_class = str(exception_class_type.__name__)
|
|
71
|
+
exception_cause = str(exception_class_type.__cause__)
|
|
72
|
+
exception_message = str(exception_message)
|
|
73
|
+
|
|
74
|
+
tb = traceback.extract_tb(traceback_object)[-1] # Get last traceback frame
|
|
75
|
+
|
|
76
|
+
file_name, line_number, throwing_method, _ = tb
|
|
77
|
+
|
|
78
|
+
full_stack_trace_str = ''.join(traceback.format_exception(*record.exc_info))
|
|
79
|
+
full_stack_trace_str = full_stack_trace_str.strip()
|
|
80
|
+
|
|
81
|
+
stack_trace_list = full_stack_trace_str.split("\n")
|
|
82
|
+
size = 2 if sys.version_info < (3, 11, 0) else 3
|
|
83
|
+
max_depth = self.agent.exception_stack_depth * size
|
|
84
|
+
|
|
85
|
+
first_line = stack_trace_list[0]
|
|
86
|
+
last_line = stack_trace_list[-1]
|
|
87
|
+
stack_trace_list = stack_trace_list[1:-1]
|
|
88
|
+
|
|
89
|
+
stack_trace_len = len(stack_trace_list)
|
|
90
|
+
if max_depth < stack_trace_len:
|
|
91
|
+
stack_trace_list = stack_trace_list[-max_depth:]
|
|
92
|
+
|
|
93
|
+
stack_trace_str = first_line + "\n" + "\n".join(stack_trace_list) + "\n" + last_line
|
|
94
|
+
|
|
95
|
+
self.agent.logger.debug('The Exception is generated with Exception_class as {} ,Exception_message as {} ,Exception_cause as {} and Throwing method as {} with a Depth of {} in file {}'.format(exception_class,exception_message,exception_cause,throwing_method,self.agent.exception_stack_depth,file_name))
|
|
96
|
+
self.agent.exceptiondump(self.bt, None, start_time, exception_class, exception_message, "None", throwing_method, exception_cause, line_number, stack_trace_str,file_name)
|
|
97
|
+
|
|
98
|
+
except Exception as e:
|
|
99
|
+
self.agent.logger.exception("Error in creating exception record: {}".format(e))
|
|
100
|
+
|
|
101
|
+
self.agent.logger.info('Logging application error as message {}'.format(record.msg))
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def intercept_logging(agent, mod):
|
|
105
|
+
agent.logger.warning("Instrument module: logging{}".format(", mod: {}".format(mod) if mod else ""))
|
|
106
|
+
LoggingInterceptor(agent, mod.Logger).attach('callHandlers')
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
from ..base import BaseInterceptor
|
|
2
|
+
|
|
3
|
+
from pythonagent.utils import get_current_timestamp_in_us, get_validated_duration, get_current_thread_time_in_us, generate_callout_id
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class PikaBlockingConnectionInterceptor(BaseInterceptor):
|
|
7
|
+
|
|
8
|
+
def __init__(self, agent, cls):
|
|
9
|
+
self.agent = agent
|
|
10
|
+
super(PikaBlockingConnectionInterceptor, self).__init__(agent, cls)
|
|
11
|
+
|
|
12
|
+
def _channel(self, channel, *args, **kwargs):
|
|
13
|
+
try:
|
|
14
|
+
connection, = args
|
|
15
|
+
select_connection = connection._impl
|
|
16
|
+
# Access host and port directly from connection
|
|
17
|
+
params = select_connection.params
|
|
18
|
+
self.host = params.host
|
|
19
|
+
self.port = params.port
|
|
20
|
+
except Exception as e:
|
|
21
|
+
self.agent.logger.warning("Exception occurred while instrumenting pika BlockingConnection.channel {}".format(e))
|
|
22
|
+
|
|
23
|
+
result = channel(*args, **kwargs)
|
|
24
|
+
return result
|
|
25
|
+
|
|
26
|
+
class PikaBlockingChannelInterceptor(BaseInterceptor):
|
|
27
|
+
|
|
28
|
+
def __init__(self, agent, cls):
|
|
29
|
+
self.agent = agent
|
|
30
|
+
super(PikaBlockingChannelInterceptor, self).__init__(agent, cls)
|
|
31
|
+
|
|
32
|
+
def _basic_publish(self, basic_publish, *args, **kwargs):
|
|
33
|
+
exit_call = None
|
|
34
|
+
try:
|
|
35
|
+
channel_prop = args[0]
|
|
36
|
+
channel_impl = channel_prop._impl
|
|
37
|
+
# Access connection from channel
|
|
38
|
+
connection = channel_impl.connection
|
|
39
|
+
connection_parameters = connection.params
|
|
40
|
+
# Access host and port from connection
|
|
41
|
+
host = connection_parameters.host
|
|
42
|
+
port = connection_parameters.port
|
|
43
|
+
db_start_time = 0
|
|
44
|
+
mNAme = basic_publish.__module__ + "." + basic_publish.__qualname__
|
|
45
|
+
db = kwargs.get('routing_key', 'default_db')
|
|
46
|
+
host_name_str = f"NA|{host}|{port}|NA|MQ|{db}|NA|NA|NA|default_user|NA"
|
|
47
|
+
ctx = self.agent.get_transaction_context()
|
|
48
|
+
if ctx:
|
|
49
|
+
ctx.entry_point_fqm = mNAme
|
|
50
|
+
ctx.host_str = host_name_str
|
|
51
|
+
ctx.status_code = 200
|
|
52
|
+
db_start_time = get_current_timestamp_in_us()
|
|
53
|
+
if ctx:
|
|
54
|
+
ctx.db_callout_start_time = db_start_time
|
|
55
|
+
db_query = None
|
|
56
|
+
db_query_params = None
|
|
57
|
+
exit_call = self.agent.db_call_begin(self.bt, host_name_str, db_query, db_query_params, db_start_time)
|
|
58
|
+
|
|
59
|
+
# Injecting custom headers
|
|
60
|
+
headers_value = self.agent.get_nd_header(self.bt, host_name_str, generate_callout_id()).decode()
|
|
61
|
+
properties = kwargs.get('properties', None)
|
|
62
|
+
if properties:
|
|
63
|
+
if properties.headers:
|
|
64
|
+
properties.headers["CavNDFPInstance"] = headers_value
|
|
65
|
+
else:
|
|
66
|
+
properties.headers = {}
|
|
67
|
+
properties.headers["CavNDFPInstance"] = headers_value
|
|
68
|
+
|
|
69
|
+
except Exception as e:
|
|
70
|
+
self.agent.logger.warning("Exception in DB Begin for pika BlockingChannel.basic_publish {}".format(e))
|
|
71
|
+
|
|
72
|
+
result = basic_publish(*args, **kwargs)
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
db_end_time = get_current_timestamp_in_us()
|
|
76
|
+
ctx = self.agent.get_transaction_context()
|
|
77
|
+
db_start_time = ctx.db_callout_start_time if ctx else 0
|
|
78
|
+
duration = get_validated_duration(db_start_time, db_end_time, "MQ")
|
|
79
|
+
if ctx:
|
|
80
|
+
ctx.status_code = 200
|
|
81
|
+
ctx.db_callout_start_time = 0
|
|
82
|
+
self.agent.db_call_end(self.bt, exit_call, duration, db_start_time)
|
|
83
|
+
except Exception as e:
|
|
84
|
+
self.agent.logger.warning("Exception in DB End for pika BlockingChannel.basic_publish {}".format(e))
|
|
85
|
+
|
|
86
|
+
return result
|
|
87
|
+
|
|
88
|
+
def wrapped_on_consumer_message_delivery(self, _on_consumer_message_delivery, *args, **kwargs):
|
|
89
|
+
bt = None
|
|
90
|
+
cpu_time_before = None
|
|
91
|
+
fp_instance = None
|
|
92
|
+
|
|
93
|
+
try:
|
|
94
|
+
method = args[2]
|
|
95
|
+
properties = args[3]
|
|
96
|
+
|
|
97
|
+
bt_name = method.routing_key
|
|
98
|
+
if hasattr(properties, 'headers'):
|
|
99
|
+
if isinstance(properties.headers, dict) and 'CavNDFPInstance' in properties.headers:
|
|
100
|
+
fp_instance = properties.headers['CavNDFPInstance']
|
|
101
|
+
|
|
102
|
+
cpu_time_before = get_current_thread_time_in_us()
|
|
103
|
+
bt = self.agent.start_business_transaction(bt_name, "", None, None, None, fp_instance)
|
|
104
|
+
|
|
105
|
+
except Exception as e:
|
|
106
|
+
self.agent.logger.warning("Exception in Start BT for RabbitMQ {}".format(e))
|
|
107
|
+
|
|
108
|
+
result = _on_consumer_message_delivery(*args, **kwargs)
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
if bt:
|
|
112
|
+
cpu_time_after = get_current_thread_time_in_us()
|
|
113
|
+
cpu_time = cpu_time_after - cpu_time_before
|
|
114
|
+
self.agent.end_business_transaction(bt, cpu_time)
|
|
115
|
+
except Exception as e:
|
|
116
|
+
self.agent.logger.warning("Exception in End BT for RabbitMQ {}".format(e))
|
|
117
|
+
|
|
118
|
+
return result
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def intercept_pika(agent, mod):
|
|
122
|
+
agent.logger.warning("Instrument module: pika{}".format(", mod: {}".format(mod) if mod else ""))
|
|
123
|
+
PikaBlockingConnectionInterceptor(agent, mod.adapters.blocking_connection.BlockingConnection).attach('channel')
|
|
124
|
+
pika_blocking_channel_interceptor = PikaBlockingChannelInterceptor(agent, mod.adapters.blocking_connection.BlockingChannel)
|
|
125
|
+
pika_blocking_channel_interceptor.attach('basic_publish')
|
|
126
|
+
pika_blocking_channel_interceptor.attach('_on_consumer_message_delivery',patched_method_name='wrapped_on_consumer_message_delivery')
|