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.
Files changed (180) hide show
  1. cavisson_pythonagent-0.0.1.dist-info/METADATA +32 -0
  2. cavisson_pythonagent-0.0.1.dist-info/RECORD +180 -0
  3. cavisson_pythonagent-0.0.1.dist-info/WHEEL +5 -0
  4. cavisson_pythonagent-0.0.1.dist-info/licenses/LICENSE +19 -0
  5. cavisson_pythonagent-0.0.1.dist-info/top_level.txt +1 -0
  6. pythonagent/__init__.py +22 -0
  7. pythonagent/agent/__init__.py +219 -0
  8. pythonagent/agent/internal/__init__.py +1 -0
  9. pythonagent/agent/internal/agent.py +1651 -0
  10. pythonagent/agent/internal/framesinfo.py +152 -0
  11. pythonagent/agent/internal/heap_dump.py +39 -0
  12. pythonagent/agent/internal/intercept_module.py +70 -0
  13. pythonagent/agent/internal/logs.py +122 -0
  14. pythonagent/agent/internal/metadata/__init__.py +0 -0
  15. pythonagent/agent/internal/metadata/agent_meta_data.py +276 -0
  16. pythonagent/agent/internal/proc_compat.py +75 -0
  17. pythonagent/agent/internal/profile.py +47 -0
  18. pythonagent/agent/internal/provider.py +83 -0
  19. pythonagent/agent/internal/thread_dump.py +85 -0
  20. pythonagent/agent/internal/udp.py +245 -0
  21. pythonagent/agent/internal/udp_message.py +800 -0
  22. pythonagent/agent/probes/Instrumentation/__init__.py +340 -0
  23. pythonagent/agent/probes/Instrumentation/find.py +243 -0
  24. pythonagent/agent/probes/Instrumentation/module_version_resolver.py +155 -0
  25. pythonagent/agent/probes/Instrumentation/new_parser.py +64 -0
  26. pythonagent/agent/probes/Instrumentation/parser.py +129 -0
  27. pythonagent/agent/probes/__init__.py +219 -0
  28. pythonagent/agent/probes/base.py +303 -0
  29. pythonagent/agent/probes/cache/__init__.py +51 -0
  30. pythonagent/agent/probes/cache/redis.py +119 -0
  31. pythonagent/agent/probes/cache/redis_asyncio.py +83 -0
  32. pythonagent/agent/probes/coroutines/__init__.py +1 -0
  33. pythonagent/agent/probes/coroutines/asyncio.py +63 -0
  34. pythonagent/agent/probes/elasticdb/__init__.py +7 -0
  35. pythonagent/agent/probes/elasticdb/aelastic.py +54 -0
  36. pythonagent/agent/probes/frameworks/__init__.py +27 -0
  37. pythonagent/agent/probes/frameworks/agentprofiler.py +105 -0
  38. pythonagent/agent/probes/frameworks/aiohttp_web.py +155 -0
  39. pythonagent/agent/probes/frameworks/aisess.py +151 -0
  40. pythonagent/agent/probes/frameworks/asgi.py +340 -0
  41. pythonagent/agent/probes/frameworks/bottle.py +27 -0
  42. pythonagent/agent/probes/frameworks/cherry.py +25 -0
  43. pythonagent/agent/probes/frameworks/django.py +128 -0
  44. pythonagent/agent/probes/frameworks/falcon.py +21 -0
  45. pythonagent/agent/probes/frameworks/fastapi.py +35 -0
  46. pythonagent/agent/probes/frameworks/flask.py +30 -0
  47. pythonagent/agent/probes/frameworks/pyramid.py +56 -0
  48. pythonagent/agent/probes/frameworks/test.py +108 -0
  49. pythonagent/agent/probes/frameworks/tornado_async_web.py +117 -0
  50. pythonagent/agent/probes/frameworks/tornado_web.py +133 -0
  51. pythonagent/agent/probes/frameworks/wsgi.py +353 -0
  52. pythonagent/agent/probes/grpc/__init__.py +76 -0
  53. pythonagent/agent/probes/grpc/client_interceptor.py +132 -0
  54. pythonagent/agent/probes/grpc/server_interceptor.py +129 -0
  55. pythonagent/agent/probes/havoc/__init__.py +0 -0
  56. pythonagent/agent/probes/havoc/custom_memory_stress.py +186 -0
  57. pythonagent/agent/probes/havoc/custom_thread_stress.py +187 -0
  58. pythonagent/agent/probes/havoc/havoc_constants.py +218 -0
  59. pythonagent/agent/probes/havoc/havoc_manager.py +981 -0
  60. pythonagent/agent/probes/http/__init__.py +49 -0
  61. pythonagent/agent/probes/http/aiohttp_client.py +59 -0
  62. pythonagent/agent/probes/http/boto.py +12 -0
  63. pythonagent/agent/probes/http/httplib.py +110 -0
  64. pythonagent/agent/probes/http/httpx_client.py +116 -0
  65. pythonagent/agent/probes/http/requests.py +15 -0
  66. pythonagent/agent/probes/http/tornado_httpclient.py +85 -0
  67. pythonagent/agent/probes/http/urllib3.py +16 -0
  68. pythonagent/agent/probes/langchain/__init__.py +21 -0
  69. pythonagent/agent/probes/langchain/base_tool.py +95 -0
  70. pythonagent/agent/probes/langchain/langchain_community.py +136 -0
  71. pythonagent/agent/probes/langchain/langchain_core.py +32 -0
  72. pythonagent/agent/probes/langchain/langchain_openai.py +110 -0
  73. pythonagent/agent/probes/logging/__init__.py +106 -0
  74. pythonagent/agent/probes/message_brokers/__init__.py +4 -0
  75. pythonagent/agent/probes/message_brokers/pika.py +126 -0
  76. pythonagent/agent/probes/mongodb/__init__.py +6 -0
  77. pythonagent/agent/probes/mongodb/pymongo.py +286 -0
  78. pythonagent/agent/probes/openai/__init__.py +3 -0
  79. pythonagent/agent/probes/openai/openai.py +797 -0
  80. pythonagent/agent/probes/span.py +101 -0
  81. pythonagent/agent/probes/sql/__init__.py +13 -0
  82. pythonagent/agent/probes/sql/botocores3.py +51 -0
  83. pythonagent/agent/probes/sql/dbapi.py +285 -0
  84. pythonagent/agent/probes/sql/dynamodb.py +90 -0
  85. pythonagent/agent/probes/sql/mysql_connector.py +24 -0
  86. pythonagent/agent/probes/sql/mysql_connector_cext.py +24 -0
  87. pythonagent/agent/probes/sql/mysqldb.py +43 -0
  88. pythonagent/agent/probes/sql/psycopg2.py +174 -0
  89. pythonagent/agent/probes/sql/pymysql.py +25 -0
  90. pythonagent/bootstrap/__init__.py +0 -0
  91. pythonagent/bootstrap/cav_gunicorn.py +26 -0
  92. pythonagent/bootstrap/cavagent_lambda_wrapper.py +291 -0
  93. pythonagent/bootstrap/run.py +47 -0
  94. pythonagent/bootstrap/sitecustomize.py +287 -0
  95. pythonagent/cavisson/netdiagnostics/CavAgent/instrumentationprofile.json +26 -0
  96. pythonagent/cavisson/netdiagnostics/CavAgent/interceptor_points.txt +29 -0
  97. pythonagent/cavisson/netdiagnostics/python/CavAgent/instrumentationprofile.json +42 -0
  98. pythonagent/cavisson/netdiagnostics/python/CavAgent/interceptor_points.txt +29 -0
  99. pythonagent/cavisson/netdiagnostics/python/config/ndsettings.conf +6 -0
  100. pythonagent/config.py +279 -0
  101. pythonagent/find.py +72 -0
  102. pythonagent/find_mod_cls_name.py +54 -0
  103. pythonagent/lang.py +131 -0
  104. pythonagent/lib.py +91 -0
  105. pythonagent/main/__init__.py +0 -0
  106. pythonagent/main/pytrace/__init__.py +79 -0
  107. pythonagent/main/pytrace/commands/__init__.py +0 -0
  108. pythonagent/main/pytrace/commands/auto_discovery.py +25 -0
  109. pythonagent/main/pytrace/commands/run.py +401 -0
  110. pythonagent/main/pytrace/pytrace.py +133 -0
  111. pythonagent/main/wsgi.py +6 -0
  112. pythonagent/main.py +27 -0
  113. pythonagent/run.py +46 -0
  114. pythonagent/sqins.py +8 -0
  115. pythonagent/test.py +73 -0
  116. pythonagent/utils.py +168 -0
  117. pythonagent/vendor/__init__.py +0 -0
  118. pythonagent/vendor/pympler/__init__.py +1 -0
  119. pythonagent/vendor/pympler/asizeof.py +2810 -0
  120. pythonagent/vendor/pympler/charts.py +62 -0
  121. pythonagent/vendor/pympler/classtracker.py +590 -0
  122. pythonagent/vendor/pympler/classtracker_stats.py +780 -0
  123. pythonagent/vendor/pympler/garbagegraph.py +80 -0
  124. pythonagent/vendor/pympler/mprofile.py +97 -0
  125. pythonagent/vendor/pympler/muppy.py +275 -0
  126. pythonagent/vendor/pympler/panels.py +115 -0
  127. pythonagent/vendor/pympler/process.py +238 -0
  128. pythonagent/vendor/pympler/py.typed +0 -0
  129. pythonagent/vendor/pympler/refbrowser.py +451 -0
  130. pythonagent/vendor/pympler/refgraph.py +350 -0
  131. pythonagent/vendor/pympler/summary.py +321 -0
  132. pythonagent/vendor/pympler/tracker.py +267 -0
  133. pythonagent/vendor/pympler/util/__init__.py +0 -0
  134. pythonagent/vendor/pympler/util/bottle.py +3809 -0
  135. pythonagent/vendor/pympler/util/compat.py +23 -0
  136. pythonagent/vendor/pympler/util/stringutils.py +77 -0
  137. pythonagent/vendor/pympler/web.py +346 -0
  138. pythonagent/vendor/werkzeug/__init__.py +20 -0
  139. pythonagent/vendor/werkzeug/_compat.py +228 -0
  140. pythonagent/vendor/werkzeug/_internal.py +473 -0
  141. pythonagent/vendor/werkzeug/_reloader.py +341 -0
  142. pythonagent/vendor/werkzeug/datastructures.py +3120 -0
  143. pythonagent/vendor/werkzeug/debug/__init__.py +498 -0
  144. pythonagent/vendor/werkzeug/debug/console.py +218 -0
  145. pythonagent/vendor/werkzeug/debug/repr.py +297 -0
  146. pythonagent/vendor/werkzeug/debug/tbtools.py +628 -0
  147. pythonagent/vendor/werkzeug/exceptions.py +829 -0
  148. pythonagent/vendor/werkzeug/filesystem.py +64 -0
  149. pythonagent/vendor/werkzeug/formparser.py +584 -0
  150. pythonagent/vendor/werkzeug/http.py +1307 -0
  151. pythonagent/vendor/werkzeug/local.py +420 -0
  152. pythonagent/vendor/werkzeug/middleware/__init__.py +25 -0
  153. pythonagent/vendor/werkzeug/middleware/dispatcher.py +66 -0
  154. pythonagent/vendor/werkzeug/middleware/http_proxy.py +219 -0
  155. pythonagent/vendor/werkzeug/middleware/lint.py +408 -0
  156. pythonagent/vendor/werkzeug/middleware/profiler.py +132 -0
  157. pythonagent/vendor/werkzeug/middleware/proxy_fix.py +169 -0
  158. pythonagent/vendor/werkzeug/middleware/shared_data.py +293 -0
  159. pythonagent/vendor/werkzeug/posixemulation.py +117 -0
  160. pythonagent/vendor/werkzeug/routing.py +2210 -0
  161. pythonagent/vendor/werkzeug/security.py +249 -0
  162. pythonagent/vendor/werkzeug/serving.py +1117 -0
  163. pythonagent/vendor/werkzeug/test.py +1123 -0
  164. pythonagent/vendor/werkzeug/testapp.py +241 -0
  165. pythonagent/vendor/werkzeug/urls.py +1138 -0
  166. pythonagent/vendor/werkzeug/useragents.py +202 -0
  167. pythonagent/vendor/werkzeug/utils.py +778 -0
  168. pythonagent/vendor/werkzeug/wrappers/__init__.py +36 -0
  169. pythonagent/vendor/werkzeug/wrappers/accept.py +50 -0
  170. pythonagent/vendor/werkzeug/wrappers/auth.py +33 -0
  171. pythonagent/vendor/werkzeug/wrappers/base_request.py +673 -0
  172. pythonagent/vendor/werkzeug/wrappers/base_response.py +700 -0
  173. pythonagent/vendor/werkzeug/wrappers/common_descriptors.py +341 -0
  174. pythonagent/vendor/werkzeug/wrappers/cors.py +100 -0
  175. pythonagent/vendor/werkzeug/wrappers/etag.py +304 -0
  176. pythonagent/vendor/werkzeug/wrappers/json.py +145 -0
  177. pythonagent/vendor/werkzeug/wrappers/request.py +49 -0
  178. pythonagent/vendor/werkzeug/wrappers/response.py +84 -0
  179. pythonagent/vendor/werkzeug/wrappers/user_agent.py +14 -0
  180. 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,4 @@
1
+ from .pika import intercept_pika
2
+
3
+ __all__ = ['intercept_pika']
4
+
@@ -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')
@@ -0,0 +1,6 @@
1
+ from __future__ import unicode_literals
2
+
3
+ from .pymongo import intercept_pymongo
4
+
5
+ __all__ = ['intercept_pymongo']
6
+