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,101 @@
1
+ import json
2
+
3
+ class BaseSpan(object):
4
+ def __init__(self, name, start_us, duration, status, meta, test_run, fpi, entry_fpi, nd_session_id, nv_session_id, page_id, full_fp):
5
+
6
+ self.trace_id = None
7
+ self.span_id = None
8
+ self.parent_id = None
9
+ self.name = name
10
+ self.start_us = start_us
11
+ self.duration = duration
12
+ self.status = status
13
+ self.meta = meta
14
+ """
15
+ self.meta = {
16
+ "span_kind": None,
17
+ "input": None,
18
+ "output": None,
19
+ "metadata": None
20
+ }
21
+ """
22
+ self.metrics = {}
23
+ self.test_run = test_run
24
+ self.fpi = fpi
25
+ self.entry_fpi =entry_fpi
26
+ self.nd_session_id = nd_session_id
27
+ self.nv_session_id = nv_session_id
28
+ self.page_id = page_id
29
+ self.full_fp = full_fp
30
+
31
+ def create_span_json(self):
32
+ span = {
33
+ "trace_id": self.trace_id,
34
+ "span_id": self.span_id,
35
+ "parent_id": self.parent_id,
36
+ "name": self.name,
37
+ "start_us": self.start_us,
38
+ "duration": self.duration,
39
+ "status": self.status,
40
+ "meta": self.meta,
41
+ "metrics": self.metrics,
42
+ "test_run":self.test_run,
43
+ "fpi":self.fpi,
44
+ "entry_fpi":self.entry_fpi,
45
+ "nd_session_id":self.nd_session_id,
46
+ "nv_session_id":self.nv_session_id,
47
+ "page_id":self.page_id,
48
+ "fp": self.full_fp
49
+ }
50
+
51
+ return json.dumps(span)
52
+
53
+
54
+
55
+ class ToolSpan(BaseSpan):
56
+ pass
57
+
58
+ class EmbeddingSpan(BaseSpan):
59
+ pass
60
+
61
+ class RetrievalSpan(BaseSpan):
62
+ pass
63
+
64
+
65
+ class LLMSpan(BaseSpan):
66
+
67
+ def __init__(self, fqm, start_time, duration, status, meta, metrics, test_run, fpi, entry_fpi, nd_session_id, nv_session_id, page_id, full_fp):
68
+ super().__init__(fqm, start_time, duration, status, meta, test_run, fpi, entry_fpi, nd_session_id, nv_session_id, page_id, full_fp)
69
+ self.metrics = metrics
70
+ """
71
+ self.metrics = {
72
+ "prompt_tokens": None,
73
+ "completion_tokens": None,
74
+ "total_tokens": None,
75
+ "prompt_tokens_details": {
76
+ "prompt_audio_tokens": None,
77
+ "prompt_cached_tokens": None
78
+ },
79
+ "completion_tokens_details": {
80
+ "completion_accepted_prediction_tokens": None,
81
+ "completion_rejected_prediction_tokens": None,
82
+ "completion_audio_tokens": None,
83
+ "completion_reasoning_tokens": None
84
+ }
85
+ }
86
+ """
87
+
88
+
89
+
90
+ """
91
+ class WorkFlowSpan(BaseSpan):
92
+ pass
93
+
94
+ class AgentSpan(BaseSpan):
95
+ pass
96
+
97
+ class TaskSpan(BaseSpan):
98
+ pass
99
+ """
100
+
101
+
@@ -0,0 +1,13 @@
1
+
2
+
3
+
4
+ """Interceptors for SQL databases.
5
+
6
+ """
7
+
8
+ from __future__ import unicode_literals
9
+
10
+ from . import mysql_connector, mysql_connector_cext, mysqldb, pymysql, psycopg2, dynamodb, botocores3
11
+
12
+ __all__ = ['pymysql', 'mysql_connector', 'mysql_connector_cext', 'mysqldb', 'psycopg2', 'dynamodb', 'botocores3']
13
+
@@ -0,0 +1,51 @@
1
+
2
+ """Interceptor for httplib/http.client.
3
+
4
+ """
5
+
6
+ from __future__ import unicode_literals
7
+ from ..base import ExitCallInterceptor
8
+ import time
9
+ #from functools import wraps
10
+ # from agent.internal.proxy import *
11
+ from pythonagent.utils import get_current_timestamp_in_ms
12
+
13
+
14
+ class BotocoreS3Interceptor(ExitCallInterceptor):
15
+
16
+ def _cav_s3_make_request(self, make_request, Endpoint, operation_model, request_dict):#, _agent):
17
+ try:
18
+ if operation_model.name != "GetObject": # PutItem and Scan in DynamoDB use the same function
19
+ return make_request(Endpoint, operation_model, request_dict)
20
+
21
+ method_name = "botocore.endpoint.Endpoint.make_request"
22
+ ctx = self.agent.get_transaction_context()
23
+ if ctx:
24
+ ctx.entry_point_fqm = method_name
25
+ query_string = operation_model.name
26
+ start_time = get_current_timestamp_in_ms()
27
+ url = request_dict["url"]
28
+ ip_handle = self.db_call_begin(0, None, query_string, url, start_time)
29
+
30
+ except Exception as e:
31
+ self.agent.logger.exception('Exception in S3 db_call_begin {}'.format(e))
32
+
33
+ endpiont_method = make_request(Endpoint, operation_model, request_dict)
34
+
35
+ try:
36
+ end_time = get_current_timestamp_in_ms()
37
+ duration = end_time - start_time
38
+ ctx = self.agent.get_transaction_context()
39
+ if ctx:
40
+ ctx.host_str = "s3"
41
+ ctx.status_code = 200
42
+ self.db_call_end(0, ip_handle, duration, start_time)
43
+ except Exception as e:
44
+ self.agent.logger.exception("Exception in S3 db_call_end {}".format(e))
45
+
46
+ return endpiont_method
47
+
48
+ def intercept_s3(agent, mod):
49
+ agent.logger.warning("Instrument module: botocore.endpoint{}".format(", mod: {}".format(mod) if mod else ""))
50
+ interceptor = BotocoreS3Interceptor(agent, mod.Endpoint)
51
+ interceptor.attach('make_request', patched_method_name='_cav_s3_make_request')
@@ -0,0 +1,285 @@
1
+
2
+ """Interceptors for dealing with DB-API 2.0 compatible libraries.
3
+
4
+ """
5
+
6
+ from __future__ import unicode_literals
7
+ import abc
8
+ import re
9
+ #import agent
10
+ #from agent.internal.proxy import *
11
+ from pythonagent.lang import str
12
+ #from pythonagentynamics.agent.core.registries import MissingConfigException
13
+ #from pythonagentynamics.agent.models.exitcalls import EXIT_DB, EXIT_SUBTYPE_DB
14
+ #from .. import HOST_PROPERTY_MAX_LEN, DB_NAME_PROPERTY_MAX_LEN, VENDOR_PROPERTY_MAX_LEN
15
+ from ..base import ExitCallInterceptor
16
+ from pythonagent.utils import generate_flow_path_id, get_utf8_bytes, get_current_timestamp_in_us, get_validated_duration
17
+
18
+ EXIT_DB = 1
19
+ EXIT_SUBTYPE_DB = 'DB'
20
+
21
+ HOST_PROPERTY_MAX_LEN = 50
22
+ DB_NAME_PROPERTY_MAX_LEN = 50
23
+ VENDOR_PROPERTY_MAX_LEN = 50
24
+
25
+ class MissingConfigException(Exception):
26
+ pass
27
+
28
+
29
+ #def get_db_backend(agent, host, port, dbname, vendor):
30
+ # if agent.backend_registry is None:
31
+ # raise MissingConfigException
32
+
33
+ # naming_format_string = '{HOST}:{PORT} - {DATABASE} - {VENDOR} - {VERSION}'
34
+ # host = host[:HOST_PROPERTY_MAX_LEN]
35
+ # dbname = dbname[:DB_NAME_PROPERTY_MAX_LEN]
36
+ # vendor = vendor[:VENDOR_PROPERTY_MAX_LEN]
37
+
38
+ # backend_properties = {
39
+ # 'VENDOR': vendor,
40
+ # 'HOST': host,
41
+ # 'PORT': str(port),
42
+ # 'DATABASE': dbname,
43
+ # 'VERSION': 'unknown',
44
+ # }
45
+
46
+ #return agent.backend_registry.get_backend(EXIT_DB, EXIT_SUBTYPE_DB, backend_properties, naming_format_string)
47
+ # return None
48
+
49
+
50
+ class DbAPICursorInterceptor(ExitCallInterceptor):
51
+
52
+ def __init__(self, agent, cls):
53
+ super(DbAPICursorInterceptor, self).__init__(agent, cls)
54
+ self.connection_properties = None
55
+
56
+ #print("going to get proxy instance (DbAPICursor Interceptor)")
57
+ #proxy = Proxy.getInstance()
58
+ #print("proxy handle = ",proxy )
59
+
60
+ def db_call_end(self, bt, exit_call, duration, start_time):
61
+ #self.agent.logger.info('Modulename: DbAPICursorInterceptor class inside db_call_end function')
62
+ # execute_result is intentionally not used here. Its purpose is to
63
+ # allow subclasses to override this method and use the value.
64
+ super(DbAPICursorInterceptor, self).db_call_end(bt, exit_call, duration, start_time)
65
+
66
+ def _execute(self, execute, cursor, operation, *args, **kwargs):
67
+ if self.agent.get_transaction_context() is None:
68
+ return execute(cursor, operation, *args, **kwargs)
69
+ exit_call = None
70
+ with self.log_exceptions():
71
+ self.agent.get_transaction_context().entry_point_fqm = str(execute.__module__ + "." + execute.__qualname__)
72
+ host, port, db_name, user, db_type = self.connection_properties
73
+ # format :- "PROTOCOL|HOST|PORT|URL|DBPRODNAME|DBNAME|DBPRODVER|DRIVERNAME|DRIVERVER|USERNAME|SERVICENAME"
74
+ self.agent.get_transaction_context().host_str = f"NA|{host}|{port}|NA|{db_type}|{db_name}|NA|NA|NA|{user}|NA"
75
+ db_start_time = 0
76
+
77
+ query_params = args
78
+ token_string = ""
79
+ if query_params:
80
+ if len(query_params) != 0:
81
+ for parameters in query_params:
82
+ counter = 0
83
+ if parameters:
84
+ for tokens in parameters:
85
+ token_string += "{}:{}\n".format(counter, tokens)
86
+ counter += 1
87
+ else:
88
+ token_string = None
89
+
90
+
91
+ #print("operation in db query in dbapi.py\n\n", operation)
92
+ backend = True
93
+
94
+ # host = None
95
+ #self.agent.logger.info("inside _execute funciton")
96
+ #self.agent.logger.info('Modulename: DbAPICursorInterceptor class inside _execute function')
97
+ self.agent.logger.info("Modulename: DbAPICursorInterceptor class || execute value is : {0}".format(execute))
98
+ self.agent.logger.info("Modulename: DbAPICursorInterceptor class || operation value is :{0}".format(str(operation)))
99
+ #self.agent.logger.info("execute: {}",execute,"cursor: {}",cursor,"operation:{} ",operation)
100
+ #print("cursor host: ", cursor.host)
101
+
102
+ #bt = self.agent.bt
103
+ bt = self.bt
104
+ if bt:
105
+ #print("bt value is ------------------",bt)
106
+ #connection = self.get_connection(cursor)
107
+ module = self.cls.__module__.lower()
108
+
109
+ if "psycopg2" in module:
110
+ mName = "psycopg2.connect"
111
+ self.agent.get_transaction_context().entry_point_fqm = mName
112
+
113
+ if backend and not hasattr(cursor, '_pythonagent_exit_call'):
114
+ db_start_time = get_current_timestamp_in_us()
115
+ self.agent.logger.debug("db_call_begin for _execute bt {} host {} query {} query_params {} db_start_time {}".format(bt, host, operation, token_string, db_start_time))
116
+ host_str = self.agent.get_transaction_context().host_str
117
+ exit_call = self.db_call_begin(bt, host, operation, token_string, db_start_time, host_str=host_str)
118
+ cursor._pythonagent_exit_call = exit_call
119
+ self.agent.get_transaction_context().db_callout_start_time = db_start_time
120
+
121
+
122
+ try:
123
+ result = execute(cursor, operation, pythonagent_exit_call=exit_call, *args, **kwargs)
124
+ except Exception as e:
125
+ self.agent.logger.exception("Error in application: {}".format(e))
126
+ try:
127
+ db_end_time = get_current_timestamp_in_us()
128
+ db_start_time = self.agent.get_transaction_context().db_callout_start_time
129
+ duration = get_validated_duration(db_start_time, db_end_time, "_execute")
130
+ self.agent.get_transaction_context().status_code = 500
131
+ self.agent.get_transaction_context().db_callout_start_time = 0
132
+ self.agent.logger.debug("db_call_end for _execute with exception bt {} ip_handle {} duration {} db_start_time {}".format(bt, exit_call, duration, db_start_time))
133
+ self.db_call_end(bt, exit_call, duration, db_start_time)
134
+ except Exception as e:
135
+ self.agent.logger.exception("Exception in Original Method DB Call End for dbapi execute {}".format(e))
136
+
137
+ try:
138
+ delattr(cursor, '_pythonagent_exit_call')
139
+ except AttributeError:
140
+ pass
141
+
142
+ raise
143
+
144
+ try:
145
+
146
+ db_end_time = get_current_timestamp_in_us()
147
+ db_start_time = self.agent.get_transaction_context().db_callout_start_time
148
+ duration = get_validated_duration(db_start_time, db_end_time, "_execute")
149
+
150
+ # Normally it's fine to just try to end the exit call even if we
151
+ # aren't sure it actually started. However for cases where we have
152
+ # several `execute` calls nested inside an `executemany` call, we do
153
+ # not want to end the exit call until the outer call is over.
154
+
155
+ if not exit_call:
156
+ self.agent.get_transaction_context().status_code = 200
157
+ self.agent.get_transaction_context().db_callout_start_time = 0
158
+ self.agent.logger.debug("db_call_end for _execute bt {} ip_handle {} duration {} db_start_time {}".format(bt, exit_call, duration, db_start_time))
159
+ self.db_call_end(bt, exit_call, duration, db_start_time)
160
+ try:
161
+ delattr(cursor, '_pythonagent_exit_call')
162
+ except AttributeError:
163
+ pass
164
+
165
+ except Exception as e:
166
+ self.agent.logger.exception("Exception in dbapi execute end{}".format(e))
167
+
168
+ return result
169
+
170
+ @abc.abstractmethod
171
+ def get_connection(self, cursor):
172
+ """Return the `Connection` object used to create this `Cursor`.
173
+
174
+ """
175
+ pass
176
+
177
+
178
+ class DbAPIConnectionInterceptor(ExitCallInterceptor):
179
+
180
+ def __init__(self, agent, cls, cursor_interceptor):
181
+ super(DbAPIConnectionInterceptor, self).__init__(agent, cls)
182
+ self.cursor_interceptor = cursor_interceptor
183
+ self.backend_properties = None
184
+
185
+ def attach(self, connect_func):
186
+ super(DbAPIConnectionInterceptor, self).attach(connect_func, patched_method_name='_connect')
187
+ super(DbAPIConnectionInterceptor, self).attach('cursor')
188
+
189
+ def db_call_end(self, bt, exit_call, duration, db_start_time):
190
+ # maybe_connection is intentionally not used here. Its purpose is to
191
+ # allow subclasses to override this method and use the value.
192
+ super(DbAPIConnectionInterceptor, self).db_call_end(bt, exit_call, duration, db_start_time)
193
+
194
+ def _connect(self, connect, connection, *args, **kwargs):
195
+ exit_call = None
196
+
197
+ with self.log_exceptions():
198
+
199
+ backend_properties = self.get_backend_properties(connection, *args, **kwargs)
200
+ self.backend_properties = backend_properties
201
+ if self.agent.get_transaction_context() is None:
202
+ maybe_connection = connect(connection, pythonagent_exit_call=None, *args, **kwargs)
203
+ return maybe_connection
204
+
205
+ mName = str(connect.__module__ + "." + connect.__qualname__)
206
+ self.agent.get_transaction_context().entry_point_fqm = mName
207
+ bt = self.bt
208
+ db_start_time = 0
209
+
210
+ backend = True
211
+
212
+ try:
213
+ connection._pythonagent_backend = backend
214
+ except MissingConfigException:
215
+ # If the agent has just started and doesn't have config yet,
216
+ # we cannot create and store a backend on the connection object.
217
+ # We store the backend properties instead so that the cursor
218
+ # interceptor can try again later.
219
+ connection._pythonagent_backend_properties = backend_properties
220
+ if bt:
221
+ db_start_time = get_current_timestamp_in_us()
222
+ self.agent.logger.debug("db_call_begin for _connect bt {} host {} query {} query_params {} db_start_time {}".format(bt, backend_properties[0], '', None, db_start_time))
223
+ #exit_call = self.db_call_begin(bt, backend_properties[0], '', None, db_start_time)
224
+ self.agent.get_transaction_context().db_callout_start_time = db_start_time
225
+
226
+ # The reason this is called `maybe_connection` is that different
227
+ # interceptors will return different values here. `connect` could
228
+ # be an __init__ method on a class, returning None, it could be a
229
+ # function which returns an initialized connection object, or even a
230
+ # method returning an async future object. The only reason we capture
231
+ # this value and pass it to `end_exit_call` is to allow subclasses to
232
+ # override the behaviour of `end_exit_call` (for example in the async
233
+ # case, to only end the exit call when the future is completed).
234
+
235
+ try:
236
+ maybe_connection = connect(connection, pythonagent_exit_call=exit_call, *args, **kwargs)
237
+ except Exception as e:
238
+ self.agent.logger.exception("Error in application: {}".format(e))
239
+ try:
240
+ db_end_time = get_current_timestamp_in_us()
241
+ db_start_time = self.agent.get_transaction_context().db_callout_start_time
242
+ duration = get_validated_duration(db_start_time, db_end_time, "_connect")
243
+ self.agent.get_transaction_context().status_code = 500
244
+ self.agent.get_transaction_context().db_callout_start_time = 0
245
+ self.agent.logger.debug("db_call_end for _connect with exception bt {} ip_handle {} duration {} db_start_time {}".format(bt, exit_call, duration, db_start_time))
246
+ #self.db_call_end(bt, exit_call, duration, db_start_time)
247
+ except Exception as e:
248
+ self.agent.logger.exception("Exception in Original Method DB Call End for dbapi connect {}".format(e))
249
+
250
+ raise
251
+
252
+ try:
253
+ db_end_time = get_current_timestamp_in_us()
254
+ db_start_time = self.agent.get_transaction_context().db_callout_start_time
255
+ duration = get_validated_duration(db_start_time, db_end_time, "_connect")
256
+ self.agent.get_transaction_context().status_code = 200
257
+ self.agent.get_transaction_context().db_callout_start_time = 0
258
+ self.agent.logger.debug("db_call_end for _connect bt {} ip_handle {} duration {} db_start_time {}".format(bt, exit_call, duration, db_start_time))
259
+ #self.db_call_end(bt, exit_call, duration, db_start_time)
260
+
261
+ except Exception as e:
262
+ self.agent.logger.exception("Exception in dbapi connect end{}".format(e))
263
+
264
+ return maybe_connection
265
+
266
+ def _cursor(self, cursor, connection, *args, **kwargs):
267
+ cursor_instance = cursor(connection, pythonagent_exit_call=None, *args, **kwargs)
268
+ with (self.log_exceptions()):
269
+ cursor_obj = self.cursor_interceptor(self.agent, type(cursor_instance))
270
+ cursor_obj.attach('execute',patched_method_name='_execute')
271
+ cursor_obj.connection_properties = self.backend_properties
272
+ return cursor_instance
273
+
274
+ @abc.abstractmethod
275
+ def get_backend_properties(self, connection, *args, **kwargs):
276
+ """Return a tuple of (host, port, database, vendor) for this connection.
277
+
278
+ The parameters passed to this function are the same as those passed to
279
+ the intercepted `connect` function.
280
+
281
+ WARNING: `connection` may not have been initialized when this
282
+ function is called; be careful.
283
+
284
+ """
285
+ pass
@@ -0,0 +1,90 @@
1
+
2
+ """Interceptor for httplib/http.client.
3
+
4
+ """
5
+
6
+ from __future__ import unicode_literals
7
+ from ..base import ExitCallInterceptor
8
+ import time
9
+ #from functools import wraps
10
+ # from agent.internal.proxy import *
11
+ from pythonagent.utils import get_current_timestamp_in_ms
12
+
13
+ # import agent
14
+ class BotocoreClientInterceptor(ExitCallInterceptor):
15
+ #print("INSIDE dynamodb.py BotocoreClientInterceptor class")
16
+
17
+ def bind__create_api_method(py_operation_name, operation_name, service_model,
18
+ *args, **kwargs):
19
+ return py_operation_name
20
+
21
+ def _cav_boto_api_method(self, _create_api_method, ClientCreator,py_operation_name, operation_name, service_mode, *args, **kwargs):
22
+
23
+ def _cav_wrapped_api_method(func, py_operation_name, _agent):
24
+ # operation_name = py_operation_name
25
+ agent = _agent
26
+ def wrapper(*args, **kwargs):
27
+ start_time = None
28
+ query_string = None
29
+ method_name = None
30
+ ip_handle = None
31
+
32
+ try:
33
+ if "TableName" in kwargs:
34
+ table_name = kwargs["TableName"]
35
+ else:
36
+ table_name = "default"
37
+
38
+ operation_name = py_operation_name
39
+ if operation_name is None:
40
+ operation_name = "default"
41
+
42
+ method_name = "botocore.client.ClientCreator._create_api_method"
43
+
44
+ query_string = str(table_name)+"."+str(operation_name)
45
+ start_time = get_current_timestamp_in_ms()
46
+ ctx = self.agent.get_transaction_context()
47
+ if ctx:
48
+ ctx.entry_point_fqm = method_name
49
+ bt = 0
50
+ db_host = None
51
+ ip_handle = self.db_call_begin(bt, db_host, query_string, "dynamodb", start_time)
52
+
53
+ except Exception as e:
54
+ self.agent.logger.exception("Some error occurred inside wrapper in method entry call {}".format(e))
55
+
56
+ results = func(*args, **kwargs)
57
+
58
+ try:
59
+ end_time = get_current_timestamp_in_ms()
60
+ duration = end_time - start_time
61
+ ctx = self.agent.get_transaction_context()
62
+ if ctx:
63
+ ctx.host_str = "dynamodb"
64
+ ctx.status_code = 200
65
+ self.db_call_end(0, ip_handle, duration, start_time)
66
+
67
+ except Exception as e:
68
+ self.agent.logger.exception("Some error occurred inside wrapper in method exit call {}".format(e))
69
+
70
+ return results
71
+
72
+ return wrapper
73
+
74
+ service_name = None
75
+ try:
76
+ service_name = service_mode.service_name.lower()
77
+ except Exception as e:
78
+ self.agent.logger.exception("Some error occurred inside _cav_boto_api_method {}".format(e))
79
+
80
+ api_method = _create_api_method(ClientCreator, py_operation_name, operation_name, service_mode, *args, **kwargs)
81
+
82
+ if service_name == "dynamodb":
83
+ return _cav_wrapped_api_method(api_method, py_operation_name, self.agent)
84
+ else:
85
+ return api_method
86
+
87
+ def intercept_dynamodb(agent, mod):
88
+ agent.logger.warning("Instrument module: botocore.client{}".format(", mod: {}".format(mod) if mod else ""))
89
+ interceptor = BotocoreClientInterceptor(agent, mod.ClientCreator)
90
+ interceptor.attach('_create_api_method', patched_method_name="_cav_boto_api_method")
@@ -0,0 +1,24 @@
1
+
2
+
3
+ """Intercept the mysql-connector-python package.
4
+
5
+ """
6
+
7
+ from __future__ import unicode_literals
8
+
9
+ from .dbapi import DbAPIConnectionInterceptor, DbAPICursorInterceptor
10
+
11
+
12
+ class MySQLConnectionInterceptor(DbAPIConnectionInterceptor):
13
+ def get_backend_properties(self, conn, *args, **kwargs):
14
+ return conn._host, conn._port, conn._database, conn._user, 'MYSQL'
15
+
16
+
17
+ class MySQLCursorInterceptor(DbAPICursorInterceptor):
18
+ def get_connection(self, cursor):
19
+ return cursor._connection
20
+
21
+
22
+ def intercept_mysql_connector_connection(agent, mod):
23
+ agent.logger.warning("Instrument module: mysql.connector.connection{}".format(", mod: {}".format(mod) if mod else ""))
24
+ MySQLConnectionInterceptor(agent, mod.MySQLConnection, MySQLCursorInterceptor).attach('_open_connection')
@@ -0,0 +1,24 @@
1
+
2
+
3
+ """Intercept the mysql-connector-python package.
4
+
5
+ """
6
+
7
+ from __future__ import unicode_literals
8
+
9
+ from .dbapi import DbAPIConnectionInterceptor, DbAPICursorInterceptor
10
+
11
+
12
+ class CMySQLConnectionInterceptor(DbAPIConnectionInterceptor):
13
+ def get_backend_properties(self, conn, *args, **kwargs):
14
+ return conn._host, conn._port, conn._database, conn._user, 'MYSQL'
15
+
16
+
17
+ class CMySQLCursorInterceptor(DbAPICursorInterceptor):
18
+ def get_connection(self, cursor):
19
+ return cursor._cnx
20
+
21
+
22
+ def intercept_mysql_connector_cext_connection(agent, mod):
23
+ agent.logger.warning("Instrument module: mysql.connector.connection_cext{}".format(", mod: {}".format(mod) if mod else ""))
24
+ CMySQLConnectionInterceptor(agent, mod.CMySQLConnection, CMySQLCursorInterceptor).attach('_open_connection')
@@ -0,0 +1,43 @@
1
+
2
+
3
+ """Intercept the MySQLdb package.
4
+
5
+ """
6
+
7
+ from __future__ import unicode_literals
8
+ import weakref
9
+
10
+ from .dbapi import DbAPIConnectionInterceptor, DbAPICursorInterceptor
11
+
12
+
13
+ class MySQLdbConnectionInterceptor(DbAPIConnectionInterceptor):
14
+ def get_backend_properties(self, conn, *args, **kwargs):
15
+ self.agent.logger.info('Modulename: MySQLdbCursorInterceptor class inside get_backend_properties function')
16
+ host = kwargs.get('host', 'localhost')
17
+ #self.agent.get_transaction_context().dbhost = host
18
+ port = kwargs.get('port', '3306')
19
+ db = kwargs.get('database', kwargs.get('db', ''))
20
+ user = kwargs.get('user', "mysqldb_user")
21
+ db_type = "MYSQL"
22
+ #format :- "PROTOCOL|HOST|PORT|URL|DBPRODNAME|DBNAME|DBPRODVER|DRIVERNAME|DRIVERVER|USERNAME|SERVICENAME"
23
+ # host_name_str = f"NA|{host}|{port}|NA|MYSQL|{db}|NA|NA|NA|{kwargs['user']}|NA"
24
+ # print("host_name_str", host_name_str)
25
+ # self.agent.get_transaction_context().host_str = host_name_str
26
+ # print("self.agent.get_transaction_context().host_str", self.agent.get_transaction_context().host_str)
27
+ return host, port, db, user, db_type
28
+
29
+
30
+ class MySQLdbCursorInterceptor(DbAPICursorInterceptor):
31
+ def get_connection(self, cursor):
32
+ self.agent.logger.info('Modulename: MySQLdbCursorInterceptor class inside get_connection function ')
33
+ conn = cursor.connection
34
+ self.agent.logger.info("Modulename: MySQLdbCursorInterceptor class inside get_connection function connection is {0} ".format(conn))
35
+
36
+ if isinstance(conn, weakref.ReferenceType):
37
+ conn = conn()
38
+ return conn
39
+
40
+
41
+ def intercept_MySQLdb_connection(agent, mod):
42
+ agent.logger.warning("Instrument module: MySQLdb.connections{}".format(", mod: {}".format(mod) if mod else ""))
43
+ MySQLdbConnectionInterceptor(agent, mod.Connection, MySQLdbCursorInterceptor).attach('__init__')