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,75 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import platform
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_process_name():
|
|
7
|
+
"""Return current process name (basename of argv[0])."""
|
|
8
|
+
try:
|
|
9
|
+
# Linux fast path
|
|
10
|
+
with open('/proc/self/comm', 'r') as f:
|
|
11
|
+
return f.read().strip()
|
|
12
|
+
except (IOError, OSError):
|
|
13
|
+
pass
|
|
14
|
+
# Cross-platform fallback
|
|
15
|
+
if sys.argv:
|
|
16
|
+
return os.path.basename(sys.argv[0])
|
|
17
|
+
return os.path.basename(sys.executable)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_cmdline():
|
|
21
|
+
"""Return command line as a list of strings."""
|
|
22
|
+
try:
|
|
23
|
+
with open('/proc/self/cmdline', 'rb') as f:
|
|
24
|
+
return f.read().decode('utf-8', errors='replace').split('\x00')
|
|
25
|
+
except (IOError, OSError):
|
|
26
|
+
pass
|
|
27
|
+
return list(sys.argv) # fallback: sys.argv covers script args
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def get_rss_bytes():
|
|
31
|
+
"""Return process RSS (resident set size) in bytes."""
|
|
32
|
+
try:
|
|
33
|
+
# Linux: /proc/self/status — VmRSS in kB
|
|
34
|
+
with open('/proc/self/status', 'r') as f:
|
|
35
|
+
for line in f:
|
|
36
|
+
if line.startswith('VmRSS:'):
|
|
37
|
+
return int(line.split()[1]) * 1024
|
|
38
|
+
except (IOError, OSError):
|
|
39
|
+
pass
|
|
40
|
+
try:
|
|
41
|
+
# macOS / BSD fallback via resource module
|
|
42
|
+
import resource
|
|
43
|
+
rss = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
|
|
44
|
+
if platform.system() == 'Linux':
|
|
45
|
+
rss *= 1024 # Linux reports ru_maxrss in kB
|
|
46
|
+
return rss
|
|
47
|
+
except (ImportError, AttributeError):
|
|
48
|
+
pass
|
|
49
|
+
return 0
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_virtual_memory():
|
|
53
|
+
"""Return (total, available, percent, used, free) in bytes."""
|
|
54
|
+
try:
|
|
55
|
+
mem = {}
|
|
56
|
+
with open('/proc/meminfo', 'r') as f:
|
|
57
|
+
for line in f:
|
|
58
|
+
parts = line.split()
|
|
59
|
+
if len(parts) >= 2:
|
|
60
|
+
mem[parts[0].rstrip(':')] = int(parts[1]) * 1024
|
|
61
|
+
total = mem.get('MemTotal', 0)
|
|
62
|
+
available = mem.get('MemAvailable', mem.get('MemFree', 0))
|
|
63
|
+
free = mem.get('MemFree', 0)
|
|
64
|
+
used = total - available
|
|
65
|
+
percent = (used / total * 100) if total else 0.0
|
|
66
|
+
return (total, available, percent, used, free)
|
|
67
|
+
except (IOError, OSError, ValueError):
|
|
68
|
+
pass
|
|
69
|
+
return (0, 0, 0.0, 0, 0)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def get_free_memory_mb():
|
|
73
|
+
"""Return free physical memory in MB."""
|
|
74
|
+
return get_virtual_memory()[4] >> 20
|
|
75
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from pythonagent.agent.internal.proc_compat import get_rss_bytes
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
#def elapsed_since(start):
|
|
6
|
+
# return time.strftime("%H:%M:%S", time.gmtime(time.time() - start))
|
|
7
|
+
|
|
8
|
+
def elapsed_since(start):
|
|
9
|
+
#return time.strftime("%H:%M:%S", time.gmtime(time.time() - start))
|
|
10
|
+
elapsed = time.time() - start
|
|
11
|
+
if elapsed < 1:
|
|
12
|
+
return str(round(elapsed*1000,2)) + " ms"
|
|
13
|
+
if elapsed < 60:
|
|
14
|
+
return str(round(elapsed, 2)) + " s"
|
|
15
|
+
if elapsed < 3600:
|
|
16
|
+
return str(round(elapsed/60, 2)) + " min"
|
|
17
|
+
else:
|
|
18
|
+
return str(round(elapsed / 3600, 2)) + " hrs"
|
|
19
|
+
|
|
20
|
+
def format_bytes(bytes):
|
|
21
|
+
if abs(bytes) < 1000:
|
|
22
|
+
return str(bytes)+" B"
|
|
23
|
+
elif abs(bytes) < 1e6:
|
|
24
|
+
return str(round(bytes/1e3,2)) + " kB"
|
|
25
|
+
elif abs(bytes) < 1e9:
|
|
26
|
+
return str(round(bytes / 1e6, 2)) + " MB"
|
|
27
|
+
else:
|
|
28
|
+
return str(round(bytes / 1e9, 2)) + " GB"
|
|
29
|
+
|
|
30
|
+
def get_process_memory():
|
|
31
|
+
return get_rss_bytes()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def profile(func):
|
|
35
|
+
def wrapper(*args, **kwargs):
|
|
36
|
+
mem_before = get_process_memory()
|
|
37
|
+
start = time.time()
|
|
38
|
+
result = func(*args, **kwargs)
|
|
39
|
+
elapsed_time = elapsed_since(start)
|
|
40
|
+
mem_after = get_process_memory()
|
|
41
|
+
print("{0}: memory before: {1}, after: {2}, consumed: {3}; exec time: {4}".format(
|
|
42
|
+
func.__name__,
|
|
43
|
+
format_bytes(mem_before), format_bytes(mem_after), format_bytes(mem_after - mem_before),
|
|
44
|
+
elapsed_time))
|
|
45
|
+
return result
|
|
46
|
+
return wrapper
|
|
47
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import contextvars
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
_CAV_CONTEXTVAR = contextvars.ContextVar("cavisson_contextvar", default=None)
|
|
5
|
+
_CURRENTBT_CONTEXTVAR = contextvars.ContextVar("currentbt_contextvar", default=None)
|
|
6
|
+
_STATUSCODE_CONTEXTVAR = contextvars.ContextVar("statuscode_contextvar", default=None)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ContextProvider(object):
|
|
10
|
+
|
|
11
|
+
def __init__(self):
|
|
12
|
+
self.token = None
|
|
13
|
+
|
|
14
|
+
def _has_active_context(self):
|
|
15
|
+
ctx = _CAV_CONTEXTVAR.get()
|
|
16
|
+
return ctx is not None
|
|
17
|
+
|
|
18
|
+
def activate(self, ctx):
|
|
19
|
+
self.token = _CAV_CONTEXTVAR.set(ctx)
|
|
20
|
+
|
|
21
|
+
def active(self):
|
|
22
|
+
item = _CAV_CONTEXTVAR.get()
|
|
23
|
+
return item
|
|
24
|
+
|
|
25
|
+
def reset(self):
|
|
26
|
+
pass
|
|
27
|
+
#if self.token:
|
|
28
|
+
#_CAV_CONTEXTVAR.reset(self.token)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class CurrentBTProvider(object):
|
|
33
|
+
|
|
34
|
+
def __init__(self):
|
|
35
|
+
self.token = None
|
|
36
|
+
|
|
37
|
+
def _has_active_context(self):
|
|
38
|
+
ctx = _CURRENTBT_CONTEXTVAR.get()
|
|
39
|
+
return ctx is not None
|
|
40
|
+
|
|
41
|
+
def activate(self, ctx):
|
|
42
|
+
self.token = _CURRENTBT_CONTEXTVAR.set(ctx)
|
|
43
|
+
|
|
44
|
+
def active(self):
|
|
45
|
+
item = _CURRENTBT_CONTEXTVAR.get()
|
|
46
|
+
return item
|
|
47
|
+
|
|
48
|
+
def reset(self):
|
|
49
|
+
pass
|
|
50
|
+
#if self.token:
|
|
51
|
+
#_CURRENTBT_CONTEXTVAR.reset(self.token)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class StatusCodeProvider(object):
|
|
56
|
+
|
|
57
|
+
def __init__(self):
|
|
58
|
+
self.token = None
|
|
59
|
+
|
|
60
|
+
def _has_active_context(self):
|
|
61
|
+
ctx = _STATUSCODE_CONTEXTVAR.get()
|
|
62
|
+
return ctx is not None
|
|
63
|
+
|
|
64
|
+
def activate(self, ctx):
|
|
65
|
+
self.token = _STATUSCODE_CONTEXTVAR.set(ctx)
|
|
66
|
+
|
|
67
|
+
def active(self):
|
|
68
|
+
item = _STATUSCODE_CONTEXTVAR.get()
|
|
69
|
+
return item
|
|
70
|
+
|
|
71
|
+
def reset(self):
|
|
72
|
+
pass
|
|
73
|
+
#if self.token:
|
|
74
|
+
#_STATUSCODE_CONTEXTVAR.reset(self.token)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
import platform
|
|
5
|
+
import time
|
|
6
|
+
import threading
|
|
7
|
+
import traceback
|
|
8
|
+
import sys
|
|
9
|
+
import multiprocessing
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def dumpstacks(nd_build):
|
|
13
|
+
my_system = platform.uname()
|
|
14
|
+
osName = my_system.system
|
|
15
|
+
osVersion = my_system.version
|
|
16
|
+
arch = my_system.machine
|
|
17
|
+
cpu_count = multiprocessing.cpu_count()
|
|
18
|
+
l = os.getloadavg()
|
|
19
|
+
res = sum(list(l))
|
|
20
|
+
sys_load_avg = round(res, 2) / 3
|
|
21
|
+
header = ("Full thread dump BCI Agent :- [ Dump Taken at : " + datetime.now().strftime(
|
|
22
|
+
"%d/%m/%Y %H:%M:%S") + " , Where BCIAgent build = " + nd_build + "]")
|
|
23
|
+
deadlocked_threads = ""
|
|
24
|
+
nid = "0x0"
|
|
25
|
+
prio = "5"
|
|
26
|
+
vendor = ""
|
|
27
|
+
version = ""
|
|
28
|
+
system_name = os.getenv('HOSTNAME')
|
|
29
|
+
# //****append the thread details into list(code)*****//
|
|
30
|
+
code = []
|
|
31
|
+
o = []
|
|
32
|
+
al = []
|
|
33
|
+
|
|
34
|
+
thread_dict = {}
|
|
35
|
+
for thread in threading.enumerate():
|
|
36
|
+
thread_dict[thread.ident] = thread
|
|
37
|
+
|
|
38
|
+
for threadId, stack in sys._current_frames().items():
|
|
39
|
+
thread_name = None
|
|
40
|
+
thread_status = None
|
|
41
|
+
thread_object = thread_dict.get(threadId, None)
|
|
42
|
+
|
|
43
|
+
if thread_object:
|
|
44
|
+
thread_name = thread_object.name
|
|
45
|
+
if thread_object.isDaemon():
|
|
46
|
+
thread_status = 'Daemon'
|
|
47
|
+
else:
|
|
48
|
+
thread_status = 'Non-Daemon'
|
|
49
|
+
|
|
50
|
+
if not thread_name:
|
|
51
|
+
thread_name = "unknown"
|
|
52
|
+
|
|
53
|
+
if not thread_status:
|
|
54
|
+
thread_status = "unknown"
|
|
55
|
+
|
|
56
|
+
thread_string = ("\n\n'{}'".format(thread_name)
|
|
57
|
+
+ " prio={}".format(prio)
|
|
58
|
+
+ " tid={}".format(threadId)
|
|
59
|
+
+ " nid={}".format(nid)
|
|
60
|
+
+ " " + thread_status + " \n"
|
|
61
|
+
+ "java.lang.Thread.State: {} ".format(thread_status))
|
|
62
|
+
|
|
63
|
+
code.extend([thread_string])
|
|
64
|
+
|
|
65
|
+
for filename, lineno, name, line in traceback.extract_stack(stack):
|
|
66
|
+
code.append('File: "%s", line %d, in %s, at %s' % (filename, lineno, name, datetime.now()))
|
|
67
|
+
if line:
|
|
68
|
+
code.append(" %s" % (line.strip()))
|
|
69
|
+
|
|
70
|
+
thread_dump_header = {
|
|
71
|
+
"": header,
|
|
72
|
+
"vmName": osName,
|
|
73
|
+
"version": version,
|
|
74
|
+
"vendor": vendor,
|
|
75
|
+
"osName": osName,
|
|
76
|
+
"osVersion": osVersion,
|
|
77
|
+
"arch": arch,
|
|
78
|
+
"noOfProcessors": cpu_count,
|
|
79
|
+
"SysLoadAvg": sys_load_avg,
|
|
80
|
+
"deadlocked threads": deadlocked_threads
|
|
81
|
+
}
|
|
82
|
+
joined_code = "\n".join((code))
|
|
83
|
+
return f"{thread_dump_header}" + '\n' + f"{joined_code}\n"
|
|
84
|
+
|
|
85
|
+
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
import os
|
|
3
|
+
import socket
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
import threading
|
|
7
|
+
import json
|
|
8
|
+
from .udp_message import create_start_transaction_message, create_end_transaction_message
|
|
9
|
+
from .udp_message import create_method_entry_message, create_method_exit_message
|
|
10
|
+
from .udp_message import create_transaction_encode_http_message
|
|
11
|
+
from .udp_message import create_exception_encode_message
|
|
12
|
+
from .udp_message import create_havoc_message
|
|
13
|
+
from .udp_message import create_init_message, create_agent_initialize_message
|
|
14
|
+
from .udp_message import create_heartbeat_message
|
|
15
|
+
import time
|
|
16
|
+
import logging
|
|
17
|
+
|
|
18
|
+
udp_connection = None
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger('pythonagent.agent')
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class UDPConnection(object):
|
|
24
|
+
def __init__(self, agent_obj):
|
|
25
|
+
|
|
26
|
+
if 'CAV_APP_AGENT_PROXYIP' in os.environ:
|
|
27
|
+
self.cav_proxy_ip = os.environ['CAV_APP_AGENT_PROXYIP']
|
|
28
|
+
else:
|
|
29
|
+
self.cav_proxy_ip = "127.0.0.1"
|
|
30
|
+
|
|
31
|
+
if 'CAV_APP_AGENT_PROXYPORT' in os.environ:
|
|
32
|
+
self.cav_proxy_port = int(os.environ['CAV_APP_AGENT_PROXYPORT'])
|
|
33
|
+
|
|
34
|
+
else:
|
|
35
|
+
self.cav_proxy_port = 10000
|
|
36
|
+
|
|
37
|
+
self.server_address_port = (self.cav_proxy_ip, self.cav_proxy_port)
|
|
38
|
+
|
|
39
|
+
# Create a UDP socket at client side
|
|
40
|
+
try:
|
|
41
|
+
|
|
42
|
+
self.UDPClientSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
|
|
43
|
+
logger.debug("Server Port {}".format(self.server_address_port))
|
|
44
|
+
|
|
45
|
+
havoc_thread = threading.Thread(target=incoming_message_processor, name="havoc_thread",
|
|
46
|
+
args=(self.UDPClientSocket, agent_obj), daemon=True)
|
|
47
|
+
havoc_thread.start()
|
|
48
|
+
|
|
49
|
+
heartbeat_thread = threading.Thread(target=heartbeat_sender, name="heartbeat_thread",
|
|
50
|
+
args=(self.UDPClientSocket, self.server_address_port, agent_obj),
|
|
51
|
+
daemon=True)
|
|
52
|
+
heartbeat_thread.start()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
except:
|
|
56
|
+
logger.warning("Unable to create UDP Connection")
|
|
57
|
+
|
|
58
|
+
def send(self, message, tx_type="non_start_fp"):
|
|
59
|
+
|
|
60
|
+
# Send to server using created UDP socket
|
|
61
|
+
try:
|
|
62
|
+
self.UDPClientSocket.sendto(message, self.server_address_port)
|
|
63
|
+
|
|
64
|
+
except:
|
|
65
|
+
logger.warning("Unable to send UDP packet")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def heartbeat_sender(udp_socket, address_port, ag_obj):
|
|
69
|
+
logger.info("heartbeat sender started")
|
|
70
|
+
context = ag_obj.get_transaction_context()
|
|
71
|
+
if not context:
|
|
72
|
+
from pythonagent.agent.internal.agent import TransactionContext
|
|
73
|
+
context = TransactionContext() # Create dummy context to avoid failure
|
|
74
|
+
message = create_heartbeat_message(context, ag_obj)
|
|
75
|
+
logger.info("heartbeat message {}".format(message))
|
|
76
|
+
while True:
|
|
77
|
+
try:
|
|
78
|
+
logger.debug("heartbeat about to send")
|
|
79
|
+
udp_socket.sendto(message, address_port)
|
|
80
|
+
logger.info("heartbeat sent")
|
|
81
|
+
time.sleep(10)
|
|
82
|
+
logger.debug("heartbeat sleep completed")
|
|
83
|
+
except Exception as e:
|
|
84
|
+
logger.error("heartbeat exception", e)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def incoming_message_processor(udp_socket, agent_obj):
|
|
88
|
+
logger.debug("New thread started")
|
|
89
|
+
|
|
90
|
+
from pythonagent.agent.probes.havoc.havoc_manager import NDNetHavocMonitor # Don't shift to top, it will cause circular import
|
|
91
|
+
from pythonagent.utils import process_raw_havoc_message, process_udp_agent_init_response
|
|
92
|
+
havoc_monitor = NDNetHavocMonitor.get_instance()
|
|
93
|
+
# logger.debug("udp.py havoc id {}".format(id(havoc_monitor)))
|
|
94
|
+
udp_socket.settimeout(2.0)
|
|
95
|
+
buffer_size = 4096
|
|
96
|
+
counter = 0
|
|
97
|
+
|
|
98
|
+
while True:
|
|
99
|
+
|
|
100
|
+
try: # timeout (non-blocking behaviour) added because in warm-start, listener is not working sometimes
|
|
101
|
+
counter += 1
|
|
102
|
+
logger.debug("counter: {}".format(counter))
|
|
103
|
+
logger.debug("Going to call recv from api for {} time".format(counter))
|
|
104
|
+
logger.debug("Going to call recv from api")
|
|
105
|
+
data, address = udp_socket.recvfrom(buffer_size)
|
|
106
|
+
logger.debug("incoming received message = {} from address {}".format(data, address))
|
|
107
|
+
logger.debug("after gettting message")
|
|
108
|
+
|
|
109
|
+
output = str(data)
|
|
110
|
+
|
|
111
|
+
if output[2:5] == "[\\n": # Output starts with b'[\n
|
|
112
|
+
process_udp_agent_init_response(output, agent_obj)
|
|
113
|
+
continue
|
|
114
|
+
|
|
115
|
+
if output == "b'Heart Beat Received'":
|
|
116
|
+
logger.debug("ignoring heartbeat acknowledgement")
|
|
117
|
+
continue
|
|
118
|
+
try:
|
|
119
|
+
body, header_dict = process_raw_havoc_message(output, agent_obj.cav_env)
|
|
120
|
+
havoc_monitor.parse_nethavoc_config(body, header_dict)
|
|
121
|
+
|
|
122
|
+
except Exception as e:
|
|
123
|
+
logger.warning("Unable to parse config: {}", e)
|
|
124
|
+
|
|
125
|
+
except socket.timeout:
|
|
126
|
+
logger.debug("recv timed out") # This is not an exception, but a mechanism to implement timeout
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def generate_bt():
|
|
130
|
+
id = uuid.uuid4()
|
|
131
|
+
id_int = id.int
|
|
132
|
+
return id_int
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def sdk_init(agent_obj):
|
|
136
|
+
agent_obj.udp_connection = UDPConnection(agent_obj)
|
|
137
|
+
logger.debug("called sdk init")
|
|
138
|
+
context = agent_obj.get_transaction_context()
|
|
139
|
+
if not context:
|
|
140
|
+
from pythonagent.agent.internal.agent import TransactionContext
|
|
141
|
+
context = TransactionContext() # Create dummy context to avoid failure
|
|
142
|
+
logger.debug("transaction context dictionary inside sdk init in udp.py {}".format(context.function_name))
|
|
143
|
+
message = create_init_message(context, agent_obj)
|
|
144
|
+
logger.debug("first message to be sent to proxy {}".format(message))
|
|
145
|
+
agent_obj.udp_connection.send(message)
|
|
146
|
+
logger.debug("init sent")
|
|
147
|
+
|
|
148
|
+
message = create_agent_initialize_message(context, agent_obj)
|
|
149
|
+
logger.debug("sending agent initialize message {}".format(message))
|
|
150
|
+
agent_obj.udp_connection.send(message)
|
|
151
|
+
logger.debug("sent agent initialize message")
|
|
152
|
+
return udp_connection
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def sdk_free(agent_obj):
|
|
156
|
+
pass
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def method_entry(agent_obj, bt, method, query_string, url_parameter, query_parameter="NA"):
|
|
160
|
+
context = agent_obj.get_transaction_context()
|
|
161
|
+
message = create_method_entry_message(context, bt, method, query_string, url_parameter, query_parameter, agent_obj)
|
|
162
|
+
|
|
163
|
+
logger.info("method_entry {}".format(message))
|
|
164
|
+
agent_obj.udp_connection.send(message)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def method_exit(agent_obj, bt, method, backend_header, status, duration):
|
|
168
|
+
context = agent_obj.get_transaction_context()
|
|
169
|
+
# message = create_method_exit_message(context, bt, method)
|
|
170
|
+
message = create_method_exit_message(context, bt, method, backend_header, status, duration, agent_obj)
|
|
171
|
+
logger.info("method_exit: status {}, duration {}, message {}".format(status, duration, message))
|
|
172
|
+
agent_obj.udp_connection.send(message)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def start_business_transaction(agent_obj, bt_name, correlation_header):
|
|
176
|
+
if os.environ['nd_init_done'] == '0':
|
|
177
|
+
agent_obj.sdk_init()
|
|
178
|
+
|
|
179
|
+
context = agent_obj.get_transaction_context()
|
|
180
|
+
# message = udp_message.create_start_transaction_message(context, bt_name, correlation_header)
|
|
181
|
+
message = create_start_transaction_message(context, bt_name, correlation_header, agent_obj)
|
|
182
|
+
logger.info("start_business_transaction {}".format(message))
|
|
183
|
+
agent_obj.udp_connection.send(message, "start_fp")
|
|
184
|
+
|
|
185
|
+
bt = generate_bt()
|
|
186
|
+
|
|
187
|
+
agent_obj.active_bts.add(bt)
|
|
188
|
+
agent_obj.set_current_bt(bt)
|
|
189
|
+
|
|
190
|
+
return bt
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def end_business_transaction(agent_obj, bt):
|
|
194
|
+
status_code = agent_obj.get_current_status_code()
|
|
195
|
+
context = agent_obj.get_transaction_context()
|
|
196
|
+
message = create_end_transaction_message(context, bt, status_code, agent_obj)
|
|
197
|
+
|
|
198
|
+
agent_obj.logger.info("status_code {}, message {}".format(status_code, message))
|
|
199
|
+
|
|
200
|
+
agent_obj.udp_connection.send(message)
|
|
201
|
+
rc = 0 # DUMMY VALUE FOR SUCCESS
|
|
202
|
+
agent_obj.reset_transaction_context()
|
|
203
|
+
|
|
204
|
+
return rc
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def store_business_transaction(agent_obj, bt, unique_bt_id):
|
|
208
|
+
pass
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def db_call_begin(bt, db_host, db_query, db_query_params=None):
|
|
212
|
+
pass
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def db_call_end(bt, ip_handle):
|
|
216
|
+
pass
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def http_call_begin(agent_obj, bt, http_host, url):
|
|
220
|
+
handle = 0 # DUMMY NON ZERO VALUE
|
|
221
|
+
return handle
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def http_call_end(agent_obj, bt, ip_handle):
|
|
225
|
+
pass
|
|
226
|
+
|
|
227
|
+
def http_req_resp_wrapper(agent_obj, bt, rbuffer, rtype, statuscode):
|
|
228
|
+
context = agent_obj.get_transaction_context()
|
|
229
|
+
message = create_transaction_encode_http_message(context, bt, rbuffer, rtype, statuscode, agent_obj)
|
|
230
|
+
logger.info("transaction_encode_http message {}".format(message))
|
|
231
|
+
agent_obj.udp_connection.send(message)
|
|
232
|
+
|
|
233
|
+
def exception_dump(agent_obj, bt, mpp, starttime, excptnclsname, excptnmsg, throwingclsname,
|
|
234
|
+
throwingmtdname, excptncause, excptnlineno, stacktrace):
|
|
235
|
+
context = agent_obj.get_transaction_context()
|
|
236
|
+
message = create_exception_encode_message(context, excptnlineno, excptnclsname, throwingclsname, throwingmtdname,
|
|
237
|
+
excptnmsg, excptncause, stacktrace, starttime, agent_obj)
|
|
238
|
+
logger.info("exception_encode message {}".format(message))
|
|
239
|
+
agent_obj.udp_connection.send(message)
|
|
240
|
+
|
|
241
|
+
def havoc_message(agent_obj, havoc_header):
|
|
242
|
+
context = agent_obj.get_transaction_context()
|
|
243
|
+
message = create_havoc_message(context, havoc_header, agent_obj)
|
|
244
|
+
logger.debug("havoc_message: {}".format(message))
|
|
245
|
+
agent_obj.udp_connection.send(message)
|