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,1651 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from pythonagent.lib import get_ident
|
|
3
|
+
import ctypes
|
|
4
|
+
from ctypes import create_string_buffer
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
import time
|
|
8
|
+
import platform
|
|
9
|
+
from pythonagent.agent.probes.havoc.havoc_manager import NDNetHavocMonitor, NDHavocException
|
|
10
|
+
|
|
11
|
+
from pythonagent.agent.internal import udp
|
|
12
|
+
from pythonagent.agent.internal.provider import ContextProvider, CurrentBTProvider, StatusCodeProvider
|
|
13
|
+
from pythonagent.agent.probes.frameworks import wsgi # aiflagset
|
|
14
|
+
from pythonagent.agent.probes.Instrumentation.find import find
|
|
15
|
+
from pythonagent.agent.internal.metadata.agent_meta_data import build_metadata_block
|
|
16
|
+
from pythonagent.utils import generate_flow_path_id, get_utf8_bytes, get_current_timestamp_in_us, process_raw_havoc_message
|
|
17
|
+
import threading,gc
|
|
18
|
+
from pythonagent.agent.internal.proc_compat import get_rss_bytes
|
|
19
|
+
from threading import Timer
|
|
20
|
+
from pythonagent.agent.internal.thread_dump import dumpstacks
|
|
21
|
+
from pythonagent.agent.internal.heap_dump import create_heap_dump_muppy
|
|
22
|
+
from pythonagent.utils import get_current_timestamp_in_us
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class RepeatedTimer(object):
|
|
26
|
+
def __init__(self, interval, function, *args, **kwargs):
|
|
27
|
+
self._timer = None
|
|
28
|
+
self.interval = interval
|
|
29
|
+
self.function = function
|
|
30
|
+
self.args = args
|
|
31
|
+
self.kwargs = kwargs
|
|
32
|
+
self.is_running = False
|
|
33
|
+
self.start()
|
|
34
|
+
|
|
35
|
+
def _run(self):
|
|
36
|
+
self.is_running = False
|
|
37
|
+
self.start()
|
|
38
|
+
self.function(*self.args, **self.kwargs)
|
|
39
|
+
def start(self):
|
|
40
|
+
if not self.is_running:
|
|
41
|
+
self._timer = Timer(self.interval, self._run)
|
|
42
|
+
self._timer.start()
|
|
43
|
+
self.is_running = True
|
|
44
|
+
|
|
45
|
+
def stop(self):
|
|
46
|
+
self._timer.cancel()
|
|
47
|
+
self.is_running = False
|
|
48
|
+
|
|
49
|
+
class TransactionContext(object):
|
|
50
|
+
def __init__(self):
|
|
51
|
+
self.nd_init_done = None
|
|
52
|
+
self.request_id = None
|
|
53
|
+
self.api_request_id = None
|
|
54
|
+
self.aws_request_id = None
|
|
55
|
+
self.function_name = None
|
|
56
|
+
self.bt_id = None
|
|
57
|
+
self.tier_callout_type = None
|
|
58
|
+
self.tier_callout_start_time = 0
|
|
59
|
+
self.db_callout_start_time = 0
|
|
60
|
+
self.backend_header = None
|
|
61
|
+
self.http_request_type = None
|
|
62
|
+
self.tier_name = None
|
|
63
|
+
self.server_name = None
|
|
64
|
+
self.instance_name = None
|
|
65
|
+
self.url_path = None
|
|
66
|
+
self.flow_path_id = None
|
|
67
|
+
self.havoc_applied = False
|
|
68
|
+
self.fp_topo = None
|
|
69
|
+
self.host_str = None
|
|
70
|
+
self.callout_id = 0
|
|
71
|
+
self.btname = None
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class Agent(object):
|
|
76
|
+
"""The entry point for the Python agent.
|
|
77
|
+
|
|
78
|
+
"""
|
|
79
|
+
_instance = None
|
|
80
|
+
@staticmethod
|
|
81
|
+
def get_instance():
|
|
82
|
+
if Agent._instance is None:
|
|
83
|
+
Agent()
|
|
84
|
+
return Agent._instance
|
|
85
|
+
|
|
86
|
+
def __init__(self):
|
|
87
|
+
if Agent._instance is not None:
|
|
88
|
+
raise Exception("Agent class is a singleton! Use get_instance()")
|
|
89
|
+
|
|
90
|
+
Agent._instance = self
|
|
91
|
+
|
|
92
|
+
super(Agent, self).__init__()
|
|
93
|
+
self.logger = logging.getLogger('pythonagent.agent')
|
|
94
|
+
self.aiobj = None
|
|
95
|
+
# if os.environ['CAV_RUNNING_MODE']=='0':
|
|
96
|
+
# os.environ['CAV_RUNNING_MODE']='1'
|
|
97
|
+
# return
|
|
98
|
+
self.app_id = None
|
|
99
|
+
self.tier_id = None
|
|
100
|
+
self.node_id = None
|
|
101
|
+
self.account_guid = None
|
|
102
|
+
self.controller_guid = None
|
|
103
|
+
self._tx_factory = None
|
|
104
|
+
|
|
105
|
+
# Services
|
|
106
|
+
# self.proxy_control_svc = None
|
|
107
|
+
# self.config_svc = None
|
|
108
|
+
# self.tx_svc = None
|
|
109
|
+
# self.snapshot_svc = None
|
|
110
|
+
|
|
111
|
+
self.active_bts = set()
|
|
112
|
+
self.current_bts = {}
|
|
113
|
+
self.transaction_context = {}
|
|
114
|
+
self.eum_config = None
|
|
115
|
+
|
|
116
|
+
self.nd_init_done = None
|
|
117
|
+
self.last_forced_snapshot = 0
|
|
118
|
+
self.lib = None
|
|
119
|
+
self.fp_topo = None
|
|
120
|
+
|
|
121
|
+
if "CAV_APP_AGENT_ENV" in os.environ:
|
|
122
|
+
if os.environ['CAV_APP_AGENT_ENV'] == "AWS_LAMBDA":
|
|
123
|
+
self.cav_env = "AWS_LAMBDA"
|
|
124
|
+
else:
|
|
125
|
+
self.cav_env = "NATIVE"
|
|
126
|
+
else:
|
|
127
|
+
self.cav_env = "NATIVE"
|
|
128
|
+
|
|
129
|
+
if "CAV_APP_AGENT_TIER" in os.environ:
|
|
130
|
+
self.tier_name = os.environ.get("CAV_APP_AGENT_TIER")
|
|
131
|
+
else:
|
|
132
|
+
self.tier_name = "default"
|
|
133
|
+
|
|
134
|
+
if "CAV_APP_AGENT_SERVER" in os.environ:
|
|
135
|
+
self.server_name = os.environ.get("CAV_APP_AGENT_SERVER")
|
|
136
|
+
else:
|
|
137
|
+
self.server_name = "default"
|
|
138
|
+
|
|
139
|
+
if "CAV_APP_AGENT_INSTANCE" in os.environ:
|
|
140
|
+
self.instance_name = os.environ.get("CAV_APP_AGENT_INSTANCE")
|
|
141
|
+
self.function_name = os.environ.get("CAV_APP_AGENT_INSTANCE")
|
|
142
|
+
else:
|
|
143
|
+
self.instance_name = "default"
|
|
144
|
+
self.function_name = "default"
|
|
145
|
+
|
|
146
|
+
self.nd_cookie_key = None
|
|
147
|
+
self.nv_cookie_key = None
|
|
148
|
+
self.cookie_method_position = None
|
|
149
|
+
self.cookie_domain = None
|
|
150
|
+
self.header_in_response = None
|
|
151
|
+
self.disable_nd_nv = False
|
|
152
|
+
self.exception_stack_depth = 50
|
|
153
|
+
self.test_running = True
|
|
154
|
+
self.nf_enabled = False
|
|
155
|
+
|
|
156
|
+
self.start()
|
|
157
|
+
|
|
158
|
+
if self.cav_env == "NATIVE":
|
|
159
|
+
self.ai_wrapper_begin()
|
|
160
|
+
self.ad_wrapper()
|
|
161
|
+
self.register_nd_cookie_callback()
|
|
162
|
+
self.gc_nd_status_callback()
|
|
163
|
+
self.thread_dump_callback()
|
|
164
|
+
self.nd_pythread_status_callback()
|
|
165
|
+
self.register_havoc_callback()
|
|
166
|
+
self.get_nf_status()
|
|
167
|
+
# self.register_test_status_callback()
|
|
168
|
+
# self.thd_wrapper()
|
|
169
|
+
# self.ai_wrapper_end()
|
|
170
|
+
# self.ai_wrapper_begin()
|
|
171
|
+
|
|
172
|
+
self.current_status_code = {}
|
|
173
|
+
|
|
174
|
+
self.havoc_monitor = NDNetHavocMonitor.get_instance()
|
|
175
|
+
|
|
176
|
+
self.application_loggers = set()
|
|
177
|
+
|
|
178
|
+
if self.cav_env == "NATIVE":
|
|
179
|
+
try:
|
|
180
|
+
self.gc_monitor_rt = RepeatedTimer(60, self.heap_gc_stats)
|
|
181
|
+
self.thread_monitor_rt = RepeatedTimer(60, self.thread_stats)
|
|
182
|
+
self.refresh_config_rt = RepeatedTimer(25, self.havoc_monitor.refresh_configs, self)
|
|
183
|
+
except Exception as e:
|
|
184
|
+
self.logger.info("Exception while starting GC thread : {}".format(e))
|
|
185
|
+
|
|
186
|
+
self.context_provider = ContextProvider()
|
|
187
|
+
self.currentbt_provider = CurrentBTProvider()
|
|
188
|
+
self.statuscode_provider = StatusCodeProvider()
|
|
189
|
+
|
|
190
|
+
def start(self):
|
|
191
|
+
# Use NDHOME env variable to locate libndsdk_py.so, fallback to default if missing
|
|
192
|
+
ndhome = os.environ.get('NDHOME')
|
|
193
|
+
path = os.path.join(ndhome,'python' ,'libs', 'libndsdk_py.so')
|
|
194
|
+
|
|
195
|
+
if not os.path.exists(path):
|
|
196
|
+
path = '/usr/local/lib/libndsdk_py.so'
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
if self.cav_env == "NATIVE":
|
|
201
|
+
self.lib = self.load_common_lib(path)
|
|
202
|
+
self.register_nv_cookie_callback()
|
|
203
|
+
self.register_exception_stack_depth_callback()
|
|
204
|
+
self.register_instr_prof_callback()
|
|
205
|
+
self.register_heap_dump_callback()
|
|
206
|
+
|
|
207
|
+
#self.logger.info("going to start sdk_init()")
|
|
208
|
+
self.sdk_init()
|
|
209
|
+
#self.logger.info("sdk_init() done")
|
|
210
|
+
# self.nd_init_done = True
|
|
211
|
+
os.environ['nd_init_done'] = '1'
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def stop(self):
|
|
215
|
+
"""Stop the agent from doing anything else.
|
|
216
|
+
|
|
217
|
+
Ideally this will stop any interceptors from doing anything, it will
|
|
218
|
+
disconnect all ties to the proxy etc etc.
|
|
219
|
+
|
|
220
|
+
"""
|
|
221
|
+
self.nd_init_done = False
|
|
222
|
+
os.environ['nd_init_done'] = '0'
|
|
223
|
+
|
|
224
|
+
# @staticmethod
|
|
225
|
+
def getInstance(self):
|
|
226
|
+
"""Static Access Method"""
|
|
227
|
+
if self.start.__shared_instance is None:
|
|
228
|
+
# Proxy()
|
|
229
|
+
self.start()
|
|
230
|
+
# return Proxy.__shared_instance
|
|
231
|
+
return self.start.__shared_instance
|
|
232
|
+
|
|
233
|
+
# @profile
|
|
234
|
+
def load_common_lib(self, lib_path):
|
|
235
|
+
|
|
236
|
+
self.lib = ctypes.cdll.LoadLibrary(lib_path)
|
|
237
|
+
# self.lib.nd_init2.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
|
|
238
|
+
|
|
239
|
+
################
|
|
240
|
+
# DECLARATIONS
|
|
241
|
+
################
|
|
242
|
+
|
|
243
|
+
self.lib.nd_method_entry.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_longlong]
|
|
244
|
+
self.lib.nd_method_exit.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_longlong, ctypes.c_longlong, ctypes.c_longlong, ctypes.POINTER(ctypes.POINTER(ctypes.c_char_p))]
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
self.lib.nd_bt_begin.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_longlong]
|
|
248
|
+
self.lib.nd_bt_begin.restype = ctypes.c_void_p
|
|
249
|
+
|
|
250
|
+
self.lib.nd_bt_end.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_longlong, ctypes.c_longlong, ctypes.POINTER(ctypes.POINTER(ctypes.c_char_p))]
|
|
251
|
+
self.lib.nd_bt_end.restype = ctypes.c_int
|
|
252
|
+
|
|
253
|
+
self.lib.nd_bt_store.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
|
|
254
|
+
|
|
255
|
+
self.lib.nd_ip_db_callout_begin.argtypes = [ctypes.c_char_p, ctypes.c_void_p, ctypes.c_char_p,ctypes.c_char_p, ctypes.c_longlong]
|
|
256
|
+
self.lib.nd_ip_db_callout_begin.restype = ctypes.c_int
|
|
257
|
+
|
|
258
|
+
self.lib.nd_ip_db_callout_end.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_longlong, ctypes.c_longlong, ctypes.POINTER(ctypes.POINTER(ctypes.c_char_p))]
|
|
259
|
+
self.lib.nd_ip_db_callout_end.restype = ctypes.c_int
|
|
260
|
+
|
|
261
|
+
self.lib.nd_ip_http_callout_begin.argtypes = [ctypes.c_char_p,ctypes.c_void_p, ctypes.c_char_p]
|
|
262
|
+
self.lib.nd_ip_http_callout_begin.restype = ctypes.c_int
|
|
263
|
+
|
|
264
|
+
self.lib.nd_ip_http_callout_end.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_longlong, ctypes.c_longlong, ctypes.POINTER(ctypes.POINTER(ctypes.c_char_p)), ctypes.c_longlong]
|
|
265
|
+
self.lib.nd_ip_http_callout_end.restype = ctypes.c_int
|
|
266
|
+
|
|
267
|
+
self.lib.sdk_getTopoFpStr.argtypes = [ctypes.c_void_p]
|
|
268
|
+
self.lib.sdk_getTopoFpStr.restype = ctypes.POINTER(ctypes.c_char_p)
|
|
269
|
+
|
|
270
|
+
self.lib.sdk_getNFStatus.argtypes = None
|
|
271
|
+
self.lib.sdk_getNFStatus.restype = ctypes.c_int
|
|
272
|
+
|
|
273
|
+
self.lib.sdk_get_propagation_header.argtypes = [ctypes.c_void_p]
|
|
274
|
+
self.lib.sdk_get_propagation_header.restype = ctypes.POINTER(ctypes.c_char_p)
|
|
275
|
+
|
|
276
|
+
self.lib.sdk_getNdBuild.argtypes = None
|
|
277
|
+
self.lib.sdk_getNdBuild.restype = ctypes.c_char_p
|
|
278
|
+
|
|
279
|
+
#self.lib.sdk_free_memory.argtypes = [ctypes.c_char_p]
|
|
280
|
+
|
|
281
|
+
self.lib.handleUploadDownload.argtypes = [ctypes.c_char_p]
|
|
282
|
+
self.lib.handleUploadDownload.restype = ctypes.c_void_p
|
|
283
|
+
|
|
284
|
+
self.lib.sdk_getNDSessionCookie.argtypes = [ctypes.c_void_p]
|
|
285
|
+
self.lib.sdk_getNDSessionCookie.restype = ctypes.POINTER(ctypes.c_char_p)
|
|
286
|
+
|
|
287
|
+
self.lib.get_custom_nd_header.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_longlong]
|
|
288
|
+
self.lib.get_custom_nd_header.restype = ctypes.c_char_p
|
|
289
|
+
|
|
290
|
+
self.lib.sendGCReport.argtypes = [ctypes.c_int,ctypes.c_char_p]
|
|
291
|
+
|
|
292
|
+
self.lib.sdk_get_otl_traceparent.argtypes = [ctypes.c_void_p]
|
|
293
|
+
self.lib.sdk_get_otl_traceparent.restype = ctypes.POINTER(ctypes.c_char_p)
|
|
294
|
+
|
|
295
|
+
self.lib.sdk_get_otl_tracestate.argtypes = [ctypes.c_void_p]
|
|
296
|
+
self.lib.sdk_get_otl_tracestate.restype = ctypes.POINTER(ctypes.c_char_p)
|
|
297
|
+
|
|
298
|
+
self.lib.getstacktracearray.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p,
|
|
299
|
+
ctypes.c_char_p,
|
|
300
|
+
ctypes.c_char_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p]
|
|
301
|
+
|
|
302
|
+
self.lib.sdk_httpReqRespWrapper.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_int]
|
|
303
|
+
|
|
304
|
+
self.lib.havoc_response_from_agent.argtypes = [ctypes.c_char_p]
|
|
305
|
+
|
|
306
|
+
self.lib.sdk_dumpLogMessage.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
|
|
307
|
+
self.lib.sdk_dumpLogMessage.restype = ctypes.c_void_p
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
self.lib.sdk_getTierName.argtypes = []
|
|
313
|
+
self.lib.sdk_getTierName.restype = ctypes.c_char_p
|
|
314
|
+
|
|
315
|
+
self.lib.sdk_getAppServerName.argtypes = []
|
|
316
|
+
self.lib.sdk_getAppServerName.restype = ctypes.c_char_p
|
|
317
|
+
|
|
318
|
+
self.lib.sdk_getAppName.argtypes = []
|
|
319
|
+
self.lib.sdk_getAppName.restype = ctypes.c_char_p
|
|
320
|
+
|
|
321
|
+
self.lib.sdk_getCurrentTR.argtypes = []
|
|
322
|
+
self.lib.sdk_getCurrentTR.restype = ctypes.c_int
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
self.lib.sdk_getBTName.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p]
|
|
328
|
+
self.lib.sdk_getBTName.restype = ctypes.POINTER(ctypes.c_char_p)
|
|
329
|
+
|
|
330
|
+
self.lib.sdk_getBciInstrSessionPctVal.argtypes=[]
|
|
331
|
+
self.lib.sdk_getBciInstrSessionPctVal.restype=ctypes.c_int
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
self.lib.sdk_UpdateBTCounters.argtypes=[ctypes.c_char_p, ctypes.c_int, ctypes.c_double, ctypes.c_long, ctypes.c_double, ctypes.c_double, ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.POINTER(ctypes.c_long)]
|
|
336
|
+
self.lib.sdk_UpdateBTCounters.restype=ctypes.c_void_p
|
|
337
|
+
|
|
338
|
+
self.lib.sdk_UpdateIPCounters.argtypes = [ctypes.c_char_p, ctypes.c_double, ctypes.c_long, ctypes.c_double, ctypes.c_double, ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.POINTER(ctypes.c_long), ctypes.c_char_p, ctypes.c_char_p]
|
|
339
|
+
self.lib.sdk_UpdateIPCounters.restype = ctypes.c_void_p
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
self.lib.sdk_settingBackendNameOtel.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
|
|
343
|
+
self.lib.sdk_settingBackendNameOtel.restype = ctypes.POINTER(ctypes.c_char_p)
|
|
344
|
+
|
|
345
|
+
|
|
346
|
+
self.lib.sdk_getTierCallOutOtel.argtypes = [ctypes.c_char_p, ctypes.c_longlong]
|
|
347
|
+
self.lib.sdk_getTierCallOutOtel.restype = ctypes.POINTER(ctypes.c_char_p)
|
|
348
|
+
|
|
349
|
+
self.lib.sdk_setTierCallOutOtel.argtypes = [ctypes.c_char_p]
|
|
350
|
+
self.lib.sdk_setTierCallOutOtel.restype = ctypes.c_void_p
|
|
351
|
+
|
|
352
|
+
self.lib.sdk_UpdateIPCountersUsingSpan.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_double, ctypes.c_int]
|
|
353
|
+
self.lib.sdk_UpdateIPCountersUsingSpan.restype = ctypes.c_void_p
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
self.lib.sdk_getDelayAtCurrentInstant.argtypes = [ctypes.c_long, ctypes.c_long, ctypes.c_long, ctypes.c_long, ctypes.c_long]
|
|
357
|
+
self.lib.sdk_getDelayAtCurrentInstant.restype = None
|
|
358
|
+
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
# self.lib.register_AI_end_callback.argtypes = [ctypes.c_char_p]
|
|
364
|
+
|
|
365
|
+
#self.lib.getDelayAtCurrentInstant.argtypes = [ctypes.c_long, ctypes.c_long, ctypes.c_long, ctypes.c_long, ctypes.c_long]
|
|
366
|
+
|
|
367
|
+
################
|
|
368
|
+
# CALLBACKS
|
|
369
|
+
################
|
|
370
|
+
|
|
371
|
+
CB_FTYPE_DOUBLE_DOUBLE = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_int, ctypes.c_longlong,
|
|
372
|
+
ctypes.c_longlong, ctypes.c_char_p)
|
|
373
|
+
self.c_startaisession = CB_FTYPE_DOUBLE_DOUBLE(self.startaisession)
|
|
374
|
+
|
|
375
|
+
ai_end_ftype = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p)
|
|
376
|
+
self.c_endaisession = ai_end_ftype(self.endaisessioncc)
|
|
377
|
+
|
|
378
|
+
ftype_autodiscovery = ctypes.CFUNCTYPE(ctypes.c_void_p, # Return type
|
|
379
|
+
ctypes.POINTER(ctypes.c_char_p), # methodFiltersPatternList
|
|
380
|
+
ctypes.POINTER(ctypes.c_char_p), # classFiltersPatternList
|
|
381
|
+
ctypes.c_int, # methodListLength
|
|
382
|
+
ctypes.c_int) # classListLength
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
self.autodiscovery_c = ftype_autodiscovery(self.autodiscovery_py)
|
|
386
|
+
|
|
387
|
+
ftype_exception_stack_depth = ctypes.CFUNCTYPE(ctypes.c_void_p, # Return type
|
|
388
|
+
ctypes.c_int) # Stack Depth
|
|
389
|
+
|
|
390
|
+
self.exception_stack_depth_c=ftype_exception_stack_depth(self.exception_stack_depth_py)
|
|
391
|
+
|
|
392
|
+
thd_ftype = ctypes.CFUNCTYPE(ctypes.c_char_p)
|
|
393
|
+
self.c_thd = thd_ftype(self.thd)
|
|
394
|
+
|
|
395
|
+
ftype_nd_cookie = ctypes.CFUNCTYPE(ctypes.c_void_p, # Pointer to Python Function
|
|
396
|
+
ctypes.c_char_p, # char *name
|
|
397
|
+
ctypes.c_char_p, # char *domain
|
|
398
|
+
ctypes.c_int, # int rheader
|
|
399
|
+
ctypes.c_int, # int mpos
|
|
400
|
+
ctypes.c_longlong) # long long int duration
|
|
401
|
+
|
|
402
|
+
self.nd_cookie_callback_c = ftype_nd_cookie(self.nd_cookie_callback_py)
|
|
403
|
+
|
|
404
|
+
ftype_nd_gc_status = ctypes.CFUNCTYPE(ctypes.c_void_p, # Pointer to Python Function
|
|
405
|
+
ctypes.c_int) # int status
|
|
406
|
+
|
|
407
|
+
self.nd_gcstatus_callback_c = ftype_nd_gc_status(self.nd_gcstatus_callback_py)
|
|
408
|
+
|
|
409
|
+
ftype_nd_python_thread_status = ctypes.CFUNCTYPE(ctypes.c_void_p, # Pointer to Python Function
|
|
410
|
+
ctypes.c_int) # int status
|
|
411
|
+
self.nd_pythread_status_callback_c = ftype_nd_python_thread_status(self.nd_pythread_status_callback_py)
|
|
412
|
+
|
|
413
|
+
thread_dump_ftype = ctypes.CFUNCTYPE(ctypes.c_char_p)
|
|
414
|
+
self.nd_thread_dump_callback_c = thread_dump_ftype(self.nd_thread_dump_callback_py)
|
|
415
|
+
|
|
416
|
+
ftype_nv_cookie = ctypes.CFUNCTYPE(ctypes.c_void_p, # Pointer to Python Function
|
|
417
|
+
ctypes.c_char_p) # char *name
|
|
418
|
+
|
|
419
|
+
self.nv_cookie_callback_c = ftype_nv_cookie(self.nv_cookie_callback_py)
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
ftype_havoc_message = ctypes.CFUNCTYPE(ctypes.c_void_p, # Return type
|
|
423
|
+
ctypes.c_char_p) # Havoc Message
|
|
424
|
+
|
|
425
|
+
ftype_heap_dump = ctypes.CFUNCTYPE(ctypes.c_char_p)
|
|
426
|
+
self.heap_dump_c = ftype_heap_dump(self.heap_dump_py)
|
|
427
|
+
|
|
428
|
+
self.receive_havoc_message_c = ftype_havoc_message(self.receive_havoc_message_py)
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
self.logger.info("load common lib -> lib.obj :{0}".format(self.lib))
|
|
432
|
+
|
|
433
|
+
ftype_test_status_callback = ctypes.CFUNCTYPE(ctypes.c_void_p, # Return type
|
|
434
|
+
ctypes.c_int) # Test Status
|
|
435
|
+
|
|
436
|
+
self.test_status_callback_c = ftype_test_status_callback(self.test_status_callback_py)
|
|
437
|
+
|
|
438
|
+
ftype_instr_prof_callback = ctypes.CFUNCTYPE(ctypes.c_void_p, # Return type
|
|
439
|
+
ctypes.c_char_p) # Test Status
|
|
440
|
+
|
|
441
|
+
self.instr_prof_callback_c = ftype_instr_prof_callback(self.instr_prof_callback_py)
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
return self.lib
|
|
445
|
+
|
|
446
|
+
###############################
|
|
447
|
+
# GET VALUES FROM COMMONLIB
|
|
448
|
+
###############################
|
|
449
|
+
|
|
450
|
+
def sdk_getNDSessionCookie(self, bt):
|
|
451
|
+
if not self.get_current_bt():
|
|
452
|
+
return None
|
|
453
|
+
nd_cookie_value = self.lib.sdk_getNDSessionCookie(bt)
|
|
454
|
+
nd_cookie_value_py = ctypes.cast(nd_cookie_value, ctypes.c_char_p).value
|
|
455
|
+
self.lib.sdk_free_memory(nd_cookie_value)
|
|
456
|
+
return nd_cookie_value_py
|
|
457
|
+
|
|
458
|
+
def get_nd_header(self, bt, backend_name, unique_id):
|
|
459
|
+
if not self.get_current_bt():
|
|
460
|
+
return None
|
|
461
|
+
backend_name_c = create_string_buffer(get_utf8_bytes(backend_name))
|
|
462
|
+
header = self.lib.get_custom_nd_header(ctypes.c_void_p(bt), backend_name_c, ctypes.c_longlong(unique_id))
|
|
463
|
+
del backend_name_c
|
|
464
|
+
return header
|
|
465
|
+
|
|
466
|
+
def get_trace_headers(self, bt):
|
|
467
|
+
if not self.get_current_bt():
|
|
468
|
+
return None, None
|
|
469
|
+
|
|
470
|
+
traceparent = self.lib.sdk_get_otl_traceparent(bt)
|
|
471
|
+
traceparent_py = ctypes.cast(traceparent, ctypes.c_char_p).value
|
|
472
|
+
self.lib.sdk_free_memory(traceparent)
|
|
473
|
+
|
|
474
|
+
tracestate = self.lib.sdk_get_otl_tracestate(bt)
|
|
475
|
+
tracestate_py = ctypes.cast(tracestate, ctypes.c_char_p).value
|
|
476
|
+
self.lib.sdk_free_memory(tracestate)
|
|
477
|
+
|
|
478
|
+
return traceparent_py, tracestate_py
|
|
479
|
+
|
|
480
|
+
def sdk_getTopoFpStr(self, bt):
|
|
481
|
+
if not self.get_current_bt():
|
|
482
|
+
return None
|
|
483
|
+
topo = None
|
|
484
|
+
topo_py = None
|
|
485
|
+
if bt:
|
|
486
|
+
topo = self.lib.sdk_getTopoFpStr(bt)
|
|
487
|
+
topo_py = ctypes.cast(topo, ctypes.c_char_p).value
|
|
488
|
+
self.lib.sdk_free_memory(topo)
|
|
489
|
+
if topo_py:
|
|
490
|
+
topo_py = topo_py.decode()
|
|
491
|
+
return topo_py
|
|
492
|
+
|
|
493
|
+
def sdk_get_propagation_header(self,bt):
|
|
494
|
+
if not self.get_current_bt():
|
|
495
|
+
return None
|
|
496
|
+
prop_headers = self.lib.sdk_get_propagation_header(bt)
|
|
497
|
+
prop_headers_py = ctypes.cast(prop_headers, ctypes.c_char_p).value
|
|
498
|
+
self.lib.sdk_free_memory(prop_headers)
|
|
499
|
+
return prop_headers_py
|
|
500
|
+
|
|
501
|
+
def get_nd_build(self):
|
|
502
|
+
return self.lib.sdk_getNdBuild().decode()
|
|
503
|
+
|
|
504
|
+
def get_nf_status(self):
|
|
505
|
+
nf_enabled = self.lib.sdk_getNFStatus()
|
|
506
|
+
if nf_enabled == 1:
|
|
507
|
+
self.nf_enabled = True
|
|
508
|
+
elif nf_enabled == 0:
|
|
509
|
+
self.nf_enabled = False
|
|
510
|
+
|
|
511
|
+
def get_app_name(self):
|
|
512
|
+
app_name = self.lib.sdk_getAppName()
|
|
513
|
+
app_name_py = ctypes.cast(app_name, ctypes.c_char_p).value
|
|
514
|
+
del app_name
|
|
515
|
+
return app_name_py
|
|
516
|
+
|
|
517
|
+
def get_tier_name(self):
|
|
518
|
+
tier = self.lib.sdk_getTierName()
|
|
519
|
+
tier_py = ctypes.cast(tier, ctypes.c_char_p).value
|
|
520
|
+
del tier
|
|
521
|
+
return tier_py
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
def get_app_server_name(self):
|
|
525
|
+
app_server = self.lib.sdk_getAppServerName()
|
|
526
|
+
|
|
527
|
+
app_server_py = ctypes.cast(app_server, ctypes.c_char_p).value
|
|
528
|
+
del app_server
|
|
529
|
+
|
|
530
|
+
return app_server_py
|
|
531
|
+
|
|
532
|
+
def get_current_tr(self):
|
|
533
|
+
TR = self.lib.sdk_getCurrentTR()
|
|
534
|
+
return TR
|
|
535
|
+
|
|
536
|
+
def getBciInstrSessionPctVal(self):
|
|
537
|
+
BciInstrSessionPctVal= self.lib.sdk_getBciInstrSessionPctVal()
|
|
538
|
+
return BciInstrSessionPctVal
|
|
539
|
+
|
|
540
|
+
def get_bt_name(self, url, parameters, btHeaderValue, httpMethod):
|
|
541
|
+
try:
|
|
542
|
+
bt_name = self.lib.sdk_getBTName(url, parameters, btHeaderValue, httpMethod)
|
|
543
|
+
|
|
544
|
+
bt_name_py = ctypes.cast(bt_name, ctypes.c_char_p).value
|
|
545
|
+
if bt_name:
|
|
546
|
+
self.lib.sdk_free_memory(bt_name)
|
|
547
|
+
|
|
548
|
+
return bt_name_py
|
|
549
|
+
except Exception as e:
|
|
550
|
+
self.logger.exception("Exception in get_bt_name: {}".format(e))
|
|
551
|
+
return None
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
def get_tier_callout(self, backend_name, thread_id):
|
|
555
|
+
backend_name_b = backend_name.encode('utf-8') if isinstance(backend_name, str) else backend_name
|
|
556
|
+
result = self.lib.sdk_getTierCallOutOtel(backend_name_b, thread_id)
|
|
557
|
+
# Decode the native bridge result into a Python header value.
|
|
558
|
+
tiercallout_py = ctypes.cast(result, ctypes.c_char_p).value
|
|
559
|
+
|
|
560
|
+
if result:
|
|
561
|
+
self.lib.sdk_free_memory(result)
|
|
562
|
+
|
|
563
|
+
return tiercallout_py
|
|
564
|
+
|
|
565
|
+
|
|
566
|
+
def setting_backend_name_otel(self, backendName, type_):
|
|
567
|
+
try:
|
|
568
|
+
# Convert Python str to byte
|
|
569
|
+
backendName_b = backendName.encode('utf-8') if backendName else None
|
|
570
|
+
type_b = type_.encode('utf-8') if type_ else None
|
|
571
|
+
# Call C function
|
|
572
|
+
result = self.lib.sdk_settingBackendNameOtel(backendName_b, type_b)
|
|
573
|
+
result_py = ctypes.cast(result,ctypes.c_char_p).value
|
|
574
|
+
# Free memory from C side
|
|
575
|
+
if result:
|
|
576
|
+
self.lib.sdk_free_memory(result)
|
|
577
|
+
|
|
578
|
+
return result_py
|
|
579
|
+
except Exception as e:
|
|
580
|
+
self.logger.exception("Exception in setting_backend_name_otel: {}".format(e))
|
|
581
|
+
return None
|
|
582
|
+
|
|
583
|
+
|
|
584
|
+
def UpdateBTCounters(self, bt_name, status_code, sum_value, count, min_val, max_val, boundaries, boundaries_len, bucketsCounts):
|
|
585
|
+
# Convert bt_name to bytes (C expects char*)
|
|
586
|
+
bt_name_bytes = bt_name.encode('utf-8')
|
|
587
|
+
|
|
588
|
+
# Convert boundaries to ctypes array
|
|
589
|
+
boundaries_array = (ctypes.c_double * boundaries_len)(*boundaries)
|
|
590
|
+
|
|
591
|
+
# Convert bucketsCounts to ctypes array
|
|
592
|
+
buckets_array = (ctypes.c_long * (boundaries_len+1))(*bucketsCounts)
|
|
593
|
+
|
|
594
|
+
# Call the C function
|
|
595
|
+
BT_Counters = self.lib.sdk_UpdateBTCounters(
|
|
596
|
+
bt_name_bytes,
|
|
597
|
+
status_code,
|
|
598
|
+
ctypes.c_double(sum_value),
|
|
599
|
+
ctypes.c_long(count),
|
|
600
|
+
ctypes.c_double(min_val),
|
|
601
|
+
ctypes.c_double(max_val),
|
|
602
|
+
boundaries_array,
|
|
603
|
+
ctypes.c_int(boundaries_len),
|
|
604
|
+
buckets_array
|
|
605
|
+
)
|
|
606
|
+
|
|
607
|
+
return BT_Counters
|
|
608
|
+
|
|
609
|
+
def UpdateIPCounters(self, backend_name, sum_value, count, min_val, max_val, boundaries, boundaries_len, bucketsCounts, type_str, dbtype_str):
|
|
610
|
+
backend_name_bytes = backend_name.encode('utf-8')
|
|
611
|
+
type_bytes = type_str.encode('utf-8')
|
|
612
|
+
dbtype_bytes = dbtype_str.encode('utf-8')
|
|
613
|
+
# Convert boundaries to ctypes array
|
|
614
|
+
boundaries_array = (ctypes.c_double * boundaries_len)(*boundaries)
|
|
615
|
+
|
|
616
|
+
# Convert bucketsCounts to ctypes array (length = boundaries_len + 1)
|
|
617
|
+
buckets_array = (ctypes.c_long * (boundaries_len + 1))(*bucketsCounts)
|
|
618
|
+
|
|
619
|
+
# Call the C function
|
|
620
|
+
IP_Counters = self.lib.sdk_UpdateIPCounters(
|
|
621
|
+
backend_name_bytes,
|
|
622
|
+
ctypes.c_double(sum_value),
|
|
623
|
+
ctypes.c_long(count),
|
|
624
|
+
ctypes.c_double(min_val),
|
|
625
|
+
ctypes.c_double(max_val),
|
|
626
|
+
boundaries_array,
|
|
627
|
+
ctypes.c_int(boundaries_len),
|
|
628
|
+
buckets_array,
|
|
629
|
+
type_bytes,
|
|
630
|
+
dbtype_bytes
|
|
631
|
+
)
|
|
632
|
+
|
|
633
|
+
|
|
634
|
+
return IP_Counters
|
|
635
|
+
|
|
636
|
+
def set_tier_callout(self, value):
|
|
637
|
+
if isinstance(value, str):
|
|
638
|
+
value = value.encode()
|
|
639
|
+
|
|
640
|
+
# The setter restores inbound tier-callout state in the native bridge.
|
|
641
|
+
return self.lib.sdk_setTierCallOutOtel(value)
|
|
642
|
+
|
|
643
|
+
def UpdateIPCountersUsingSpan(self, backend_name, type_str, dbtype_str, duration, status_code):
|
|
644
|
+
backend_name_bytes = backend_name.encode('utf-8')
|
|
645
|
+
type_bytes = type_str.encode('utf-8')
|
|
646
|
+
dbtype_bytes = dbtype_str.encode('utf-8')
|
|
647
|
+
IP_Counters = self.lib.sdk_UpdateIPCountersUsingSpan(
|
|
648
|
+
backend_name_bytes,
|
|
649
|
+
type_bytes,
|
|
650
|
+
dbtype_bytes,
|
|
651
|
+
ctypes.c_double(duration),
|
|
652
|
+
ctypes.c_int(status_code)
|
|
653
|
+
|
|
654
|
+
)
|
|
655
|
+
|
|
656
|
+
return IP_Counters
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
#########################
|
|
660
|
+
# DUMP TO COMMONLIB
|
|
661
|
+
#########################
|
|
662
|
+
|
|
663
|
+
def dump_log_message(self, bt, logs):
|
|
664
|
+
if not self.get_current_bt():
|
|
665
|
+
return None
|
|
666
|
+
|
|
667
|
+
logs_c = create_string_buffer(get_utf8_bytes(logs))
|
|
668
|
+
|
|
669
|
+
resp = self.lib.sdk_dumpLogMessage(bt, logs_c)
|
|
670
|
+
|
|
671
|
+
del logs_c
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
##########################
|
|
675
|
+
# REGISTER CALLBACKS
|
|
676
|
+
##########################
|
|
677
|
+
|
|
678
|
+
def register_nd_cookie_callback(self):
|
|
679
|
+
self.lib.register_nd_cookie_callback(self.nd_cookie_callback_c)
|
|
680
|
+
#print("**** callback registered for ND cookie ****")
|
|
681
|
+
|
|
682
|
+
def gc_nd_status_callback(self):
|
|
683
|
+
self.lib.register_GC_status_for_agent(self.nd_gcstatus_callback_c)
|
|
684
|
+
|
|
685
|
+
def register_exception_stack_depth_callback(self):
|
|
686
|
+
self.lib.register_exception_depth_callback(self.exception_stack_depth_c)
|
|
687
|
+
|
|
688
|
+
def nd_pythread_status_callback(self):
|
|
689
|
+
self.lib.register_TH_status_for_agent(self.nd_pythread_status_callback_c)
|
|
690
|
+
|
|
691
|
+
def thread_dump_callback(self):
|
|
692
|
+
self.lib.register_thread_dump_callback(self.nd_thread_dump_callback_c)
|
|
693
|
+
|
|
694
|
+
def register_nv_cookie_callback(self):
|
|
695
|
+
self.lib.register_nv_cookie_callback(self.nv_cookie_callback_c)
|
|
696
|
+
#print("**** callback registered for NV cookie ****")
|
|
697
|
+
|
|
698
|
+
def ad_wrapper(self):
|
|
699
|
+
self.lib.register_AD_callback(self.autodiscovery_c)
|
|
700
|
+
|
|
701
|
+
def thd_wrapper(self):
|
|
702
|
+
self.lib.register_thread_dump_callback(self.c_thd)
|
|
703
|
+
|
|
704
|
+
def ai_wrapper_begin(self):
|
|
705
|
+
#print("************************ callback registered ********************************************")
|
|
706
|
+
self.lib.register_AI_start_callback(self.c_startaisession)
|
|
707
|
+
|
|
708
|
+
def ai_wrapper_end(self):
|
|
709
|
+
self.lib.register_AI_end_callback(self.c_endaisession)
|
|
710
|
+
|
|
711
|
+
def register_test_status_callback(self):
|
|
712
|
+
self.lib.register_test_status_for_agent(self.test_status_callback_c)
|
|
713
|
+
|
|
714
|
+
def register_instr_prof_callback(self):
|
|
715
|
+
self.lib.register_instr_prof_callback(self.instr_prof_callback_c)
|
|
716
|
+
|
|
717
|
+
def register_heap_dump_callback(self):
|
|
718
|
+
self.lib.register_heap_dump_callback(self.heap_dump_c)
|
|
719
|
+
|
|
720
|
+
def register_havoc_callback(self):
|
|
721
|
+
self.lib.register_havoc_msg_for_agent_callback_sdk(self.receive_havoc_message_c)
|
|
722
|
+
|
|
723
|
+
##########################
|
|
724
|
+
# CALLBACK DEFINITIONS
|
|
725
|
+
##########################
|
|
726
|
+
|
|
727
|
+
def common_sleep(self, havocStarttime, shootUpDuration, stableDuration, tumbleDuration, delayInSec):
|
|
728
|
+
self.lib.sdk_getDelayAtCurrentInstant(ctypes.c_long(int(havocStarttime)),
|
|
729
|
+
ctypes.c_long(int(shootUpDuration * 1000)),
|
|
730
|
+
ctypes.c_long(int(stableDuration * 1000)),
|
|
731
|
+
ctypes.c_long(int(tumbleDuration * 1000)),
|
|
732
|
+
ctypes.c_long(int(delayInSec)))
|
|
733
|
+
|
|
734
|
+
def thd(self):
|
|
735
|
+
print("INSIDE THD")
|
|
736
|
+
# dumpstacks()
|
|
737
|
+
|
|
738
|
+
def exception_stack_depth_py(self, stack_depth):
|
|
739
|
+
self.logger.debug("Stack depth callback called {}".format(stack_depth))
|
|
740
|
+
self.exception_stack_depth=stack_depth
|
|
741
|
+
|
|
742
|
+
def test_status_callback_py(self, test_status):
|
|
743
|
+
if test_status == 1:
|
|
744
|
+
self.test_running = True
|
|
745
|
+
elif test_status == 0:
|
|
746
|
+
self.test_running = False
|
|
747
|
+
self.logger.info("Test Running: {}".format(self.test_running))
|
|
748
|
+
|
|
749
|
+
def nd_cookie_callback_py(self, name, domain, rheader, mpos, duration):
|
|
750
|
+
self.logger.info(f"nd_cookie name {name} \ndomain {domain}\nrheader {rheader}\nmpos {mpos}\nduration {duration}")
|
|
751
|
+
if name:
|
|
752
|
+
self.nd_cookie_key = name.decode()
|
|
753
|
+
if not mpos:
|
|
754
|
+
self.nd_cookie_key = None
|
|
755
|
+
self.disable_nd_nv = True
|
|
756
|
+
|
|
757
|
+
self.header_in_response = rheader
|
|
758
|
+
self.cookie_method_position = mpos
|
|
759
|
+
if domain:
|
|
760
|
+
self.cookie_domain = domain.decode()
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
|
|
764
|
+
def nd_gcstatus_callback_py(self,status):
|
|
765
|
+
self.gc_run_status = status
|
|
766
|
+
if self.gc_run_status == 1:
|
|
767
|
+
if not self.gc_monitor_rt.is_running:
|
|
768
|
+
self.gc_monitor_rt.start()
|
|
769
|
+
elif self.gc_run_status == 0:
|
|
770
|
+
if self.gc_monitor_rt.is_running:
|
|
771
|
+
self.gc_monitor_rt.stop()
|
|
772
|
+
|
|
773
|
+
def nv_cookie_callback_py(self, name):
|
|
774
|
+
#print(f"nv_cookie name {name}")
|
|
775
|
+
if name:
|
|
776
|
+
self.nv_cookie_key = name.decode()
|
|
777
|
+
|
|
778
|
+
def nd_pythread_status_callback_py(self, status):
|
|
779
|
+
self.pythread_run_status = status
|
|
780
|
+
if self.pythread_run_status == 1:
|
|
781
|
+
if not self.thread_monitor_rt.is_running:
|
|
782
|
+
self.thread_monitor_rt.start()
|
|
783
|
+
elif self.pythread_run_status == 0:
|
|
784
|
+
if self.thread_monitor_rt.is_running:
|
|
785
|
+
self.thread_monitor_rt.stop()
|
|
786
|
+
|
|
787
|
+
def nd_thread_dump_callback_py(self):
|
|
788
|
+
build_details = self.get_nd_build()
|
|
789
|
+
dump_stack_str = dumpstacks(build_details)
|
|
790
|
+
try:
|
|
791
|
+
dump_str = bytes(dump_stack_str, 'utf-8')
|
|
792
|
+
except:
|
|
793
|
+
dump_str = bytes(dump_stack_str.encode("utf-8"))
|
|
794
|
+
|
|
795
|
+
return dump_str
|
|
796
|
+
|
|
797
|
+
def endaisessioncc(self, char):
|
|
798
|
+
print("INSIDE END AI SESSION")
|
|
799
|
+
|
|
800
|
+
def startaisession(self, istart, startTime, duration, sname):
|
|
801
|
+
# if not self.get_current_bt():
|
|
802
|
+
# return
|
|
803
|
+
self.logger.info("ai start")
|
|
804
|
+
#print(" IN startaisession", sname.decode('ascii'))
|
|
805
|
+
if sname:
|
|
806
|
+
wsgi.aiflagset(istart, startTime, duration, sname)
|
|
807
|
+
#pathd = "/opt/cavisson/netdiagnostics/logs/"
|
|
808
|
+
ndhome = os.environ.get('NDHOME')
|
|
809
|
+
pathd = ndhome + '/python/logs/'
|
|
810
|
+
filenameai1 = str(self.sname.decode('ascii')) + ".txt"
|
|
811
|
+
aifile_to_open_to_d = os.path.join(pathd, filenameai1)
|
|
812
|
+
self.lib.handleUploadDownload(bytes(aifile_to_open_to_d, 'utf-8'))
|
|
813
|
+
self.logger.info("ai end")
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
def autodiscovery_py(self, method_filters_pattern_list, class_filters_pattern_list,
|
|
817
|
+
method_list_length, class_list_length):
|
|
818
|
+
# if not self.get_current_bt():
|
|
819
|
+
# return
|
|
820
|
+
|
|
821
|
+
self.logger.info("ad start")
|
|
822
|
+
if method_list_length > 0:
|
|
823
|
+
method_filter_list = []
|
|
824
|
+
for i in range(method_list_length):
|
|
825
|
+
method_filter_list.append(method_filters_pattern_list[i].decode())
|
|
826
|
+
else:
|
|
827
|
+
method_filter_list = None
|
|
828
|
+
|
|
829
|
+
if class_list_length > 0:
|
|
830
|
+
class_filter_list = []
|
|
831
|
+
for i in range(class_list_length):
|
|
832
|
+
class_filter_list.append(class_filters_pattern_list[i].decode())
|
|
833
|
+
else:
|
|
834
|
+
class_filter_list = None
|
|
835
|
+
|
|
836
|
+
start_time = time.time()
|
|
837
|
+
|
|
838
|
+
try: # Defensive check for failure of finder.run_script(sys.argv[0])
|
|
839
|
+
output_from_ad, num_of_modules, num_of_methods = find(method_filter_list, class_filter_list)
|
|
840
|
+
except Exception as e:
|
|
841
|
+
self.logger.error("Unable to auto-discover methods, please try again")
|
|
842
|
+
self.logger.debug(e)
|
|
843
|
+
output_from_ad = "default||default"
|
|
844
|
+
num_of_modules = 1
|
|
845
|
+
num_of_methods = 1
|
|
846
|
+
|
|
847
|
+
end_time = time.time()
|
|
848
|
+
total_time = end_time - start_time
|
|
849
|
+
ad_summary = "totalTimeTaken={} ms;totalModules={};totalMethods={};\n".format(total_time, num_of_modules, num_of_methods)
|
|
850
|
+
|
|
851
|
+
output_from_ad_c = create_string_buffer(get_utf8_bytes(output_from_ad))
|
|
852
|
+
self.lib.wraphandleMessageForDiscovery(output_from_ad_c)
|
|
853
|
+
|
|
854
|
+
# Metadata must be sent before the "totalTimeTaken=...;" summary line below - that line is
|
|
855
|
+
# treated by the collector as the terminal response for this discovery request, so anything
|
|
856
|
+
# sent after it would never be attached to the .adr output. Defensive try/except so a
|
|
857
|
+
# metadata-collection failure never breaks the rest of auto-discovery.
|
|
858
|
+
try:
|
|
859
|
+
metadata_block_c = create_string_buffer(get_utf8_bytes(build_metadata_block(self)))
|
|
860
|
+
self.lib.wraphandleMessageForDiscovery(metadata_block_c)
|
|
861
|
+
del metadata_block_c
|
|
862
|
+
except Exception as e:
|
|
863
|
+
self.logger.exception("Error building/sending auto-discovery metadata block")
|
|
864
|
+
|
|
865
|
+
self.logger.info("ad sending summary")
|
|
866
|
+
ad_summary_c = create_string_buffer(get_utf8_bytes(ad_summary))
|
|
867
|
+
self.lib.wraphandleMessageForDiscovery(ad_summary_c)
|
|
868
|
+
del output_from_ad_c, ad_summary_c
|
|
869
|
+
|
|
870
|
+
|
|
871
|
+
def instr_prof_callback_py(self, instr_prof):
|
|
872
|
+
self.logger.info("Received Instrumentation Profile Callback")
|
|
873
|
+
self.logger.debug("Instr Prof {}".format(instr_prof))
|
|
874
|
+
|
|
875
|
+
try:
|
|
876
|
+
if instr_prof:
|
|
877
|
+
instr_prof_str = instr_prof.decode()
|
|
878
|
+
|
|
879
|
+
instr_prof_str_split = instr_prof_str.split("\n\n\n")
|
|
880
|
+
|
|
881
|
+
instr_prof_list = []
|
|
882
|
+
|
|
883
|
+
for profile in instr_prof_str_split:
|
|
884
|
+
profile = profile.strip()
|
|
885
|
+
if profile[0] == "[" and profile[-1] != "]":
|
|
886
|
+
profile += "}]"
|
|
887
|
+
instr_prof_list.append(profile)
|
|
888
|
+
|
|
889
|
+
new_instr_prof_str = "\n\n\n".join(instr_prof_list)
|
|
890
|
+
|
|
891
|
+
|
|
892
|
+
from pythonagent import config
|
|
893
|
+
pythonagent_path = os.path.dirname(config.__file__)
|
|
894
|
+
instr_prof_path = os.path.join(pythonagent_path, 'agent/internal/instrprof.json')
|
|
895
|
+
try:
|
|
896
|
+
with open(instr_prof_path, "w+") as outfile:
|
|
897
|
+
outfile.write(new_instr_prof_str)
|
|
898
|
+
|
|
899
|
+
except:
|
|
900
|
+
self.logger.exception("Unable to write instrprof.json")
|
|
901
|
+
|
|
902
|
+
import pythonagent.agent as agent
|
|
903
|
+
agent.bootstrap(self)
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
except Exception as e:
|
|
907
|
+
self.logger.exception("Error in Instrumentation Profile Callback")
|
|
908
|
+
|
|
909
|
+
|
|
910
|
+
def receive_havoc_message_py(self, havoc_message):
|
|
911
|
+
self.logger.warning("Havoc callback called{}".format(havoc_message))
|
|
912
|
+
body, header_dict = process_raw_havoc_message(havoc_message.decode(), self.cav_env)
|
|
913
|
+
self.logger.debug("Header:".format(header_dict))
|
|
914
|
+
self.logger.debug("Body:".format(body))
|
|
915
|
+
self.havoc_monitor.parse_nethavoc_config(body, header_dict)
|
|
916
|
+
|
|
917
|
+
def send_havoc_response(self, header_str):
|
|
918
|
+
if self.cav_env == "NATIVE":
|
|
919
|
+
self.logger.warning("Havoc Response from Agent{}".format(header_str))
|
|
920
|
+
header_c = create_string_buffer(get_utf8_bytes(header_str))
|
|
921
|
+
self.lib.havoc_response_from_agent(header_c)
|
|
922
|
+
del header_c
|
|
923
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
924
|
+
udp.havoc_message(self, header_str)
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
#############################
|
|
928
|
+
# REPEATER TIMER FUNCTIONS
|
|
929
|
+
#############################
|
|
930
|
+
|
|
931
|
+
def send_gc_report(self, record_string):
|
|
932
|
+
|
|
933
|
+
record_string_c = create_string_buffer(get_utf8_bytes(record_string))
|
|
934
|
+
|
|
935
|
+
self.lib.sendGCReport(ctypes.c_int(77),record_string_c)
|
|
936
|
+
del record_string_c
|
|
937
|
+
|
|
938
|
+
def heap_gc_stats(self):
|
|
939
|
+
try:
|
|
940
|
+
RSS = get_rss_bytes()
|
|
941
|
+
x = gc.get_count()
|
|
942
|
+
y = gc.get_stats()
|
|
943
|
+
record_str = ""
|
|
944
|
+
record_str += str(int(RSS / 1000)) + ' '
|
|
945
|
+
for i in range(0, 3):
|
|
946
|
+
record_str += str(x[i]) + ' '
|
|
947
|
+
record_str += str(y[i]['collected']) + ' '
|
|
948
|
+
record_str += str(y[i]['uncollectable']) + ' '
|
|
949
|
+
if i < 2:
|
|
950
|
+
record_str += str(y[i]['collections']) + ' '
|
|
951
|
+
else:
|
|
952
|
+
record_str += str(y[i]['collections'])
|
|
953
|
+
self.send_gc_report(record_str)
|
|
954
|
+
except Exception as e:
|
|
955
|
+
self.logger.info("Exception on heap_gc_stats : {}".format(e))
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
def send_thread_report(self, record_string):
|
|
959
|
+
record_string_c = create_string_buffer(get_utf8_bytes(record_string))
|
|
960
|
+
|
|
961
|
+
self.lib.sendGCReport(ctypes.c_int(83), record_string_c)
|
|
962
|
+
del record_string_c
|
|
963
|
+
|
|
964
|
+
def thread_stats(self):
|
|
965
|
+
thread_details_ = threading.enumerate()
|
|
966
|
+
total_threads = str(len(thread_details_))
|
|
967
|
+
thread_status_dict = {'deamon': 0, 'notdeamon': 0,}
|
|
968
|
+
for thread in thread_details_:
|
|
969
|
+
|
|
970
|
+
if thread.daemon == True:
|
|
971
|
+
thread_status_dict['deamon'] += 1
|
|
972
|
+
|
|
973
|
+
if thread.daemon == False:
|
|
974
|
+
thread_status_dict['notdeamon'] += 1
|
|
975
|
+
|
|
976
|
+
thread_stats_string = (total_threads + " " +
|
|
977
|
+
str(thread_status_dict['deamon']) + " " +
|
|
978
|
+
str(thread_status_dict['notdeamon']))
|
|
979
|
+
|
|
980
|
+
self.send_thread_report(thread_stats_string)
|
|
981
|
+
|
|
982
|
+
######################
|
|
983
|
+
# CORE SDK FUNCTIONS
|
|
984
|
+
######################
|
|
985
|
+
|
|
986
|
+
# @profile
|
|
987
|
+
def sdk_init_native(self):
|
|
988
|
+
self.logger.info("sdk_init -> lib.obj :{0}".format(self.lib))
|
|
989
|
+
agent_type = bytes("python", 'utf-8')
|
|
990
|
+
log_file_name = bytes("cavlib", 'utf-8')
|
|
991
|
+
version_string = "python" + platform.python_version()
|
|
992
|
+
|
|
993
|
+
"""
|
|
994
|
+
appname = None
|
|
995
|
+
for item in sys.argv:
|
|
996
|
+
if item.endswith(".py"):
|
|
997
|
+
appname = item.split("/")[-1]
|
|
998
|
+
appname = appname[:-3] # Remove .py extension
|
|
999
|
+
break
|
|
1000
|
+
|
|
1001
|
+
if not appname:
|
|
1002
|
+
appname = "wsgi"
|
|
1003
|
+
"""
|
|
1004
|
+
|
|
1005
|
+
appname = "Python"
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
version_string_c = create_string_buffer(get_utf8_bytes(version_string))
|
|
1010
|
+
appname_string_c = create_string_buffer(get_utf8_bytes(appname))
|
|
1011
|
+
self.lib.nd_init2(agent_type, log_file_name, version_string_c, appname_string_c)
|
|
1012
|
+
|
|
1013
|
+
del version_string_c
|
|
1014
|
+
del appname_string_c
|
|
1015
|
+
|
|
1016
|
+
def sdk_init(self):
|
|
1017
|
+
if self.cav_env == "NATIVE":
|
|
1018
|
+
self.sdk_init_native()
|
|
1019
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1020
|
+
udp.sdk_init(self)
|
|
1021
|
+
|
|
1022
|
+
def sdk_free_native(self):
|
|
1023
|
+
self.logger.info("sdk_free -> lib.obj :{0}".format(self.lib))
|
|
1024
|
+
self.lib.nd_free()
|
|
1025
|
+
|
|
1026
|
+
def sdk_free(self):
|
|
1027
|
+
if self.cav_env == "NATIVE":
|
|
1028
|
+
self.sdk_free_native()
|
|
1029
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1030
|
+
udp.sdk_free()
|
|
1031
|
+
|
|
1032
|
+
def method_entry_native(self, bt, method, start_time):
|
|
1033
|
+
if not self.get_current_bt():
|
|
1034
|
+
return
|
|
1035
|
+
self.logger.info("method entry: {}".format(method))
|
|
1036
|
+
method_c = create_string_buffer(get_utf8_bytes(method))
|
|
1037
|
+
self.lib.nd_method_entry(bt, method_c, ctypes.c_longlong(start_time))
|
|
1038
|
+
del method_c
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
def method_entry(self, bt, method, start_time=0):
|
|
1042
|
+
if self.cav_env == "NATIVE":
|
|
1043
|
+
self.method_entry_native(bt, method, start_time)
|
|
1044
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1045
|
+
udp.method_entry(self, bt, method, "NA", "NA")
|
|
1046
|
+
|
|
1047
|
+
#@profile
|
|
1048
|
+
def method_exit_native(self, bt, method, duration, cpu_time, method_start_time):
|
|
1049
|
+
if not self.get_current_bt():
|
|
1050
|
+
return
|
|
1051
|
+
self.logger.info("method exit: {}".format(method))
|
|
1052
|
+
method_bytes = get_utf8_bytes(str(method))
|
|
1053
|
+
str_span_c = ctypes.POINTER(ctypes.c_char_p)()
|
|
1054
|
+
method_c = create_string_buffer(get_utf8_bytes(method))
|
|
1055
|
+
|
|
1056
|
+
self.lib.nd_method_exit(bt, method_c, ctypes.c_longlong(cpu_time), ctypes.c_longlong(duration), ctypes.c_longlong(method_start_time), ctypes.byref(str_span_c))
|
|
1057
|
+
|
|
1058
|
+
span_obj = ctypes.c_char_p.from_buffer(str_span_c)
|
|
1059
|
+
self.dump_span(span_obj)
|
|
1060
|
+
self.lib.sdk_free_memory(str_span_c)
|
|
1061
|
+
del span_obj, method_c
|
|
1062
|
+
|
|
1063
|
+
def method_exit(self, bt, method, duration, cpu_time=0, method_start_time=0):
|
|
1064
|
+
if self.cav_env == "NATIVE":
|
|
1065
|
+
self.method_exit_native(bt, method, duration, cpu_time, method_start_time)
|
|
1066
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1067
|
+
udp.method_exit(self, bt, method, "NA", 0, duration)
|
|
1068
|
+
|
|
1069
|
+
# @profile
|
|
1070
|
+
def start_business_transaction_native(self, bt_name, correlation_header, nd_cookie, nv_cookie, bt_header_value, fp_instance):
|
|
1071
|
+
start_time = get_current_timestamp_in_us()
|
|
1072
|
+
self.unset_current_bt()
|
|
1073
|
+
if os.environ['nd_init_done'] == '0':
|
|
1074
|
+
self.start()
|
|
1075
|
+
#print("start_business_transaction ->")
|
|
1076
|
+
#self.logger.debug(" start_business_transaction -> lib.obj {0}:".format(self.lib))
|
|
1077
|
+
|
|
1078
|
+
self.logger.info(" start_business_transaction -> bt_name {0}:".format(bt_name))
|
|
1079
|
+
bt_name_c = create_string_buffer(get_utf8_bytes(bt_name))
|
|
1080
|
+
correlation_header_c = create_string_buffer(get_utf8_bytes(correlation_header))
|
|
1081
|
+
|
|
1082
|
+
|
|
1083
|
+
if not fp_instance:
|
|
1084
|
+
self.get_transaction_context().flow_path_id = generate_flow_path_id()
|
|
1085
|
+
else:
|
|
1086
|
+
self.get_transaction_context().flow_path_id = fp_instance
|
|
1087
|
+
|
|
1088
|
+
|
|
1089
|
+
nd_cookie_c = create_string_buffer(get_utf8_bytes(nd_cookie))
|
|
1090
|
+
nv_cookie_c = create_string_buffer(get_utf8_bytes(nv_cookie))
|
|
1091
|
+
bt_header_value_c = create_string_buffer(get_utf8_bytes(bt_header_value))
|
|
1092
|
+
|
|
1093
|
+
flow_path_id = self.get_transaction_context().flow_path_id
|
|
1094
|
+
flow_path_id_c = create_string_buffer(get_utf8_bytes(flow_path_id))
|
|
1095
|
+
start_time_c = ctypes.c_longlong(start_time)
|
|
1096
|
+
|
|
1097
|
+
bt = self.lib.nd_bt_begin(bt_name_c, correlation_header_c, nd_cookie_c, nv_cookie_c, bt_header_value_c, flow_path_id_c, start_time_c)
|
|
1098
|
+
|
|
1099
|
+
del start_time_c, bt_header_value_c, nd_cookie, nv_cookie, bt_name_c, correlation_header_c
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
if not bt:
|
|
1103
|
+
self.logger.warning("BT is None. Either Test Run is stopped or Connection is broken")
|
|
1104
|
+
#self.logger.info("bt datatype : {0}".format(type(bt)))
|
|
1105
|
+
#print("btname value: {0}".format(btname))
|
|
1106
|
+
# print('-----------------\nCurrent heap memory stack for BT: ',bt_name,' is : ',hpy().heap())
|
|
1107
|
+
self.active_bts.add(bt)
|
|
1108
|
+
self.set_current_bt(bt)
|
|
1109
|
+
#print("BT value of this txn: ", bt)
|
|
1110
|
+
return bt
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
def inbound_havoc_delay_otel(self, req_url, bt_name=None):
|
|
1114
|
+
# Apply configured inbound service delay during OTel instrumentation flow.
|
|
1115
|
+
# req_url is the request URL/path used for havoc matching; bt_name is optional
|
|
1116
|
+
# for backward-compatible OTel callers while ndotel is migrated.
|
|
1117
|
+
try:
|
|
1118
|
+
self.havoc_monitor.apply_inbound_service_delay(req_url, bt_name)
|
|
1119
|
+
except Exception as e:
|
|
1120
|
+
# Keep OTel span processing aligned with the existing BT path:
|
|
1121
|
+
# havoc config/load issues should not break the request.
|
|
1122
|
+
print(e)
|
|
1123
|
+
pass
|
|
1124
|
+
|
|
1125
|
+
def inbound_havoc_failure_otel(self, req_url, bt_name=None):
|
|
1126
|
+
self.havoc_monitor.apply_inbound_service_failure(req_url, bt_name)
|
|
1127
|
+
|
|
1128
|
+
def outbound_havoc_delay_otel(
|
|
1129
|
+
self,
|
|
1130
|
+
req_hostname,
|
|
1131
|
+
backend_name=None,
|
|
1132
|
+
req_url=None,
|
|
1133
|
+
bt_name=None,
|
|
1134
|
+
):
|
|
1135
|
+
# Apply configured outbound service delay during OTel instrumentation flow.
|
|
1136
|
+
# req_hostname is used for host matching; backend_name, req_url and bt_name
|
|
1137
|
+
# are optional for backward-compatible OTel callers while ndotel is migrated.
|
|
1138
|
+
try:
|
|
1139
|
+
self.havoc_monitor.apply_outbound_service_delay(
|
|
1140
|
+
req_hostname,
|
|
1141
|
+
backend_name,
|
|
1142
|
+
req_url,
|
|
1143
|
+
bt_name,
|
|
1144
|
+
)
|
|
1145
|
+
except Exception as e:
|
|
1146
|
+
print(e)
|
|
1147
|
+
pass
|
|
1148
|
+
|
|
1149
|
+
def outbound_havoc_failure_otel(
|
|
1150
|
+
self,
|
|
1151
|
+
req_hostname,
|
|
1152
|
+
backend_name=None,
|
|
1153
|
+
req_url=None,
|
|
1154
|
+
bt_name=None,
|
|
1155
|
+
):
|
|
1156
|
+
self.havoc_monitor.apply_outbound_service_failure(
|
|
1157
|
+
req_hostname,
|
|
1158
|
+
backend_name,
|
|
1159
|
+
req_url,
|
|
1160
|
+
bt_name,
|
|
1161
|
+
)
|
|
1162
|
+
def start_business_transaction(self, urlinfo, correlation_header, nd_cookie=None, nv_cookie=None, bt_header_value=None, fp_instance=None):
|
|
1163
|
+
bt = None
|
|
1164
|
+
btname = urlinfo
|
|
1165
|
+
context = self.get_transaction_context()
|
|
1166
|
+
if context is None:
|
|
1167
|
+
context = TransactionContext()
|
|
1168
|
+
self.set_transaction_context(context)
|
|
1169
|
+
|
|
1170
|
+
if self.cav_env == "NATIVE":
|
|
1171
|
+
bt = self.start_business_transaction_native(urlinfo, correlation_header, nd_cookie, nv_cookie, bt_header_value, fp_instance)
|
|
1172
|
+
fp_topo_val = self.sdk_getTopoFpStr(bt)
|
|
1173
|
+
|
|
1174
|
+
self.get_transaction_context().fp_topo = fp_topo_val
|
|
1175
|
+
self.get_transaction_context().url_path = str(urlinfo).split("|", 1)[0]
|
|
1176
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1177
|
+
bt = udp.start_business_transaction(self, urlinfo, correlation_header)
|
|
1178
|
+
|
|
1179
|
+
try:
|
|
1180
|
+
if self.cav_env == "NATIVE":
|
|
1181
|
+
url, http_method = str(urlinfo).rsplit("|", 1) if "|" in str(urlinfo) else (urlinfo, "")
|
|
1182
|
+
btname_value = self.get_bt_name(
|
|
1183
|
+
get_utf8_bytes(url),
|
|
1184
|
+
get_utf8_bytes(""),
|
|
1185
|
+
get_utf8_bytes(bt_header_value or ""),
|
|
1186
|
+
get_utf8_bytes(http_method)
|
|
1187
|
+
)
|
|
1188
|
+
if btname_value:
|
|
1189
|
+
btname = btname_value.decode() if isinstance(btname_value, bytes) else btname_value
|
|
1190
|
+
except Exception as e:
|
|
1191
|
+
self.logger.exception("Unable to get BT name from SDK: {}".format(e))
|
|
1192
|
+
|
|
1193
|
+
if self.get_transaction_context():
|
|
1194
|
+
self.get_transaction_context().btname = btname
|
|
1195
|
+
|
|
1196
|
+
try:
|
|
1197
|
+
self.havoc_monitor.apply_inbound_service_delay(urlinfo, btname)
|
|
1198
|
+
except Exception as e:
|
|
1199
|
+
# Will fail first time
|
|
1200
|
+
self.logger.exception("apply_inbound_service_delay exception: {}".format(e))
|
|
1201
|
+
pass
|
|
1202
|
+
|
|
1203
|
+
return bt
|
|
1204
|
+
|
|
1205
|
+
# @profile
|
|
1206
|
+
def end_business_transaction_native(self, bt, cpu_time):
|
|
1207
|
+
end_time = get_current_timestamp_in_us()
|
|
1208
|
+
#print("end_business_transaction--> BT: ", bt)
|
|
1209
|
+
if not self.get_current_bt():
|
|
1210
|
+
return None
|
|
1211
|
+
|
|
1212
|
+
self.logger.info('At end_business_transaction bt value is {0}'.format(bt))
|
|
1213
|
+
statuscode = self.get_current_status_code()
|
|
1214
|
+
if statuscode:
|
|
1215
|
+
c_statuscode = ctypes.c_int(statuscode)
|
|
1216
|
+
else:
|
|
1217
|
+
c_statuscode = ctypes.c_int(200)
|
|
1218
|
+
str_span_c = ctypes.POINTER(ctypes.c_char_p)()
|
|
1219
|
+
end_time_c = ctypes.c_longlong(end_time)
|
|
1220
|
+
rc = self.lib.nd_bt_end(bt, c_statuscode, ctypes.c_int(0), end_time_c, ctypes.c_longlong(cpu_time), ctypes.byref(str_span_c))
|
|
1221
|
+
|
|
1222
|
+
span_obj = ctypes.c_char_p.from_buffer(str_span_c)
|
|
1223
|
+
self.dump_span(span_obj)
|
|
1224
|
+
self.lib.sdk_free_memory(str_span_c)
|
|
1225
|
+
# self.lib.sdk_free_memory(bt)
|
|
1226
|
+
|
|
1227
|
+
del span_obj
|
|
1228
|
+
self.logger.info("nd_bt_end return value: {0}".format(int(rc)))
|
|
1229
|
+
#self.unset_current_bt()
|
|
1230
|
+
self.unset_current_status_code()
|
|
1231
|
+
self.active_bts.discard(bt)
|
|
1232
|
+
return int(rc)
|
|
1233
|
+
|
|
1234
|
+
def end_business_transaction(self, bt, cpu_time):
|
|
1235
|
+
if self.cav_env == "NATIVE":
|
|
1236
|
+
rc = self.end_business_transaction_native(bt, cpu_time)
|
|
1237
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1238
|
+
rc = udp.end_business_transaction(self, bt)
|
|
1239
|
+
if self.get_transaction_context():
|
|
1240
|
+
self.get_transaction_context().havoc_applied = False
|
|
1241
|
+
context_object = self.get_transaction_context()
|
|
1242
|
+
del context_object
|
|
1243
|
+
if sys.version_info >= (3, 7, 0):
|
|
1244
|
+
self.context_provider.reset()
|
|
1245
|
+
else:
|
|
1246
|
+
self.transaction_context.pop(get_ident(), None)
|
|
1247
|
+
|
|
1248
|
+
return rc
|
|
1249
|
+
|
|
1250
|
+
def dump_span(self, span_obj):
|
|
1251
|
+
if not span_obj:
|
|
1252
|
+
return
|
|
1253
|
+
span_value = span_obj.value.decode()
|
|
1254
|
+
for x in self.application_loggers:
|
|
1255
|
+
#print("\n inside for", x.name, "\n")
|
|
1256
|
+
if x.name != "werkzeug" and not x.name.startswith("pythonagent"):
|
|
1257
|
+
#print("\n inside if", x.name, "\n")
|
|
1258
|
+
x.info(span_value)
|
|
1259
|
+
|
|
1260
|
+
"""
|
|
1261
|
+
#@profile
|
|
1262
|
+
def store_business_transaction_native(self, bt, unique_bt_id):
|
|
1263
|
+
self.logger.info('lib variable in store business txn: {0}'.format(self.lib))
|
|
1264
|
+
# unique_bt_id_bytes = bytes(unique_bt_id, 'utf-8')
|
|
1265
|
+
try:
|
|
1266
|
+
unique_bt_id_bytes = bytes(unique_bt_id, 'utf-8')
|
|
1267
|
+
except:
|
|
1268
|
+
unique_bt_id_bytes = bytes(unique_bt_id.encode("utf-8"))
|
|
1269
|
+
|
|
1270
|
+
bt_id_c = ctypes.c_char_p(unique_bt_id_bytes)
|
|
1271
|
+
self.lib.nd_bt_store(bt, bt_id_c)
|
|
1272
|
+
|
|
1273
|
+
|
|
1274
|
+
def store_business_transaction(self, bt, unique_bt_id):
|
|
1275
|
+
if self.cav_env == "NATIVE":
|
|
1276
|
+
self.store_business_transaction_native(bt, unique_bt_id)
|
|
1277
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1278
|
+
udp.store_business_transaction(bt, unique_bt_id)
|
|
1279
|
+
"""
|
|
1280
|
+
|
|
1281
|
+
def db_call_begin_native(self, method_name, bt, db_host, db_query, query_parameters, db_start_time):
|
|
1282
|
+
if not self.get_current_bt():
|
|
1283
|
+
return None
|
|
1284
|
+
self.logger.info("db call begin: db_host {} db_query {}".format(db_host, db_query))
|
|
1285
|
+
|
|
1286
|
+
db_host_bytes = get_utf8_bytes(str(db_host))
|
|
1287
|
+
db_query_c = create_string_buffer(get_utf8_bytes(db_query))
|
|
1288
|
+
|
|
1289
|
+
if not query_parameters:
|
|
1290
|
+
query_parameters = ""
|
|
1291
|
+
|
|
1292
|
+
db_query_parameters_c = create_string_buffer(get_utf8_bytes(query_parameters))
|
|
1293
|
+
method_name_c = create_string_buffer(get_utf8_bytes(method_name))
|
|
1294
|
+
|
|
1295
|
+
ip_handle = self.lib.nd_ip_db_callout_begin(method_name_c, bt, db_query_c,
|
|
1296
|
+
db_query_parameters_c, ctypes.c_longlong(db_start_time))
|
|
1297
|
+
|
|
1298
|
+
del method_name_c, db_query_parameters_c, db_query_c
|
|
1299
|
+
return ip_handle
|
|
1300
|
+
|
|
1301
|
+
def db_call_begin(self, method_name, bt, db_host, hostinfo, query_parameters=None, db_start_time=None):
|
|
1302
|
+
#db_host = "NA|" + str(db_host) + "|NA|NA|NA|NA|NA|NA|NA|NA|NA|NA"
|
|
1303
|
+
ip_handle = 0
|
|
1304
|
+
if self.cav_env == "NATIVE":
|
|
1305
|
+
ip_handle = self.db_call_begin_native(method_name, bt, db_host, hostinfo, query_parameters, db_start_time)
|
|
1306
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1307
|
+
entry_point_fqm = self.get_transaction_context().entry_point_fqm
|
|
1308
|
+
if not query_parameters:
|
|
1309
|
+
query_parameters = "NA"
|
|
1310
|
+
udp.method_entry(self, bt, entry_point_fqm, hostinfo, query_parameters)
|
|
1311
|
+
|
|
1312
|
+
backend_name = None
|
|
1313
|
+
try:
|
|
1314
|
+
if self.cav_env == "NATIVE":
|
|
1315
|
+
context = self.get_transaction_context()
|
|
1316
|
+
host_str = context.host_str if context and context.host_str else db_host
|
|
1317
|
+
backend_name_value = self.setting_backend_name_otel(host_str, "DB")
|
|
1318
|
+
if backend_name_value:
|
|
1319
|
+
backend_name = backend_name_value.decode() if isinstance(backend_name_value, bytes) else backend_name_value
|
|
1320
|
+
except Exception as e:
|
|
1321
|
+
self.logger.exception("Unable to get DB backend name from SDK: {}".format(e))
|
|
1322
|
+
|
|
1323
|
+
context = self.get_transaction_context()
|
|
1324
|
+
btname = context.btname if context else None
|
|
1325
|
+
req_url = context.url_path if context else None
|
|
1326
|
+
self.havoc_monitor.apply_outbound_service_delay(hostinfo, backend_name, req_url, btname)
|
|
1327
|
+
|
|
1328
|
+
return ip_handle
|
|
1329
|
+
|
|
1330
|
+
#@profile #@staticmethod
|
|
1331
|
+
def db_call_end_native(self, bt, ip_handle, duration, db_start_time, entry_point_fqm, host_str, _status_code):
|
|
1332
|
+
if not self.get_current_bt():
|
|
1333
|
+
return None
|
|
1334
|
+
str_span_c = ctypes.POINTER(ctypes.c_char_p)()
|
|
1335
|
+
|
|
1336
|
+
if not entry_point_fqm:
|
|
1337
|
+
method_name = get_utf8_bytes("NA")
|
|
1338
|
+
else:
|
|
1339
|
+
method_name = get_utf8_bytes(entry_point_fqm)
|
|
1340
|
+
|
|
1341
|
+
if not host_str:
|
|
1342
|
+
host_name = get_utf8_bytes("NA|NA|NA|NA|NA|NA|NA|NA|NA|NA|NA")
|
|
1343
|
+
else:
|
|
1344
|
+
host_name = get_utf8_bytes(host_str)
|
|
1345
|
+
|
|
1346
|
+
self.logger.info("db call end: db_host {} status {}".format(host_name, _status_code))
|
|
1347
|
+
|
|
1348
|
+
method_name_c = create_string_buffer(method_name)
|
|
1349
|
+
host_name_c = create_string_buffer(host_name)
|
|
1350
|
+
|
|
1351
|
+
rc = self.lib.nd_ip_db_callout_end(method_name_c, host_name_c, bt, ctypes.c_int(_status_code),ctypes.c_longlong(duration), ctypes.c_longlong(db_start_time), ctypes.byref(str_span_c))
|
|
1352
|
+
span_obj = ctypes.c_char_p.from_buffer(str_span_c)
|
|
1353
|
+
self.dump_span(span_obj)
|
|
1354
|
+
self.lib.sdk_free_memory(str_span_c)
|
|
1355
|
+
# self.lib.sdk_free_memory(ip_handle)
|
|
1356
|
+
|
|
1357
|
+
del span_obj
|
|
1358
|
+
del method_name_c, host_name_c
|
|
1359
|
+
return int(rc)
|
|
1360
|
+
|
|
1361
|
+
def db_call_end(self, bt, ip_handle, duration, db_start_time, entry_point_fqm, host_str, status_code):
|
|
1362
|
+
if self.cav_env == "NATIVE":
|
|
1363
|
+
self.db_call_end_native(bt, ip_handle, duration, db_start_time, entry_point_fqm, host_str, status_code)
|
|
1364
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1365
|
+
entry_point_fqm = self.get_transaction_context().entry_point_fqm
|
|
1366
|
+
backend_header = self.get_transaction_context().host_str
|
|
1367
|
+
status_code = self.get_transaction_context().status_code
|
|
1368
|
+
udp.method_exit(self, bt, entry_point_fqm, backend_header, status_code, duration)
|
|
1369
|
+
|
|
1370
|
+
#@profile #@staticmethod
|
|
1371
|
+
def http_call_begin_native(self, bt, http_host, url, method_name, http_start_time):
|
|
1372
|
+
if not self.get_current_bt():
|
|
1373
|
+
return None
|
|
1374
|
+
self.logger.info("http call begin: http_host {} url {}".format(http_host, url))
|
|
1375
|
+
host_bytes = get_utf8_bytes(str(http_host))
|
|
1376
|
+
url_c = create_string_buffer(get_utf8_bytes(url))
|
|
1377
|
+
method_name_c = create_string_buffer(get_utf8_bytes(method_name))
|
|
1378
|
+
|
|
1379
|
+
handle = self.lib.nd_ip_http_callout_begin(method_name_c, bt, url_c, ctypes.c_longlong(http_start_time))
|
|
1380
|
+
|
|
1381
|
+
del url_c, method_name_c
|
|
1382
|
+
return handle
|
|
1383
|
+
|
|
1384
|
+
def http_call_begin(self, bt, http_host, url, method_name, http_start_time=0):
|
|
1385
|
+
if self.cav_env == "NATIVE":
|
|
1386
|
+
handle = self.http_call_begin_native(bt, http_host, url, method_name, http_start_time)
|
|
1387
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1388
|
+
handle = udp.method_entry(self, bt, method_name, http_host, url)
|
|
1389
|
+
|
|
1390
|
+
backend_name = None
|
|
1391
|
+
try:
|
|
1392
|
+
if self.cav_env == "NATIVE":
|
|
1393
|
+
backend_name_value = self.setting_backend_name_otel(http_host, "HTTP")
|
|
1394
|
+
if backend_name_value:
|
|
1395
|
+
backend_name = backend_name_value.decode() if isinstance(backend_name_value, bytes) else backend_name_value
|
|
1396
|
+
except Exception as e:
|
|
1397
|
+
self.logger.exception("Unable to get HTTP backend name from SDK: {}".format(e))
|
|
1398
|
+
|
|
1399
|
+
context = self.get_transaction_context()
|
|
1400
|
+
btname = context.btname if context else None
|
|
1401
|
+
req_url = context.url_path if context else None
|
|
1402
|
+
self.havoc_monitor.apply_outbound_service_delay(http_host, backend_name, req_url, btname)
|
|
1403
|
+
return handle
|
|
1404
|
+
|
|
1405
|
+
#@profile #@staticmethod
|
|
1406
|
+
def http_call_end_native(self, bt, ip_handle, method_name, backend_name, status_code, wall_time, http_start_time, callout_id):
|
|
1407
|
+
if not self.get_current_bt():
|
|
1408
|
+
return None
|
|
1409
|
+
self.logger.info("http call end: backend_name {} status_code {}".format(backend_name, status_code))
|
|
1410
|
+
str_span_c = ctypes.POINTER(ctypes.c_char_p)()
|
|
1411
|
+
method_name_c = create_string_buffer(get_utf8_bytes(method_name))
|
|
1412
|
+
backend_name_c = create_string_buffer(get_utf8_bytes(backend_name))
|
|
1413
|
+
status_code_c = ctypes.c_int(status_code)
|
|
1414
|
+
rc = self.lib.nd_ip_http_callout_end(method_name_c, backend_name_c, bt, status_code_c, ctypes.c_longlong(wall_time), ctypes.c_longlong(http_start_time), ctypes.byref(str_span_c), ctypes.c_longlong(callout_id))
|
|
1415
|
+
span_obj = ctypes.c_char_p.from_buffer(str_span_c)
|
|
1416
|
+
self.dump_span(span_obj)
|
|
1417
|
+
self.lib.sdk_free_memory(str_span_c)
|
|
1418
|
+
# self.lib.sdk_free_memory(ip_handle)
|
|
1419
|
+
|
|
1420
|
+
del span_obj
|
|
1421
|
+
del method_name_c, backend_name_c
|
|
1422
|
+
return int(rc)
|
|
1423
|
+
|
|
1424
|
+
def http_call_end(self, bt, ip_handle, method_name=None, backend_name=None, status_code=200, duration=0, http_start_time=0, callout_id=0):
|
|
1425
|
+
if self.cav_env == "NATIVE":
|
|
1426
|
+
self.http_call_end_native(bt, ip_handle, method_name, backend_name, status_code, duration, http_start_time, callout_id)
|
|
1427
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1428
|
+
udp.method_exit(self, bt, method_name, backend_name, status_code, duration)
|
|
1429
|
+
|
|
1430
|
+
def http_req_resp_wrapper_native(self, bt, rbuffer, rtype, statuscode):
|
|
1431
|
+
if not self.get_current_bt():
|
|
1432
|
+
return
|
|
1433
|
+
|
|
1434
|
+
r_buffer_c = create_string_buffer(get_utf8_bytes(rbuffer))
|
|
1435
|
+
r_type_c = create_string_buffer(get_utf8_bytes(rtype))
|
|
1436
|
+
|
|
1437
|
+
self.lib.sdk_httpReqRespWrapper(bt, r_buffer_c, r_type_c, statuscode)
|
|
1438
|
+
|
|
1439
|
+
del r_buffer_c, r_type_c
|
|
1440
|
+
|
|
1441
|
+
def http_req_resp_wrapper(self, bt, rbuffer, rtype, statuscode):
|
|
1442
|
+
if self.cav_env == "NATIVE":
|
|
1443
|
+
self.http_req_resp_wrapper_native(bt, rbuffer, rtype, statuscode)
|
|
1444
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1445
|
+
udp.http_req_resp_wrapper(self, bt, rbuffer, rtype, statuscode)
|
|
1446
|
+
|
|
1447
|
+
|
|
1448
|
+
def exception_dump_native(self, bt, mpp, starttime, excptnclsname, excptnmsg, throwingclsname,
|
|
1449
|
+
throwingmtdname, excptncause, excptnlineno, stacktrace, file_name):
|
|
1450
|
+
if not self.get_current_bt():
|
|
1451
|
+
return
|
|
1452
|
+
|
|
1453
|
+
stack_trace_c = create_string_buffer(get_utf8_bytes(stacktrace))
|
|
1454
|
+
file_name_c = create_string_buffer(get_utf8_bytes(file_name))
|
|
1455
|
+
exception_class_c = create_string_buffer(get_utf8_bytes(excptnclsname))
|
|
1456
|
+
throwing_class_c = create_string_buffer(get_utf8_bytes(throwingclsname))
|
|
1457
|
+
exception_message_c = create_string_buffer(get_utf8_bytes(excptnmsg))
|
|
1458
|
+
throwing_method_c = create_string_buffer(get_utf8_bytes(throwingmtdname))
|
|
1459
|
+
exception_cause_c = create_string_buffer(get_utf8_bytes(excptncause))
|
|
1460
|
+
|
|
1461
|
+
self.lib.getstacktracearray(bt,
|
|
1462
|
+
stack_trace_c,
|
|
1463
|
+
file_name_c,
|
|
1464
|
+
exception_class_c,
|
|
1465
|
+
throwing_class_c,
|
|
1466
|
+
exception_message_c,
|
|
1467
|
+
throwing_method_c,
|
|
1468
|
+
excptnlineno,
|
|
1469
|
+
exception_cause_c
|
|
1470
|
+
)
|
|
1471
|
+
|
|
1472
|
+
del stack_trace_c, file_name_c, exception_class_c, throwing_class_c
|
|
1473
|
+
del exception_message_c, throwing_method_c, exception_cause_c
|
|
1474
|
+
|
|
1475
|
+
def exceptiondump(self, bt, mpp, starttime, excptnclsname, excptnmsg, throwingclsname,
|
|
1476
|
+
throwingmtdname, excptncause, excptnlineno, stacktrace, file_name):
|
|
1477
|
+
if self.cav_env == "NATIVE":
|
|
1478
|
+
self.exception_dump_native(bt, mpp, starttime, excptnclsname, excptnmsg, throwingclsname,
|
|
1479
|
+
throwingmtdname, excptncause, excptnlineno, stacktrace, file_name)
|
|
1480
|
+
elif self.cav_env == "AWS_LAMBDA":
|
|
1481
|
+
udp.exception_dump(self, bt, mpp, starttime, excptnclsname, excptnmsg, throwingclsname,
|
|
1482
|
+
throwingmtdname, excptncause, excptnlineno, stacktrace)
|
|
1483
|
+
|
|
1484
|
+
def heap_dump_py(self):
|
|
1485
|
+
heap_string = create_heap_dump_muppy(self)
|
|
1486
|
+
heap = bytes(heap_string.encode('utf-8'))
|
|
1487
|
+
return heap
|
|
1488
|
+
|
|
1489
|
+
######################
|
|
1490
|
+
# UNUSED FUNCTIONS
|
|
1491
|
+
######################
|
|
1492
|
+
|
|
1493
|
+
def wait_for_start(self, timeout_ms=None):
|
|
1494
|
+
"""Wait for the agent to start and get configured.
|
|
1495
|
+
|
|
1496
|
+
Other Parameters
|
|
1497
|
+
----------------
|
|
1498
|
+
timeout_ms : int, optional
|
|
1499
|
+
The maximum time to wait for the agent to start and be configured
|
|
1500
|
+
before returning.
|
|
1501
|
+
|
|
1502
|
+
Returns
|
|
1503
|
+
-------
|
|
1504
|
+
bool
|
|
1505
|
+
Returns ``True`` if the agent is enabled after waiting, else
|
|
1506
|
+
``False``.
|
|
1507
|
+
|
|
1508
|
+
"""
|
|
1509
|
+
if timeout_ms is not None:
|
|
1510
|
+
with self.timer() as timer:
|
|
1511
|
+
if self.proxy_control_svc is not None:
|
|
1512
|
+
self.proxy_control_svc.wait_for_start(timeout_ms=timeout_ms)
|
|
1513
|
+
|
|
1514
|
+
if self.config_svc is not None:
|
|
1515
|
+
timeout_ms = max(0, timeout_ms - timer.duration_ms)
|
|
1516
|
+
self.config_svc.wait_for_config(timeout_ms=timeout_ms)
|
|
1517
|
+
|
|
1518
|
+
if self.tx_svc is not None:
|
|
1519
|
+
timeout_ms = max(0, timeout_ms - timer.duration_ms)
|
|
1520
|
+
self.tx_svc.wait_for_start(timeout_ms=timeout_ms)
|
|
1521
|
+
else:
|
|
1522
|
+
self.proxy_control_svc.wait_for_start()
|
|
1523
|
+
self.config_svc.wait_for_config()
|
|
1524
|
+
self.tx_svc.wait_for_start()
|
|
1525
|
+
|
|
1526
|
+
return self.enabled
|
|
1527
|
+
|
|
1528
|
+
|
|
1529
|
+
def wait_for_end(self, timeout_ms=None):
|
|
1530
|
+
"""Wait for the agent to finish reporting any pending BTs.
|
|
1531
|
+
|
|
1532
|
+
"""
|
|
1533
|
+
self.tx_svc.wait_for_end(timeout_ms=timeout_ms)
|
|
1534
|
+
|
|
1535
|
+
#@property
|
|
1536
|
+
def enabled(self):
|
|
1537
|
+
"""Return true if the agent has started and is enabled.
|
|
1538
|
+
|
|
1539
|
+
"""
|
|
1540
|
+
return (
|
|
1541
|
+
self.nd_init_done and
|
|
1542
|
+
self.config_svc and self.config_svc.enabled and
|
|
1543
|
+
self.tx_svc)
|
|
1544
|
+
|
|
1545
|
+
##################################
|
|
1546
|
+
# TRANSACTION RELATED FUNCTIONS
|
|
1547
|
+
##################################
|
|
1548
|
+
|
|
1549
|
+
def get_current_bt(self):
|
|
1550
|
+
"""Get the currently active BT for the calling context.
|
|
1551
|
+
|
|
1552
|
+
The calling context is the active greenlet or thread, depending on
|
|
1553
|
+
whether greenlets are in use or not. If the agent is disabled, or if
|
|
1554
|
+
there is no active transaction for the calling context, None is
|
|
1555
|
+
returned.
|
|
1556
|
+
|
|
1557
|
+
Returns
|
|
1558
|
+
-------
|
|
1559
|
+
bt : appdynamics.agent.core.bt.Transaction or None
|
|
1560
|
+
the active business transaction (if any)
|
|
1561
|
+
|
|
1562
|
+
"""
|
|
1563
|
+
# if not self.enabled:
|
|
1564
|
+
# return None
|
|
1565
|
+
|
|
1566
|
+
if sys.version_info >= (3, 7, 0):
|
|
1567
|
+
return self.currentbt_provider.active()
|
|
1568
|
+
else:
|
|
1569
|
+
return self.current_bts.get(get_ident(), None)
|
|
1570
|
+
|
|
1571
|
+
def set_current_bt(self, bt):
|
|
1572
|
+
if bt:
|
|
1573
|
+
if sys.version_info >= (3, 7, 0):
|
|
1574
|
+
self.currentbt_provider.activate(bt)
|
|
1575
|
+
else:
|
|
1576
|
+
self.current_bts[get_ident()] = bt
|
|
1577
|
+
|
|
1578
|
+
def unset_current_bt(self):
|
|
1579
|
+
if sys.version_info >= (3, 7, 0):
|
|
1580
|
+
self.currentbt_provider.reset()
|
|
1581
|
+
else:
|
|
1582
|
+
self.current_bts.pop(get_ident(), None)
|
|
1583
|
+
|
|
1584
|
+
def get_current_status_code(self):
|
|
1585
|
+
if sys.version_info >= (3, 7, 0):
|
|
1586
|
+
return self.statuscode_provider.active()
|
|
1587
|
+
else:
|
|
1588
|
+
return self.current_status_code.get(get_ident(), None)
|
|
1589
|
+
|
|
1590
|
+
def set_current_status_code(self, status_code):
|
|
1591
|
+
if status_code:
|
|
1592
|
+
if sys.version_info >= (3, 7, 0):
|
|
1593
|
+
self.statuscode_provider.activate(status_code)
|
|
1594
|
+
else:
|
|
1595
|
+
self.current_status_code[get_ident()] = status_code
|
|
1596
|
+
|
|
1597
|
+
def unset_current_status_code(self):
|
|
1598
|
+
if sys.version_info >= (3, 7, 0):
|
|
1599
|
+
self.statuscode_provider.reset()
|
|
1600
|
+
else:
|
|
1601
|
+
self.current_status_code.pop(get_ident(), None)
|
|
1602
|
+
|
|
1603
|
+
def set_transaction_context(self, context):
|
|
1604
|
+
if context:
|
|
1605
|
+
context.tier_name = self.tier_name
|
|
1606
|
+
context.server_name = self.server_name
|
|
1607
|
+
context.instance_name = self.instance_name
|
|
1608
|
+
context.function_name = self.function_name
|
|
1609
|
+
context.flow_path_id = generate_flow_path_id()
|
|
1610
|
+
context.fp_topo = self.fp_topo
|
|
1611
|
+
|
|
1612
|
+
if sys.version_info >= (3, 7, 0):
|
|
1613
|
+
self.context_provider.activate(context)
|
|
1614
|
+
else:
|
|
1615
|
+
self.transaction_context[get_ident()] = context
|
|
1616
|
+
|
|
1617
|
+
def get_transaction_context(self):
|
|
1618
|
+
if sys.version_info >= (3, 7, 0):
|
|
1619
|
+
context = self.context_provider.active()
|
|
1620
|
+
else:
|
|
1621
|
+
context = self.transaction_context.get(get_ident(), None)
|
|
1622
|
+
return context
|
|
1623
|
+
|
|
1624
|
+
def reset_transaction_context(self):
|
|
1625
|
+
if sys.version_info >= (3, 7, 0):
|
|
1626
|
+
self.currentbt_provider.reset()
|
|
1627
|
+
self.statuscode_provider.reset()
|
|
1628
|
+
self.context_provider.reset()
|
|
1629
|
+
else:
|
|
1630
|
+
self.transaction_context.pop(get_ident(), None)
|
|
1631
|
+
self.current_status_code.pop(get_ident(), None)
|
|
1632
|
+
self.current_bts.pop(get_ident(), None)
|
|
1633
|
+
|
|
1634
|
+
|
|
1635
|
+
##################
|
|
1636
|
+
# UNUSED CLASSES
|
|
1637
|
+
##################
|
|
1638
|
+
|
|
1639
|
+
|
|
1640
|
+
class AgentNotStartedException(Exception):
|
|
1641
|
+
pass
|
|
1642
|
+
|
|
1643
|
+
|
|
1644
|
+
class AgentNotReadyException(Exception):
|
|
1645
|
+
pass
|
|
1646
|
+
|
|
1647
|
+
|
|
1648
|
+
class IgnoreTransaction(Exception):
|
|
1649
|
+
pass
|
|
1650
|
+
|
|
1651
|
+
|