cavisson-pythonagent 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. cavisson_pythonagent-0.0.1.dist-info/METADATA +32 -0
  2. cavisson_pythonagent-0.0.1.dist-info/RECORD +180 -0
  3. cavisson_pythonagent-0.0.1.dist-info/WHEEL +5 -0
  4. cavisson_pythonagent-0.0.1.dist-info/licenses/LICENSE +19 -0
  5. cavisson_pythonagent-0.0.1.dist-info/top_level.txt +1 -0
  6. pythonagent/__init__.py +22 -0
  7. pythonagent/agent/__init__.py +219 -0
  8. pythonagent/agent/internal/__init__.py +1 -0
  9. pythonagent/agent/internal/agent.py +1651 -0
  10. pythonagent/agent/internal/framesinfo.py +152 -0
  11. pythonagent/agent/internal/heap_dump.py +39 -0
  12. pythonagent/agent/internal/intercept_module.py +70 -0
  13. pythonagent/agent/internal/logs.py +122 -0
  14. pythonagent/agent/internal/metadata/__init__.py +0 -0
  15. pythonagent/agent/internal/metadata/agent_meta_data.py +276 -0
  16. pythonagent/agent/internal/proc_compat.py +75 -0
  17. pythonagent/agent/internal/profile.py +47 -0
  18. pythonagent/agent/internal/provider.py +83 -0
  19. pythonagent/agent/internal/thread_dump.py +85 -0
  20. pythonagent/agent/internal/udp.py +245 -0
  21. pythonagent/agent/internal/udp_message.py +800 -0
  22. pythonagent/agent/probes/Instrumentation/__init__.py +340 -0
  23. pythonagent/agent/probes/Instrumentation/find.py +243 -0
  24. pythonagent/agent/probes/Instrumentation/module_version_resolver.py +155 -0
  25. pythonagent/agent/probes/Instrumentation/new_parser.py +64 -0
  26. pythonagent/agent/probes/Instrumentation/parser.py +129 -0
  27. pythonagent/agent/probes/__init__.py +219 -0
  28. pythonagent/agent/probes/base.py +303 -0
  29. pythonagent/agent/probes/cache/__init__.py +51 -0
  30. pythonagent/agent/probes/cache/redis.py +119 -0
  31. pythonagent/agent/probes/cache/redis_asyncio.py +83 -0
  32. pythonagent/agent/probes/coroutines/__init__.py +1 -0
  33. pythonagent/agent/probes/coroutines/asyncio.py +63 -0
  34. pythonagent/agent/probes/elasticdb/__init__.py +7 -0
  35. pythonagent/agent/probes/elasticdb/aelastic.py +54 -0
  36. pythonagent/agent/probes/frameworks/__init__.py +27 -0
  37. pythonagent/agent/probes/frameworks/agentprofiler.py +105 -0
  38. pythonagent/agent/probes/frameworks/aiohttp_web.py +155 -0
  39. pythonagent/agent/probes/frameworks/aisess.py +151 -0
  40. pythonagent/agent/probes/frameworks/asgi.py +340 -0
  41. pythonagent/agent/probes/frameworks/bottle.py +27 -0
  42. pythonagent/agent/probes/frameworks/cherry.py +25 -0
  43. pythonagent/agent/probes/frameworks/django.py +128 -0
  44. pythonagent/agent/probes/frameworks/falcon.py +21 -0
  45. pythonagent/agent/probes/frameworks/fastapi.py +35 -0
  46. pythonagent/agent/probes/frameworks/flask.py +30 -0
  47. pythonagent/agent/probes/frameworks/pyramid.py +56 -0
  48. pythonagent/agent/probes/frameworks/test.py +108 -0
  49. pythonagent/agent/probes/frameworks/tornado_async_web.py +117 -0
  50. pythonagent/agent/probes/frameworks/tornado_web.py +133 -0
  51. pythonagent/agent/probes/frameworks/wsgi.py +353 -0
  52. pythonagent/agent/probes/grpc/__init__.py +76 -0
  53. pythonagent/agent/probes/grpc/client_interceptor.py +132 -0
  54. pythonagent/agent/probes/grpc/server_interceptor.py +129 -0
  55. pythonagent/agent/probes/havoc/__init__.py +0 -0
  56. pythonagent/agent/probes/havoc/custom_memory_stress.py +186 -0
  57. pythonagent/agent/probes/havoc/custom_thread_stress.py +187 -0
  58. pythonagent/agent/probes/havoc/havoc_constants.py +218 -0
  59. pythonagent/agent/probes/havoc/havoc_manager.py +981 -0
  60. pythonagent/agent/probes/http/__init__.py +49 -0
  61. pythonagent/agent/probes/http/aiohttp_client.py +59 -0
  62. pythonagent/agent/probes/http/boto.py +12 -0
  63. pythonagent/agent/probes/http/httplib.py +110 -0
  64. pythonagent/agent/probes/http/httpx_client.py +116 -0
  65. pythonagent/agent/probes/http/requests.py +15 -0
  66. pythonagent/agent/probes/http/tornado_httpclient.py +85 -0
  67. pythonagent/agent/probes/http/urllib3.py +16 -0
  68. pythonagent/agent/probes/langchain/__init__.py +21 -0
  69. pythonagent/agent/probes/langchain/base_tool.py +95 -0
  70. pythonagent/agent/probes/langchain/langchain_community.py +136 -0
  71. pythonagent/agent/probes/langchain/langchain_core.py +32 -0
  72. pythonagent/agent/probes/langchain/langchain_openai.py +110 -0
  73. pythonagent/agent/probes/logging/__init__.py +106 -0
  74. pythonagent/agent/probes/message_brokers/__init__.py +4 -0
  75. pythonagent/agent/probes/message_brokers/pika.py +126 -0
  76. pythonagent/agent/probes/mongodb/__init__.py +6 -0
  77. pythonagent/agent/probes/mongodb/pymongo.py +286 -0
  78. pythonagent/agent/probes/openai/__init__.py +3 -0
  79. pythonagent/agent/probes/openai/openai.py +797 -0
  80. pythonagent/agent/probes/span.py +101 -0
  81. pythonagent/agent/probes/sql/__init__.py +13 -0
  82. pythonagent/agent/probes/sql/botocores3.py +51 -0
  83. pythonagent/agent/probes/sql/dbapi.py +285 -0
  84. pythonagent/agent/probes/sql/dynamodb.py +90 -0
  85. pythonagent/agent/probes/sql/mysql_connector.py +24 -0
  86. pythonagent/agent/probes/sql/mysql_connector_cext.py +24 -0
  87. pythonagent/agent/probes/sql/mysqldb.py +43 -0
  88. pythonagent/agent/probes/sql/psycopg2.py +174 -0
  89. pythonagent/agent/probes/sql/pymysql.py +25 -0
  90. pythonagent/bootstrap/__init__.py +0 -0
  91. pythonagent/bootstrap/cav_gunicorn.py +26 -0
  92. pythonagent/bootstrap/cavagent_lambda_wrapper.py +291 -0
  93. pythonagent/bootstrap/run.py +47 -0
  94. pythonagent/bootstrap/sitecustomize.py +287 -0
  95. pythonagent/cavisson/netdiagnostics/CavAgent/instrumentationprofile.json +26 -0
  96. pythonagent/cavisson/netdiagnostics/CavAgent/interceptor_points.txt +29 -0
  97. pythonagent/cavisson/netdiagnostics/python/CavAgent/instrumentationprofile.json +42 -0
  98. pythonagent/cavisson/netdiagnostics/python/CavAgent/interceptor_points.txt +29 -0
  99. pythonagent/cavisson/netdiagnostics/python/config/ndsettings.conf +6 -0
  100. pythonagent/config.py +279 -0
  101. pythonagent/find.py +72 -0
  102. pythonagent/find_mod_cls_name.py +54 -0
  103. pythonagent/lang.py +131 -0
  104. pythonagent/lib.py +91 -0
  105. pythonagent/main/__init__.py +0 -0
  106. pythonagent/main/pytrace/__init__.py +79 -0
  107. pythonagent/main/pytrace/commands/__init__.py +0 -0
  108. pythonagent/main/pytrace/commands/auto_discovery.py +25 -0
  109. pythonagent/main/pytrace/commands/run.py +401 -0
  110. pythonagent/main/pytrace/pytrace.py +133 -0
  111. pythonagent/main/wsgi.py +6 -0
  112. pythonagent/main.py +27 -0
  113. pythonagent/run.py +46 -0
  114. pythonagent/sqins.py +8 -0
  115. pythonagent/test.py +73 -0
  116. pythonagent/utils.py +168 -0
  117. pythonagent/vendor/__init__.py +0 -0
  118. pythonagent/vendor/pympler/__init__.py +1 -0
  119. pythonagent/vendor/pympler/asizeof.py +2810 -0
  120. pythonagent/vendor/pympler/charts.py +62 -0
  121. pythonagent/vendor/pympler/classtracker.py +590 -0
  122. pythonagent/vendor/pympler/classtracker_stats.py +780 -0
  123. pythonagent/vendor/pympler/garbagegraph.py +80 -0
  124. pythonagent/vendor/pympler/mprofile.py +97 -0
  125. pythonagent/vendor/pympler/muppy.py +275 -0
  126. pythonagent/vendor/pympler/panels.py +115 -0
  127. pythonagent/vendor/pympler/process.py +238 -0
  128. pythonagent/vendor/pympler/py.typed +0 -0
  129. pythonagent/vendor/pympler/refbrowser.py +451 -0
  130. pythonagent/vendor/pympler/refgraph.py +350 -0
  131. pythonagent/vendor/pympler/summary.py +321 -0
  132. pythonagent/vendor/pympler/tracker.py +267 -0
  133. pythonagent/vendor/pympler/util/__init__.py +0 -0
  134. pythonagent/vendor/pympler/util/bottle.py +3809 -0
  135. pythonagent/vendor/pympler/util/compat.py +23 -0
  136. pythonagent/vendor/pympler/util/stringutils.py +77 -0
  137. pythonagent/vendor/pympler/web.py +346 -0
  138. pythonagent/vendor/werkzeug/__init__.py +20 -0
  139. pythonagent/vendor/werkzeug/_compat.py +228 -0
  140. pythonagent/vendor/werkzeug/_internal.py +473 -0
  141. pythonagent/vendor/werkzeug/_reloader.py +341 -0
  142. pythonagent/vendor/werkzeug/datastructures.py +3120 -0
  143. pythonagent/vendor/werkzeug/debug/__init__.py +498 -0
  144. pythonagent/vendor/werkzeug/debug/console.py +218 -0
  145. pythonagent/vendor/werkzeug/debug/repr.py +297 -0
  146. pythonagent/vendor/werkzeug/debug/tbtools.py +628 -0
  147. pythonagent/vendor/werkzeug/exceptions.py +829 -0
  148. pythonagent/vendor/werkzeug/filesystem.py +64 -0
  149. pythonagent/vendor/werkzeug/formparser.py +584 -0
  150. pythonagent/vendor/werkzeug/http.py +1307 -0
  151. pythonagent/vendor/werkzeug/local.py +420 -0
  152. pythonagent/vendor/werkzeug/middleware/__init__.py +25 -0
  153. pythonagent/vendor/werkzeug/middleware/dispatcher.py +66 -0
  154. pythonagent/vendor/werkzeug/middleware/http_proxy.py +219 -0
  155. pythonagent/vendor/werkzeug/middleware/lint.py +408 -0
  156. pythonagent/vendor/werkzeug/middleware/profiler.py +132 -0
  157. pythonagent/vendor/werkzeug/middleware/proxy_fix.py +169 -0
  158. pythonagent/vendor/werkzeug/middleware/shared_data.py +293 -0
  159. pythonagent/vendor/werkzeug/posixemulation.py +117 -0
  160. pythonagent/vendor/werkzeug/routing.py +2210 -0
  161. pythonagent/vendor/werkzeug/security.py +249 -0
  162. pythonagent/vendor/werkzeug/serving.py +1117 -0
  163. pythonagent/vendor/werkzeug/test.py +1123 -0
  164. pythonagent/vendor/werkzeug/testapp.py +241 -0
  165. pythonagent/vendor/werkzeug/urls.py +1138 -0
  166. pythonagent/vendor/werkzeug/useragents.py +202 -0
  167. pythonagent/vendor/werkzeug/utils.py +778 -0
  168. pythonagent/vendor/werkzeug/wrappers/__init__.py +36 -0
  169. pythonagent/vendor/werkzeug/wrappers/accept.py +50 -0
  170. pythonagent/vendor/werkzeug/wrappers/auth.py +33 -0
  171. pythonagent/vendor/werkzeug/wrappers/base_request.py +673 -0
  172. pythonagent/vendor/werkzeug/wrappers/base_response.py +700 -0
  173. pythonagent/vendor/werkzeug/wrappers/common_descriptors.py +341 -0
  174. pythonagent/vendor/werkzeug/wrappers/cors.py +100 -0
  175. pythonagent/vendor/werkzeug/wrappers/etag.py +304 -0
  176. pythonagent/vendor/werkzeug/wrappers/json.py +145 -0
  177. pythonagent/vendor/werkzeug/wrappers/request.py +49 -0
  178. pythonagent/vendor/werkzeug/wrappers/response.py +84 -0
  179. pythonagent/vendor/werkzeug/wrappers/user_agent.py +14 -0
  180. pythonagent/vendor/werkzeug/wsgi.py +1000 -0
@@ -0,0 +1,401 @@
1
+ import errno
2
+ import os
3
+ import sys
4
+ #from agent.internal.proxy import Proxy
5
+ from pythonagent.main.pytrace import CommandInvocationError, CommandExecutionError
6
+
7
+ USAGE = "run <command> [args...]"
8
+
9
+ ABOUT = """Run a program with the agent enabled.
10
+
11
+ Use this command to instrument a Python application. If <command> is not the
12
+ path to an executable, the command is looked for in your PATH. The command may
13
+ be a Python interpreter or a supported server that embeds Python (like uwsgi
14
+ and gunicorn).
15
+
16
+ For example, if you normally run your application as below commands:
17
+
18
+ 1) python manage.py runserver --norelaod 10:20.0.117:6062
19
+ 2) gunicorn -w 4 -b unix:acme.sock acme.app:app
20
+
21
+ You can run the same application instrumented by pythonagent with below commands:
22
+
23
+ 1) cavagent run python manage.py runserver --norelaod 10:20.0.117:6062
24
+ 2) cavagent run -- gunicorn -w 4 -b unix:acme.sock acme.app:app
25
+
26
+
27
+ The agent requires the TestRun to be running. If it
28
+ is not running, your application will not be start.
29
+
30
+ """
31
+
32
+ OPTION = {
33
+ 'cli': 'run in CLI mode',
34
+
35
+ # 'no-watchdog': 'disable the watchdog when auto-starting proxy',
36
+
37
+ 'config-file': {
38
+ 'short': 'c',
39
+ 'help': 'the config file to use',
40
+ 'value': True,
41
+ 'value_help': '<file>',
42
+ },
43
+
44
+ 'app': {
45
+ 'short': 'a',
46
+ 'help': 'the name of the app',
47
+ 'value': True,
48
+ 'value_help': '<app>',
49
+ },
50
+ 'tier': {
51
+ 'short': 't',
52
+ 'help': 'the name of the tier',
53
+ 'value': True,
54
+ 'value_help': '<tier>',
55
+ },
56
+ # 'node': {
57
+ # 'short': 'n',
58
+ # 'help': 'the name of the node',
59
+ # 'value': True,
60
+ # 'value_help': '<node>',
61
+ # },
62
+
63
+ # 'controller': {
64
+ # 'short': 'h',
65
+ # 'help': 'the host (and optionally port) of the controller',
66
+ # 'value': True,
67
+ # 'value_help': '<host>[:<port>]',
68
+ # },
69
+
70
+ # 'ssl': {
71
+ # 'help': 'pass to use SSL with the controller',
72
+ # },
73
+ #
74
+ # 'no-ssl': {
75
+ # 'help': 'pass to disable SSL with the controller (the default)',
76
+ # },
77
+
78
+ 'proxyMode': {
79
+ 'short': 'pmode',
80
+ 'help': 'proxyMode',
81
+ 'value': True,
82
+ 'value_help': '<proxyMode> value - [0/1]',
83
+ },
84
+
85
+ 'proxyConType': {
86
+ 'short': 'pctype',
87
+ 'help': 'please enter proxy con type ',
88
+ 'value': True,
89
+ 'value_help': '<proxyConType> value - [0/1]',
90
+ },
91
+
92
+ 'proxyIP': {
93
+ 'short': 'pip',
94
+ 'help': 'please enter proxy IP host address',
95
+ 'value': True,
96
+ 'value_help': '<proxyConType>',
97
+ },
98
+
99
+ 'proxyPort': {
100
+ 'short': 'pport',
101
+ 'help': 'please enter proxy port number ',
102
+ 'value': True,
103
+ 'value_help': '<proxyPort>',
104
+ },
105
+
106
+ # Internal / undocumented options
107
+
108
+ # 'run-proxy-script': {
109
+ # 'help': False, # "Path to runProxy script"
110
+ # 'value': True,
111
+ # },
112
+ #
113
+ # 'proxy-args': {
114
+ # 'help': False, # "Command line arguments to pass to runProxy"
115
+ # 'value': True,
116
+ # },
117
+
118
+ }
119
+
120
+
121
+ # ---------------------------------------------------------------------------
122
+ # uWSGI argument / config-file rewriting helpers (Approaches 1-6)
123
+ # ---------------------------------------------------------------------------
124
+
125
+ def _get_agent_wsgi_path():
126
+ """Return the absolute filesystem path to pythonagent/main/wsgi.py."""
127
+ import pythonagent.main.wsgi as _m
128
+ return os.path.abspath(_m.__file__.replace('.pyc', '.py'))
129
+
130
+
131
+ def _parse_uwsgi_ini(path):
132
+ """Parse a uWSGI INI config file and return the [uwsgi] section as a dict."""
133
+ import configparser
134
+ parser = configparser.RawConfigParser()
135
+ parser.read(path)
136
+ section = 'uwsgi'
137
+ if not parser.has_section(section):
138
+ return {}
139
+ return dict(parser.items(section))
140
+
141
+
142
+ def _parse_uwsgi_xml(path):
143
+ """Parse a uWSGI XML config file and return top-level tags as a dict."""
144
+ import xml.etree.ElementTree as ET
145
+ try:
146
+ root = ET.parse(path).getroot()
147
+ return {child.tag: (child.text or '') for child in root}
148
+ except Exception:
149
+ return {}
150
+
151
+
152
+ def _parse_uwsgi_yaml(path):
153
+ """Parse a uWSGI YAML config file and return the 'uwsgi' key as a dict.
154
+ Returns an empty dict silently when PyYAML is not installed."""
155
+ try:
156
+ import yaml
157
+ with open(path) as f:
158
+ data = yaml.safe_load(f)
159
+ return data.get('uwsgi', {}) if isinstance(data, dict) else {}
160
+ except ImportError:
161
+ return {}
162
+ except Exception:
163
+ return {}
164
+
165
+
166
+ def _parse_uwsgi_json(path):
167
+ """Parse a uWSGI JSON config file and return the 'uwsgi' key as a dict."""
168
+ import json
169
+ try:
170
+ with open(path) as f:
171
+ data = json.load(f)
172
+ return data.get('uwsgi', {}) if isinstance(data, dict) else {}
173
+ except Exception:
174
+ return {}
175
+
176
+
177
+ def _apply_uwsgi_config(cfg, args, environ):
178
+ """Given a dict parsed from a uWSGI config file, extract the WSGI app
179
+ location and inject it into environ as CAV_* vars. Appends a
180
+ --wsgi-file override pointing at the agent entry point so uWSGI loads
181
+ the agent wrapper instead of the user app directly."""
182
+ agent_wsgi = _get_agent_wsgi_path()
183
+ if 'module' in cfg and 'CAV_WSGI_MODULE' not in environ:
184
+ environ['CAV_WSGI_MODULE'] = cfg['module']
185
+ args += ['--wsgi-file', agent_wsgi]
186
+ elif 'wsgi-file' in cfg and 'CAV_WSGI_SCRIPT_ALIAS' not in environ:
187
+ environ['CAV_WSGI_SCRIPT_ALIAS'] = cfg['wsgi-file']
188
+ args += ['--wsgi-file', agent_wsgi]
189
+ if 'callable' in cfg and 'CAV_WSGI_CALLABLE_OBJECT' not in environ:
190
+ environ['CAV_WSGI_CALLABLE_OBJECT'] = cfg['callable']
191
+
192
+
193
+ def _rewrite_uwsgi_args(args, environ):
194
+ """Scan uWSGI command-line arguments and rewrite them so that:
195
+
196
+ * --wsgi-file → value saved to CAV_WSGI_SCRIPT_ALIAS; replaced with the
197
+ agent's pythonagent/main/wsgi.py entry point.
198
+ * --module/-w → value saved to CAV_WSGI_MODULE; arg replaced with an
199
+ equivalent --wsgi-file pointing at the agent entry point.
200
+ * --callable → value saved to CAV_WSGI_CALLABLE_OBJECT (kept in args).
201
+ * --ini/--xml/--yaml/--json → config file parsed; WSGI keys extracted and
202
+ --wsgi-file override appended (Approaches 3-6).
203
+
204
+ All other uWSGI arguments (--processes, --socket, --master …) are left
205
+ untouched so uWSGI continues to function normally.
206
+
207
+ Returns (rewritten_args, updated_environ).
208
+ """
209
+ if not args or os.path.basename(args[0]) not in ('uwsgi', 'uwsgi3'):
210
+ return args, environ
211
+
212
+ args = list(args)
213
+ environ = dict(environ) # work on a copy; caller replaces os.environ at the end
214
+ agent_wsgi = _get_agent_wsgi_path()
215
+ i = 1 # args[0] is the uwsgi binary itself
216
+
217
+ while i < len(args):
218
+ arg = args[i]
219
+
220
+ # ---- Approach 1: --wsgi-file ----------------------------------------
221
+ if arg in ('--wsgi-file', '--wsgi') and i + 1 < len(args):
222
+ environ.setdefault('CAV_WSGI_SCRIPT_ALIAS', args[i + 1])
223
+ args[i + 1] = agent_wsgi
224
+ i += 2
225
+
226
+ elif arg.startswith('--wsgi-file=') or arg.startswith('--wsgi='):
227
+ key, val = arg.split('=', 1)
228
+ environ.setdefault('CAV_WSGI_SCRIPT_ALIAS', val)
229
+ args[i] = key + '=' + agent_wsgi
230
+ i += 1
231
+
232
+ # ---- Approach 1: --callable -----------------------------------------
233
+ elif arg == '--callable' and i + 1 < len(args):
234
+ environ.setdefault('CAV_WSGI_CALLABLE_OBJECT', args[i + 1])
235
+ i += 2
236
+
237
+ elif arg.startswith('--callable='):
238
+ environ.setdefault('CAV_WSGI_CALLABLE_OBJECT', arg.split('=', 1)[1])
239
+ i += 1
240
+
241
+ # ---- Approach 2: --module / -w --------------------------------------
242
+ elif arg in ('--module', '-w') and i + 1 < len(args):
243
+ environ.setdefault('CAV_WSGI_MODULE', args[i + 1])
244
+ args[i] = '--wsgi-file'
245
+ args[i + 1] = agent_wsgi
246
+ i += 2
247
+
248
+ elif arg.startswith('--module='):
249
+ environ.setdefault('CAV_WSGI_MODULE', arg.split('=', 1)[1])
250
+ args[i] = '--wsgi-file=' + agent_wsgi
251
+ i += 1
252
+
253
+ # ---- Approach 3: --ini ----------------------------------------------
254
+ elif arg == '--ini' and i + 1 < len(args):
255
+ _apply_uwsgi_config(_parse_uwsgi_ini(args[i + 1]), args, environ)
256
+ i += 2
257
+
258
+ elif arg.startswith('--ini='):
259
+ _apply_uwsgi_config(_parse_uwsgi_ini(arg.split('=', 1)[1]), args, environ)
260
+ i += 1
261
+
262
+ # ---- Approach 4: --xml ----------------------------------------------
263
+ elif arg == '--xml' and i + 1 < len(args):
264
+ _apply_uwsgi_config(_parse_uwsgi_xml(args[i + 1]), args, environ)
265
+ i += 2
266
+
267
+ elif arg.startswith('--xml='):
268
+ _apply_uwsgi_config(_parse_uwsgi_xml(arg.split('=', 1)[1]), args, environ)
269
+ i += 1
270
+
271
+ # ---- Approach 5: --yaml ---------------------------------------------
272
+ elif arg == '--yaml' and i + 1 < len(args):
273
+ _apply_uwsgi_config(_parse_uwsgi_yaml(args[i + 1]), args, environ)
274
+ i += 2
275
+
276
+ elif arg.startswith('--yaml='):
277
+ _apply_uwsgi_config(_parse_uwsgi_yaml(arg.split('=', 1)[1]), args, environ)
278
+ i += 1
279
+
280
+ # ---- Approach 6: --json ---------------------------------------------
281
+ elif arg == '--json' and i + 1 < len(args):
282
+ _apply_uwsgi_config(_parse_uwsgi_json(args[i + 1]), args, environ)
283
+ i += 2
284
+
285
+ elif arg.startswith('--json='):
286
+ _apply_uwsgi_config(_parse_uwsgi_json(arg.split('=', 1)[1]), args, environ)
287
+ i += 1
288
+
289
+ else:
290
+ i += 1
291
+
292
+ return args, environ
293
+
294
+
295
+ # ---------------------------------------------------------------------------
296
+
297
+ def command(options, args):
298
+
299
+ '''
300
+ processname = 'TestRun'
301
+ tmp = os.popen("nsu_show_netstorm").read()
302
+ proccount = tmp.count(processname)
303
+
304
+ if proccount > 0:
305
+ print("TestRun is running...")
306
+ else:
307
+ print("ERROR!! TestRun is not running on this machine !!!\nKindly start the TestRun and try again...")
308
+ sys.exit(1)
309
+ '''
310
+ import bootstrap
311
+ pythonpath = [os.path.dirname(bootstrap.__file__), '.']
312
+
313
+ if not args:
314
+ raise CommandInvocationError('missing command: run <options> -- <command> [args...]')
315
+
316
+ environ = os.environ
317
+
318
+ if 'PYTHONPATH' in environ:
319
+ pythonpath.append(environ['PYTHONPATH'])
320
+
321
+ environ['PYTHONPATH'] = ':'.join(pythonpath)
322
+ #environ['CAV_APP_AGENT_ENV']= "NATIVE"
323
+ #environ['LD_LIBRARY_PATH'] = "/usr/local/lib"
324
+ environ['LD_PRELOAD'] = "libcavapr-1.so.0 libwebsockets.so"
325
+ #print('NDHOME set as ',environ.get('NDHOME'))
326
+ print("NDHOME Environment variable :", environ.get('NDHOME'))
327
+ if environ.get('NDHOME') is None:
328
+ #environ['NDHOME'] = "/opt/cavisson/netdiagnostics"
329
+ environ['NDHOME'] = "/opt/cavisson/netdiagnostics"
330
+ print("Taking Default NDHOME path",environ.get('NDHOME'))
331
+ environ['CAV_RUNNING_MODE'] = '0'
332
+
333
+ if 'config-file' in options:
334
+ environ['CAV_CONFIG_FILE'] = options['config-file']
335
+ if 'app' in options:
336
+ environ['CAV_APP_NAME'] = options['app']
337
+ if 'tier' in options:
338
+ environ['CAV_TIER_NAME'] = options['tier']
339
+ if 'node' in options:
340
+ environ['CAV_NODE_NAME'] = options['node']
341
+ if 'proxyMode' in options:
342
+ environ['CAV_APP_AGENT_PROXYMODE'] = options['proxyMode']
343
+ if logger.isEnabledFor(logging.INFO):
344
+ logger.info("Using proxy mode from env %s=%s", 'CAV_APP_AGENT_PROXYMODE', environ['CAV_APP_AGENT_PROXYMODE'])
345
+ if 'proxyConType' in options:
346
+ environ['CAV_proxyConType'] = options['proxyConType']
347
+ if 'proxyIP' in options:
348
+ environ['CAV_APP_AGENT_PROXYIP'] = options['proxyIP']
349
+ if logger.isEnabledFor(logging.INFO):
350
+ logger.info("Using proxy IP from env %s=%s", 'CAV_APP_AGENT_PROXYIP', environ['CAV_APP_AGENT_PROXYIP'])
351
+ if 'proxyPort' in options:
352
+ environ['CAV_APP_AGENT_PROXYPORT'] = options['proxyPort']
353
+ if logger.isEnabledFor(logging.INFO):
354
+ logger.info("Using proxy port from env %s=%s", 'CAV_APP_AGENT_PROXYPORT', environ['CAV_APP_AGENT_PROXYPORT'])
355
+ environ['nd_init_done'] = '0'
356
+
357
+ # if 'ssl' in options:
358
+ # environ['APPD_SSL_ENABLED'] = 'on'
359
+ # elif 'no-ssl' in options:
360
+ # environ['APPD_SSL_ENABLED'] = 'off'
361
+
362
+ # if 'controller' in options:
363
+ # value = options['controller']
364
+ #
365
+ # if ':' in value:
366
+ # host, port = value.split(':', 1)
367
+ # environ['APPD_CONTROLLER_HOST'] = host
368
+ # environ['APPD_CONTROLLER_PORT'] = port
369
+ # else:
370
+ # environ['APPD_CONTROLLER_HOST'] = value
371
+
372
+ # if 'use-manual-proxy' not in options:
373
+ # proxy_args = []
374
+ #
375
+ # if 'no-watchdog' in options:
376
+ # proxy_args.append('--no-watchdog')
377
+ #
378
+ # if 'run-proxy-script' in options:
379
+ # proxy_args.append('--run-proxy-script')
380
+ # proxy_args.append(options['run-proxy-script'])
381
+ #
382
+ # if 'proxy-args' in options:
383
+ # proxy_args.extend(shlex.split(options['proxy-args']))
384
+
385
+ # proxy.start(proxy_args)
386
+
387
+ try:
388
+ # Approaches 1-6: rewrite uWSGI args so the agent's wsgi.py becomes the
389
+ # entry point and the real app location is saved to CAV_WSGI_* env vars.
390
+ args, environ = _rewrite_uwsgi_args(args, environ)
391
+
392
+ os.execvpe(args[0], args, environ)
393
+
394
+
395
+ except OSError as exc:
396
+ if exc.errno == errno.ENOENT:
397
+ raise CommandExecutionError('%s: no such file or directory' % args[0])
398
+ elif exc.errno == errno.EPERM:
399
+ raise CommandExecutionError('%s: permission denied' % args[0])
400
+ raise
401
+
@@ -0,0 +1,133 @@
1
+ # Copyright (c) cavisson, Inc., and its affiliates
2
+ # 2015
3
+ # All Rights Reserved
4
+
5
+ import os
6
+ import sys
7
+
8
+ import sys,os
9
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname( __file__ ))))
10
+
11
+
12
+ from lang import keys
13
+ from pythonagent.main.pytrace import CommandInvocationError, CommandExecutionError, parse_options, HELP_OPTIONS
14
+ from pythonagent.main.pytrace.commands import run,auto_discovery
15
+
16
+ pytrace = os.path.basename(sys.argv[0])
17
+
18
+
19
+ COMMANDS = {
20
+ 'run': run,
21
+ 'auto_discovery': auto_discovery,
22
+ }
23
+ COMMANDS_ORDER = ["run"]
24
+
25
+ HELP_TEMPLATE = """\
26
+ USAGE
27
+ {pytrace} {usage}
28
+
29
+ ABOUT
30
+ {about}"""
31
+
32
+ USAGE = """\
33
+ USAGE
34
+ {pytrace} <command> <args...>
35
+
36
+ ABOUT
37
+ Cavisson Python Agent management utility
38
+
39
+ COMMANDS
40
+ help Print this message
41
+ help <command> Show detailed help for the given pytrace command
42
+ """
43
+
44
+
45
+ def main():
46
+ if len(sys.argv) < 2:
47
+ print_usage()
48
+
49
+
50
+ command = sys.argv[1]
51
+ args = sys.argv[2:]
52
+
53
+ if command in HELP_OPTIONS or command == 'help':
54
+ if args:
55
+ print_usage(command=args[0])
56
+ else:
57
+ print_usage()
58
+
59
+ if command not in COMMANDS:
60
+ print_usage(error="%s: unrecognized command" % command)
61
+
62
+ mod = COMMANDS[command]
63
+
64
+ try:
65
+ options, args = parse_options(getattr(mod, 'OPTIONS', {}), args)
66
+
67
+ if 'help' in options:
68
+ print_usage(command=command)
69
+
70
+ mod.command(options, args)
71
+
72
+ except CommandInvocationError as exc:
73
+ print_usage(command=command, error=str(exc))
74
+ #print("wrong usage!")
75
+ except CommandExecutionError as exc:
76
+ print(str(exc))
77
+
78
+
79
+ def indent(text, spaces=4):
80
+ indentation = ' ' * spaces
81
+ indented_text = ('\n%s' % indentation).join(text.split('\n'))
82
+ return indented_text
83
+
84
+ def print_usage(command=None, error=None):
85
+ if command and command not in COMMANDS:
86
+ error = '%s: unrecognized command' % command
87
+ command = None
88
+
89
+ if command:
90
+ mod = COMMANDS[command]
91
+ about = indent(mod.ABOUT.format(pytrace=pytrace))
92
+
93
+ print(HELP_TEMPLATE.format(pytrace=pytrace, usage=mod.USAGE, about=about))
94
+
95
+ if getattr(mod, 'OPTIONS', None):
96
+ print('OPTIONS')
97
+ for opt in sorted(keys(mod.OPTIONS)):
98
+ opt_descr = mod.OPTIONS[opt]
99
+ if isinstance(opt_descr, dict):
100
+ if 'short' in opt_descr:
101
+ opt = '%s / -%s' % (opt, opt_descr['short'])
102
+ if opt_descr.get('value', False):
103
+ opt += ' %s' % (opt_descr.get('value_help', ' <value>'))
104
+
105
+ opt_help = opt_descr.get('help', False)
106
+
107
+ if opt_help is False:
108
+ continue
109
+
110
+ if opt_descr.get('required', False):
111
+ opt_help = 'REQUIRED: %s' % opt_help
112
+ else:
113
+ opt_help = opt_descr
114
+
115
+ print(' --%-28s %s' % (opt, opt_help))
116
+ else:
117
+ print(USAGE.format(pytrace=pytrace))
118
+
119
+ for cmd in COMMANDS_ORDER:
120
+ mod = COMMANDS[cmd]
121
+ first_line = mod.ABOUT.splitlines()[0]
122
+ print(" %-18s %s" % (cmd, first_line))
123
+
124
+ if error:
125
+ prefix = "{pytrace} {command}".format(pytrace=pytrace, command=command) if command else pytrace
126
+ print('')
127
+ print("ERROR: {prefix}: {error}".format(prefix=prefix, error=error))
128
+
129
+ sys.exit(1 if error else 0)
130
+
131
+
132
+ if __name__ == '__main__':
133
+ main()
@@ -0,0 +1,6 @@
1
+ from __future__ import unicode_literals
2
+
3
+ from pythonagent.agent.probes.frameworks.wsgi import WSGIMiddleware
4
+ #from pythonagent import config
5
+ #config.WSGI_SCRIPT_ALIAS = input("Enter the absolute path of WSGI application script. (command to get 'readlink -f <script_path.py>') : ")
6
+ application = WSGIMiddleware()
pythonagent/main.py ADDED
@@ -0,0 +1,27 @@
1
+ """"
2
+ Local Testing for Python Agent on AWS Lambda
3
+ """
4
+
5
+ import sys
6
+ import os
7
+
8
+ python_agent_parent_dir = os.path.abspath(os.path.join(__file__, "../.."))
9
+ sys.path.append(python_agent_parent_dir)
10
+
11
+ from pythonagent.bootstrap.cavagent_lambda_wrapper import handler
12
+
13
+
14
+ if __name__ == "__main__":
15
+
16
+ event = {"path": "test_local_application"}
17
+
18
+ class Context:
19
+ def __init__(self):
20
+ self.log_stream_name = "test_request_id_localapp"
21
+ self.aws_request_id = "test_request_id_localapp"
22
+ self.function_name = "test_function_localapp"
23
+
24
+ context = Context()
25
+
26
+ response = handler(event, context)
27
+
pythonagent/run.py ADDED
@@ -0,0 +1,46 @@
1
+ import requests
2
+ import boto3
3
+ from flask import Flask
4
+
5
+
6
+ def http_callout():
7
+ print("Client Lambda - HTTP Callout Begin")
8
+ x = requests.get('https://www.facebook.com/')
9
+ # x = requests.put('https://httpbin.org/put', data={'key': 'value'})
10
+ # x = requests.post('https://www.w3schools.com/python/demopage.php', data={'key': 'value'})
11
+ # x = requests.delete('https://httpbin.org/delete', data={'key': 'value'})
12
+ print("Client Lambda - HTTP Callout End")
13
+
14
+
15
+ def first():
16
+ print("Client Lambda - First Function")
17
+
18
+
19
+ def second():
20
+ print("Client Lambda - Second Function")
21
+
22
+
23
+ def db_callout():
24
+ print("Client Lambda - DB Callout Begin")
25
+ client = boto3.client('dynamodb')
26
+ print("client METHODS FOR THIS SESSION::", dir(client))
27
+ data = client.scan(TableName='Person')
28
+ item = {
29
+ "id": {"N": "556"},
30
+ "address": {"S": "United States"},
31
+ "firstName": {"S": "John"},
32
+ "lastName": {"S": "Doe"},
33
+ "age": {"N": "30"}
34
+ }
35
+ response = client.put_item(TableName='Person', Item=item)
36
+ print("Client Lambda - DB Call out Begin")
37
+
38
+
39
+ def flask_wsgi():
40
+ app = Flask(__name__)
41
+
42
+ @app.route("/")
43
+ def hello_world():
44
+ return "<p>Hello, World!</p>"
45
+
46
+ app.run(port=6063)
pythonagent/sqins.py ADDED
@@ -0,0 +1,8 @@
1
+ import sqlite3
2
+ con = sqlite3.connect('checklist.db')
3
+ con.execute("CREATE TABLE checklist(id INTEGER PRIMARY KEY,task VARCHAR(100) NOT NULL,description VARCHAR(200) NOT NULL,status VARCHAR(3) NOT NULL)")
4
+ con.execute("INSERT INTO checklist(id,task,description,status) VALUES (1,'Task number 1', 'This is a description about Task number 1', 'Yes')")
5
+ con.execute("INSERT INTO checklist(id,task,description,status) VALUES (2,'Task number 2', 'This is a description about Task number 2', 'Yes')")
6
+ con.execute("INSERT INTO checklist(id,task,description,status) VALUES (3,'Task number 3', 'This is a description about Task number 3', 'Yes')")
7
+ con.commit()
8
+