whatap-python 2.1.0__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 (227) hide show
  1. whatap/LICENSE +0 -0
  2. whatap/README.rst +49 -0
  3. whatap/__init__.py +923 -0
  4. whatap/__main__.py +4 -0
  5. whatap/agent/darwin/amd64/whatap_python +0 -0
  6. whatap/agent/darwin/arm64/whatap_python +0 -0
  7. whatap/agent/linux/amd64/whatap_python +0 -0
  8. whatap/agent/linux/arm64/whatap_python +0 -0
  9. whatap/agent/windows/whatap_python.exe +0 -0
  10. whatap/bootstrap/__init__.py +0 -0
  11. whatap/bootstrap/sitecustomize.py +19 -0
  12. whatap/build.py +4 -0
  13. whatap/conf/__init__.py +0 -0
  14. whatap/conf/configuration.py +280 -0
  15. whatap/conf/configure.py +105 -0
  16. whatap/conf/license.py +49 -0
  17. whatap/control/__init__.py +0 -0
  18. whatap/counter/__init__.py +14 -0
  19. whatap/counter/counter_manager.py +45 -0
  20. whatap/counter/tasks/__init__.py +3 -0
  21. whatap/counter/tasks/base_task.py +26 -0
  22. whatap/counter/tasks/llm_evaluator_task.py +501 -0
  23. whatap/counter/tasks/llm_log_sink_task.py +309 -0
  24. whatap/counter/tasks/llm_stat_task.py +78 -0
  25. whatap/counter/tasks/openfiledescriptor.py +67 -0
  26. whatap/io/__init__.py +1 -0
  27. whatap/io/data_inputx.py +161 -0
  28. whatap/io/data_outputx.py +262 -0
  29. whatap/llm/__init__.py +17 -0
  30. whatap/llm/definitions.py +43 -0
  31. whatap/llm/evaluators/__init__.py +136 -0
  32. whatap/llm/evaluators/base.py +114 -0
  33. whatap/llm/evaluators/builtins/__init__.py +91 -0
  34. whatap/llm/evaluators/builtins/answer_relevance.py +46 -0
  35. whatap/llm/evaluators/builtins/combined_judge.py +271 -0
  36. whatap/llm/evaluators/builtins/factuality.py +71 -0
  37. whatap/llm/evaluators/builtins/hallucination.py +97 -0
  38. whatap/llm/evaluators/builtins/llm_judge.py +516 -0
  39. whatap/llm/evaluators/builtins/pii_leak.py +214 -0
  40. whatap/llm/evaluators/builtins/prompt_injection.py +71 -0
  41. whatap/llm/evaluators/builtins/toxicity.py +53 -0
  42. whatap/llm/evaluators/builtins/url_scan.py +194 -0
  43. whatap/llm/evaluators/registry.py +192 -0
  44. whatap/llm/evaluators/sampler.py +83 -0
  45. whatap/llm/evaluators/scope.py +334 -0
  46. whatap/llm/features.py +66 -0
  47. whatap/llm/log_sink_packs/__init__.py +9 -0
  48. whatap/llm/log_sink_packs/llm_input_message.py +16 -0
  49. whatap/llm/log_sink_packs/llm_log_sink_pack.py +72 -0
  50. whatap/llm/log_sink_packs/llm_output_message.py +19 -0
  51. whatap/llm/log_sink_packs/llm_step_eval_status.py +94 -0
  52. whatap/llm/log_sink_packs/llm_step_status.py +118 -0
  53. whatap/llm/log_sink_packs/llm_system_message.py +16 -0
  54. whatap/llm/log_sink_packs/llm_tool_calls.py +44 -0
  55. whatap/llm/log_sink_packs/llm_tool_results.py +16 -0
  56. whatap/llm/log_sink_packs/llm_tx_status.py +108 -0
  57. whatap/llm/pricing.py +236 -0
  58. whatap/llm/prompt_meta.py +288 -0
  59. whatap/llm/providers/__init__.py +0 -0
  60. whatap/llm/providers/anthropic/__init__.py +37 -0
  61. whatap/llm/providers/anthropic/messages/__init__.py +0 -0
  62. whatap/llm/providers/anthropic/messages/messages.py +70 -0
  63. whatap/llm/providers/anthropic/messages/messages_context.py +76 -0
  64. whatap/llm/providers/anthropic/messages/messages_extractor.py +126 -0
  65. whatap/llm/providers/interceptor.py +182 -0
  66. whatap/llm/providers/openai/__init__.py +133 -0
  67. whatap/llm/providers/openai/chat/__init__.py +0 -0
  68. whatap/llm/providers/openai/chat/chat.py +82 -0
  69. whatap/llm/providers/openai/chat/chat_context.py +78 -0
  70. whatap/llm/providers/openai/chat/chat_extractor.py +127 -0
  71. whatap/llm/providers/openai/completions/__init__.py +0 -0
  72. whatap/llm/providers/openai/completions/completions.py +70 -0
  73. whatap/llm/providers/openai/completions/completions_context.py +31 -0
  74. whatap/llm/providers/openai/completions/completions_extractor.py +61 -0
  75. whatap/llm/providers/openai/content_parser.py +41 -0
  76. whatap/llm/providers/openai/embeddings/__init__.py +0 -0
  77. whatap/llm/providers/openai/embeddings/embeddings.py +59 -0
  78. whatap/llm/providers/openai/embeddings/embeddings_context.py +25 -0
  79. whatap/llm/providers/openai/embeddings/embeddings_extractor.py +26 -0
  80. whatap/llm/providers/openai/responses/__init__.py +0 -0
  81. whatap/llm/providers/openai/responses/responses.py +70 -0
  82. whatap/llm/providers/openai/responses/responses_context.py +88 -0
  83. whatap/llm/providers/openai/responses/responses_extractor.py +126 -0
  84. whatap/llm/providers/stream_accumulator.py +73 -0
  85. whatap/llm/stats/__init__.py +35 -0
  86. whatap/llm/stats/active_stat.py +86 -0
  87. whatap/llm/stats/answer_relevance_eval_stat.py +10 -0
  88. whatap/llm/stats/api_status_stat.py +35 -0
  89. whatap/llm/stats/base_stat.py +107 -0
  90. whatap/llm/stats/combined_judge_eval_stat.py +11 -0
  91. whatap/llm/stats/error_stat.py +59 -0
  92. whatap/llm/stats/eval_stat.py +225 -0
  93. whatap/llm/stats/factuality_eval_stat.py +10 -0
  94. whatap/llm/stats/feature_stat.py +104 -0
  95. whatap/llm/stats/finish_stat.py +105 -0
  96. whatap/llm/stats/hallucination_eval_stat.py +10 -0
  97. whatap/llm/stats/meter.py +18 -0
  98. whatap/llm/stats/perf_stat.py +117 -0
  99. whatap/llm/stats/pii_leak_eval_stat.py +12 -0
  100. whatap/llm/stats/prompt_injection_eval_stat.py +10 -0
  101. whatap/llm/stats/token_usage_stat.py +133 -0
  102. whatap/llm/stats/toxicity_eval_stat.py +10 -0
  103. whatap/llm/stats/url_scan_eval_stat.py +12 -0
  104. whatap/net/__init__.py +0 -0
  105. whatap/net/async_sender.py +107 -0
  106. whatap/net/packet_enum.py +44 -0
  107. whatap/net/packet_type_enum.py +31 -0
  108. whatap/net/param_def.py +69 -0
  109. whatap/net/stackhelper.py +87 -0
  110. whatap/net/udp_session.py +394 -0
  111. whatap/net/udp_thread.py +54 -0
  112. whatap/pack/__init__.py +0 -0
  113. whatap/pack/logSinkPack.py +77 -0
  114. whatap/pack/pack.py +34 -0
  115. whatap/pack/pack_enum.py +41 -0
  116. whatap/pack/tagCountPack.py +61 -0
  117. whatap/scripts/__init__.py +208 -0
  118. whatap/trace/__init__.py +12 -0
  119. whatap/trace/mod/__init__.py +0 -0
  120. whatap/trace/mod/amqp/__init__.py +0 -0
  121. whatap/trace/mod/amqp/kombu.py +122 -0
  122. whatap/trace/mod/amqp/pika.py +62 -0
  123. whatap/trace/mod/application/__init__.py +0 -0
  124. whatap/trace/mod/application/bottle.py +34 -0
  125. whatap/trace/mod/application/celery.py +81 -0
  126. whatap/trace/mod/application/cherrypy.py +30 -0
  127. whatap/trace/mod/application/django.py +287 -0
  128. whatap/trace/mod/application/django_asgi.py +266 -0
  129. whatap/trace/mod/application/django_py3.py +251 -0
  130. whatap/trace/mod/application/fastapi/__init__.py +31 -0
  131. whatap/trace/mod/application/fastapi/endpoint.py +73 -0
  132. whatap/trace/mod/application/fastapi/exception_log.py +63 -0
  133. whatap/trace/mod/application/fastapi/instrumentation.py +204 -0
  134. whatap/trace/mod/application/fastapi/scope.py +115 -0
  135. whatap/trace/mod/application/fastapi/transaction.py +67 -0
  136. whatap/trace/mod/application/flask.py +52 -0
  137. whatap/trace/mod/application/frappe.py +224 -0
  138. whatap/trace/mod/application/graphql.py +170 -0
  139. whatap/trace/mod/application/nameko.py +39 -0
  140. whatap/trace/mod/application/odoo.py +63 -0
  141. whatap/trace/mod/application/starlette.py +126 -0
  142. whatap/trace/mod/application/tornado.py +163 -0
  143. whatap/trace/mod/application/wsgi.py +195 -0
  144. whatap/trace/mod/database/__init__.py +0 -0
  145. whatap/trace/mod/database/cxoracle.py +49 -0
  146. whatap/trace/mod/database/mongo.py +169 -0
  147. whatap/trace/mod/database/mysql.py +80 -0
  148. whatap/trace/mod/database/neo4j.py +90 -0
  149. whatap/trace/mod/database/psycopg2.py +45 -0
  150. whatap/trace/mod/database/psycopg3.py +359 -0
  151. whatap/trace/mod/database/redis.py +122 -0
  152. whatap/trace/mod/database/sqlalchemy.py +213 -0
  153. whatap/trace/mod/database/sqlite3.py +130 -0
  154. whatap/trace/mod/database/util.py +630 -0
  155. whatap/trace/mod/email/__init__.py +0 -0
  156. whatap/trace/mod/email/smtp.py +78 -0
  157. whatap/trace/mod/httpc/__init__.py +0 -0
  158. whatap/trace/mod/httpc/django.py +31 -0
  159. whatap/trace/mod/httpc/httplib.py +70 -0
  160. whatap/trace/mod/httpc/httpx.py +62 -0
  161. whatap/trace/mod/httpc/requests.py +20 -0
  162. whatap/trace/mod/httpc/urllib3.py +27 -0
  163. whatap/trace/mod/httpc/util.py +388 -0
  164. whatap/trace/mod/logging.py +161 -0
  165. whatap/trace/mod/plugin.py +84 -0
  166. whatap/trace/mod/standalone/__init__.py +0 -0
  167. whatap/trace/mod/standalone/multiple.py +293 -0
  168. whatap/trace/mod/standalone/single.py +135 -0
  169. whatap/trace/simple_trace_context.py +18 -0
  170. whatap/trace/trace_context.py +212 -0
  171. whatap/trace/trace_context_manager.py +244 -0
  172. whatap/trace/trace_error.py +84 -0
  173. whatap/trace/trace_handler.py +89 -0
  174. whatap/trace/trace_import.py +91 -0
  175. whatap/trace/trace_module_definition.py +156 -0
  176. whatap/util/__init__.py +0 -0
  177. whatap/util/bit_util.py +49 -0
  178. whatap/util/cardinality/__init__.py +0 -0
  179. whatap/util/cardinality/hyperloglog.py +84 -0
  180. whatap/util/cardinality/murmurhash.py +20 -0
  181. whatap/util/cardinality/registerset.py +60 -0
  182. whatap/util/compare_util.py +19 -0
  183. whatap/util/date_util.py +55 -0
  184. whatap/util/debug_util.py +73 -0
  185. whatap/util/escape_literal_sql.py +233 -0
  186. whatap/util/frame_util.py +20 -0
  187. whatap/util/hash_util.py +103 -0
  188. whatap/util/hexa32.py +66 -0
  189. whatap/util/int_set.py +199 -0
  190. whatap/util/ip_util.py +63 -0
  191. whatap/util/keygen.py +11 -0
  192. whatap/util/linked_list.py +113 -0
  193. whatap/util/linked_map.py +359 -0
  194. whatap/util/metering_util.py +103 -0
  195. whatap/util/request_double_queue.py +68 -0
  196. whatap/util/request_queue.py +60 -0
  197. whatap/util/string_util.py +20 -0
  198. whatap/util/throttle_util.py +99 -0
  199. whatap/util/userid_util.py +134 -0
  200. whatap/value/__init__.py +1 -0
  201. whatap/value/blob_value.py +38 -0
  202. whatap/value/boolean_value.py +33 -0
  203. whatap/value/decimal_value.py +36 -0
  204. whatap/value/double_summary.py +86 -0
  205. whatap/value/double_value.py +33 -0
  206. whatap/value/float_array.py +42 -0
  207. whatap/value/float_value.py +34 -0
  208. whatap/value/int_array.py +42 -0
  209. whatap/value/ip4_value.py +50 -0
  210. whatap/value/list_value.py +105 -0
  211. whatap/value/long_array.py +44 -0
  212. whatap/value/long_summary.py +83 -0
  213. whatap/value/map_value.py +154 -0
  214. whatap/value/null_value.py +21 -0
  215. whatap/value/number_value.py +33 -0
  216. whatap/value/summary_value.py +39 -0
  217. whatap/value/text_array.py +58 -0
  218. whatap/value/text_hash_value.py +37 -0
  219. whatap/value/text_value.py +43 -0
  220. whatap/value/value.py +26 -0
  221. whatap/value/value_enum.py +80 -0
  222. whatap/whatap.conf +14 -0
  223. whatap_python-2.1.0.dist-info/METADATA +87 -0
  224. whatap_python-2.1.0.dist-info/RECORD +227 -0
  225. whatap_python-2.1.0.dist-info/WHEEL +5 -0
  226. whatap_python-2.1.0.dist-info/entry_points.txt +6 -0
  227. whatap_python-2.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,63 @@
1
+ import traceback
2
+ from whatap import logging
3
+ from whatap.trace.trace_handler import trace_handler
4
+ from whatap.trace.trace_error import interceptor_error
5
+ from whatap.trace.mod.application.wsgi import interceptor
6
+ from whatap.trace.trace_context_manager import TraceContextManager
7
+
8
+
9
+ def instrument(module):
10
+ root = module.http.root
11
+ AppClass = root.__class__
12
+ original_call = AppClass.__call__
13
+
14
+ def wrapper(fn):
15
+ @trace_handler(fn, True)
16
+ def trace(self, environ, start_response):
17
+ def custom_start_response(status, headers, exc_info=None):
18
+ ctx = TraceContextManager.getLocalContext()
19
+ try:
20
+ ctx.status = int(status.split()[0])
21
+ except Exception as e:
22
+ logging.warning('[ODOO] status parse failed: %s' % e, extra={'id': 'ODOO001'})
23
+ ctx.status = 0
24
+ return start_response(status, headers, exc_info)
25
+ try:
26
+ callback = interceptor(fn, self, environ, custom_start_response)
27
+ except Exception as e:
28
+ interceptor_error(
29
+ 500 , #해당 status 값은 에러 처리용으로만 사용됩니다.
30
+ [e.__class__.__name__, str(e)]
31
+ )
32
+ raise
33
+ return callback
34
+
35
+ return trace
36
+
37
+ AppClass.__call__ = wrapper(original_call)
38
+
39
+
40
+ """
41
+ Odoo 16+ HttpDispatcher.handle_error 패치
42
+ """
43
+ Dispatcher = getattr(module.http, 'HttpDispatcher', None)
44
+
45
+ if Dispatcher:
46
+ original_handle_error = Dispatcher.handle_error
47
+
48
+ def wrapper(fn):
49
+ @trace_handler(fn)
50
+ def trace(self,exception):
51
+ ctx = TraceContextManager.getLocalContext()
52
+ interceptor_error(
53
+ 500, # 해당 status 값은 에러 처리용으로만 사용됩니다.
54
+ [exception.__class__.__name__,
55
+ str(exception)],
56
+ ctx=ctx
57
+ )
58
+
59
+ callback = fn(self, exception)
60
+ return callback
61
+
62
+ return trace
63
+ Dispatcher.handle_error = wrapper(Dispatcher.handle_error)
@@ -0,0 +1,126 @@
1
+ import whatap.net.async_sender as async_sender
2
+ from whatap.trace.trace_context import TraceContext
3
+ from whatap.trace.trace_context_manager import TraceContextManager
4
+ from whatap.net.packet_type_enum import PacketTypeEnum
5
+ from whatap.util.date_util import DateUtil
6
+ from whatap.util.userid_util import UseridUtil as userid_util
7
+ from whatap.trace.trace_error import interceptor_step_error
8
+ from whatap.trace.mod.application.wsgi import \
9
+ start_interceptor,end_interceptor
10
+ from whatap.conf.configure import Configure as conf
11
+ from typing import Any
12
+
13
+
14
+
15
+ def intercept_websocket(web_socket, data: str):
16
+ try:
17
+ ctx = TraceContext()
18
+
19
+ scope = web_socket.scope
20
+ headers = dict(scope.get("headers", [])) # headers는 리스트(tuple) 형태
21
+ query_string = scope.get("query_string", b'').decode()
22
+ client = scope.get("client", ("0.0.0.0", 0))
23
+
24
+ # 기본 ctx 설정
25
+ ctx.service_name = scope.get("path", "WebSocket")
26
+ if query_string:
27
+ ctx.service_name += f"?{query_string}"
28
+ ctx.http_method = "WEBSOCKET"
29
+ ctx.remoteIp = client[0]
30
+ ctx.port = client[1]
31
+
32
+ # User-Agent, Referer 추출 (바이트를 디코딩)
33
+ ctx.userAgentString = headers.get(b'user-agent', b'').decode()
34
+ ctx.referer = headers.get(b'referer', b'').decode()
35
+
36
+ # userid 관련
37
+ if conf.trace_user_enabled:
38
+ if conf.trace_user_using_ip:
39
+ ctx.userid = ctx.remoteIp
40
+ else:
41
+ ctx.userid, ctx._rawuserid = userid_util.getUserId([scope], ctx.remoteIp)
42
+
43
+ # 트랜잭션 전파 관련
44
+ mstt = headers.get(f"HTTP_{conf._trace_mtrace_caller_key}".encode(), b'').decode()
45
+ if mstt:
46
+ ctx.setTransfer(mstt)
47
+ if conf.stat_mtrace_enabled:
48
+ val = headers.get(f"HTTP_{conf._trace_mtrace_info_key}".encode(), b'').decode()
49
+ if val:
50
+ ctx.setTransferInfo(val)
51
+ txid = headers.get(f"HTTP_{conf._trace_mtrace_callee_key}".encode(), b'').decode()
52
+ if txid:
53
+ ctx.setTxid(txid)
54
+
55
+ poid = headers.get(f"HTTP_{conf._trace_mtrace_caller_poid_key}".encode(), b'').decode()
56
+ if poid:
57
+ ctx.mcaller_poid = poid
58
+
59
+ start_interceptor(ctx)
60
+
61
+ start_time = DateUtil.nowSystem()
62
+ ctx.start_time = start_time
63
+ ctx.error = 0
64
+ ctx.elapsed = 0
65
+
66
+ datas = [ctx.remoteIp, ctx.port, ctx.elapsed, ctx.error]
67
+ async_sender.send_packet(PacketTypeEnum.TX_WEB_SOCKET, ctx, datas)
68
+
69
+ except Exception as e:
70
+ interceptor_step_error(e)
71
+ finally:
72
+ end_interceptor(ctx=ctx)
73
+
74
+
75
+ def instrument_starlette_websocket(module):
76
+
77
+ if not conf.trace_websocket_enabled:
78
+ return
79
+
80
+ OriginalWebSocket = module.WebSocket
81
+ if getattr(OriginalWebSocket, "_whatap_patched", False):
82
+ return
83
+
84
+ #original_accept = OriginalWebSocket.accept
85
+ original_send_text = OriginalWebSocket.send_text
86
+ original_send_bytes = OriginalWebSocket.send_bytes
87
+ original_send_json = OriginalWebSocket.send_json
88
+
89
+
90
+ # # 연결 시점도 래핑은 하지만, APM 인터셉트는 하지 않음
91
+ # async def wrapped_accept(self, *args, **kwargs):
92
+ # try:
93
+ # pass
94
+ # except Exception as e:
95
+ # interceptor_step_error(e)
96
+ # return await original_accept(self, *args, **kwargs)
97
+
98
+ async def wrapped_send_text(self, data: str):
99
+ try:
100
+ intercept_websocket(self, data)
101
+ except Exception as e:
102
+ interceptor_step_error(e)
103
+ return await original_send_text(self, data)
104
+
105
+ async def wrapped_send_bytes(self, data: bytes):
106
+ try:
107
+ intercept_websocket(self, None)
108
+ except Exception as e:
109
+ interceptor_step_error(e)
110
+ return await original_send_bytes(self, data)
111
+
112
+ async def wrapped_send_json(self, data: Any):
113
+ try:
114
+ intercept_websocket(self, None)
115
+ except Exception as e:
116
+ interceptor_step_error(e)
117
+ return await original_send_json(self, data)
118
+
119
+ #OriginalWebSocket.accept = wrapped_accept
120
+ OriginalWebSocket.send_text = wrapped_send_text
121
+ OriginalWebSocket.send_bytes = wrapped_send_bytes
122
+ OriginalWebSocket.send_json = wrapped_send_json
123
+ OriginalWebSocket._whatap_patched = True
124
+
125
+
126
+
@@ -0,0 +1,163 @@
1
+ import inspect
2
+ import whatap.net.async_sender as async_sender
3
+ from whatap.net.packet_type_enum import PacketTypeEnum
4
+ from whatap.util.userid_util import UseridUtil as userid_util
5
+ from whatap.trace.trace_context import TraceContext
6
+ from whatap.trace.trace_context_manager import TraceContextManager
7
+ from whatap.util.date_util import DateUtil
8
+ from whatap.conf.configure import Configure as conf
9
+ from whatap.trace.trace_handler import trace_handler
10
+ from whatap.trace.trace_error import interceptor_error
11
+ from whatap.trace.mod.application.wsgi import \
12
+ start_interceptor, end_interceptor, isIgnore
13
+
14
+
15
+ def parseServiceName(environ):
16
+ return environ.get('PATH_INFO', '')
17
+
18
+
19
+ def instrument(module):
20
+ def wrapper(fn):
21
+ async def trace(*args, **kwargs):
22
+ request = args[0].request
23
+ environ = {
24
+ 'HTTP_HOST': request.host,
25
+ 'PATH_INFO': request.path,
26
+ 'QUERY_STRING': request.query_arguments,
27
+ 'REMOTE_ADDR': request.remote_ip,
28
+ 'HTTP_USER_AGENT': request.headers.get('User-Agent', ''),
29
+ 'HTTP_REFERER': request.headers.get('Referer', ''),
30
+ 'REQUEST_METHOD': request.method
31
+ }
32
+
33
+ for header_name, value in request.headers.items():
34
+ key = 'HTTP_' + header_name.upper().replace('-', '_')
35
+ environ[key] = value
36
+
37
+ async def run():
38
+ await interceptor((fn, environ), *args, **kwargs)
39
+
40
+ from tornado.ioloop import IOLoop
41
+ IOLoop.current().add_callback(run)
42
+
43
+ return None
44
+
45
+ return trace
46
+
47
+ module.RequestHandler._execute = wrapper(module.RequestHandler._execute)
48
+
49
+ def wrapper(fn):
50
+ @trace_handler(fn)
51
+ def trace(*args, **kwargs):
52
+ callback = fn(*args, **kwargs)
53
+
54
+ e = args[1]
55
+ status_code = args[0]._status_code
56
+ errors = [e.__class__.__name__, str(e)]
57
+ interceptor_error(status_code, errors)
58
+ return callback
59
+
60
+ return trace
61
+
62
+ module.RequestHandler._handle_request_exception = wrapper(
63
+ module.RequestHandler._handle_request_exception)
64
+
65
+
66
+ async def interceptor(rn_environ, *args, **kwargs):
67
+ if not isinstance(rn_environ, tuple):
68
+ rn_environ = (rn_environ, args[1])
69
+ fn, environ = rn_environ
70
+
71
+ ctx = TraceContext()
72
+ ctx.host = environ.get('HTTP_HOST', '').split(':')[0]
73
+ ctx.service_name = parseServiceName(environ)
74
+ ctx.http_method = environ.get('REQUEST_METHOD', '')
75
+ ctx.remoteIp = userid_util.getRemoteAddr(args)
76
+ ctx.userAgentString = environ.get('HTTP_USER_AGENT', '')
77
+ ctx.referer = environ.get('HTTP_REFERER', '')
78
+
79
+ if conf.trace_user_enabled:
80
+ if conf.trace_user_using_ip:
81
+ ctx.userid = userid_util.getRemoteAddr(args)
82
+ else:
83
+ ctx.userid, ctx._rawuserid = userid_util.getUserId(args, ctx.remoteIp)
84
+
85
+ mstt = environ.get('HTTP_{}'.format(
86
+ conf._trace_mtrace_caller_key.upper().replace('-', '_')), '')
87
+
88
+ if mstt:
89
+ ctx.setTransfer(mstt)
90
+ if conf.stat_mtrace_enabled:
91
+ val = environ.get('HTTP_{}'.format(
92
+ conf._trace_mtrace_info_key.upper().replace('-', '_')), '')
93
+ if val and len(val):
94
+ ctx.setTransferInfo(val)
95
+ pass
96
+
97
+ myid = environ.get('HTTP_{}'.format(
98
+ conf._trace_mtrace_callee_key.upper().replace('-', '_')), '')
99
+ if myid:
100
+ ctx.setTxid(myid)
101
+ caller_poid = environ.get('HTTP_{}'.format(
102
+ conf._trace_mtrace_caller_poid_key.upper().replace('-', '_')), '')
103
+
104
+ if caller_poid:
105
+ ctx.mcaller_poid = caller_poid
106
+
107
+ try:
108
+ if isIgnore(ctx.service_name):
109
+ ctx.is_ignored = True
110
+ TraceContextManager.end(ctx.id)
111
+ callback = fn(*args, **kwargs)
112
+ if inspect.isawaitable(callback):
113
+ return await callback
114
+ return callback
115
+ except Exception:
116
+ pass
117
+
118
+ start_interceptor(ctx)
119
+
120
+ try:
121
+ callback = fn(*args, **kwargs)
122
+ if inspect.isawaitable(callback):
123
+ callback = await callback
124
+
125
+ query_string = environ.get('QUERY_STRING', '')
126
+ if query_string:
127
+ ctx.service_name += '?{}'.format(query_string)
128
+
129
+ if ctx.service_name.find('.') > -1 and ctx.service_name.split('.')[
130
+ 1] in conf.web_static_content_extensions:
131
+ ctx.isStaticContents = 'true'
132
+
133
+ handler = args[0]
134
+ status_code = getattr(handler, '_status_code', 200)
135
+ if status_code >= 400:
136
+ errors = [
137
+ callback.__class__.__name__ if callback else 'Unknown',
138
+ getattr(callback, 'reason_phrase', '')
139
+ ]
140
+ interceptor_error(status_code, errors, ctx=ctx)
141
+
142
+ else:
143
+ ctx.status = status_code
144
+
145
+ if conf.profile_http_header_enabled:
146
+ keys = []
147
+ for key, value in environ.items():
148
+ if key.startswith('HTTP_'):
149
+ keys.append(key)
150
+ keys.sort()
151
+
152
+ text = ''
153
+ for key in keys:
154
+ text += '{}={}\n'.format(key.split('HTTP_')[1].lower(),
155
+ environ[key])
156
+
157
+ datas = ['HTTP-HEADERS', 'HTTP-HEADERS', text]
158
+ ctx.start_time = DateUtil.nowSystem()
159
+ async_sender.send_packet(PacketTypeEnum.TX_MSG, ctx, datas)
160
+
161
+ return callback
162
+ finally:
163
+ end_interceptor(ctx=ctx)
@@ -0,0 +1,195 @@
1
+ import sys
2
+ import traceback
3
+ import threading
4
+
5
+ from whatap.conf.configure import Configure as conf
6
+ from whatap.net.packet_type_enum import PacketTypeEnum
7
+ import whatap.net.async_sender as async_sender
8
+ from whatap.trace.trace_context import TraceContext
9
+ from whatap.trace.trace_context_manager import TraceContextManager
10
+ from whatap.util.date_util import DateUtil
11
+ from whatap.util.hash_util import HashUtil
12
+ from whatap.util.userid_util import UseridUtil as userid_util
13
+ from whatap import logging
14
+
15
+
16
+ def isEventlet():
17
+ greenlet = sys.modules.get('greenlet')
18
+
19
+ if greenlet:
20
+ current = greenlet.getcurrent()
21
+ if current is not None and current.parent:
22
+ print('thread:', threading.get_ident(), 'greenlet:', id(current.parent))
23
+ traceback.print_stack()
24
+ return True
25
+ else:
26
+ return False
27
+
28
+
29
+ from whatap.trace.trace_error import interceptor_error
30
+
31
+
32
+
33
+ def start_interceptor(ctx):
34
+ if conf.dev:
35
+ logging.debug('start transaction id(seq): {}'.format(ctx.id),
36
+ extra={'id': 'WA111'})
37
+ print('start transaction id(seq): {}'.format(ctx.id), dict(extra={'id': 'WA111'}))
38
+
39
+ start_time = DateUtil.nowSystem()
40
+ ctx.start_time = start_time
41
+
42
+ if ctx.service_name and not ctx.service_hash:
43
+ ctx.service_hash = HashUtil.hashFromString(ctx.service_name)
44
+
45
+ datas = [ctx.host,
46
+ ctx.service_name,
47
+ ctx.remoteIp,
48
+ ctx.userAgentString,
49
+ ctx.referer,
50
+ ctx.userid,
51
+ ctx.isStaticContents,
52
+ ctx.http_method
53
+ ]
54
+ # print("start_interceptor txid:", ctx.id)
55
+ async_sender.send_packet(PacketTypeEnum.TX_START, ctx, datas)
56
+
57
+ return ctx
58
+
59
+
60
+ def end_interceptor(thread_id=None, ctx=None):
61
+ if not ctx:
62
+ ctx = TraceContextManager.getContext(
63
+ thread_id) if thread_id else TraceContextManager.getLocalContext()
64
+ if not ctx:
65
+ return
66
+
67
+ if conf.dev:
68
+ logging.debug('end transaction id(seq): {}'.format(ctx.id),
69
+ extra={'id': 'WA112'})
70
+ print('end transaction id(seq): {}'.format(ctx.id),
71
+ dict(extra={'id': 'WA112'}))
72
+
73
+ start_time = DateUtil.nowSystem()
74
+ ctx.start_time = start_time
75
+
76
+ datas = [ctx.host, ctx.service_name, ctx.mtid, ctx.mdepth, ctx.mcaller_txid,
77
+ ctx.mcaller_pcode, ctx.mcaller_spec, str(ctx.mcaller_url_hash), ctx.mcaller_poid, ctx.status,
78
+ ctx.is_llm, ctx.mcaller_step_id]
79
+ ctx.elapsed = DateUtil.nowSystem() - start_time
80
+
81
+ async_sender.send_packet(PacketTypeEnum.TX_END, ctx, datas)
82
+
83
+ try:
84
+ from whatap.counter.tasks.llm_log_sink_task import send_llm_tx_status
85
+ send_llm_tx_status(ctx)
86
+ from whatap.counter.tasks.llm_stat_task import LlmStatTask
87
+ if LlmStatTask._instance:
88
+ LlmStatTask._instance.flush_last_error(ctx)
89
+ except Exception:
90
+ pass
91
+
92
+
93
+ def parseServiceName(environ):
94
+ return environ.get('PATH_INFO', '')
95
+
96
+
97
+ def isIgnore(service_name):
98
+ if conf.trace_ignore_url_prefix and service_name.startswith(conf.trace_ignore_url_prefix):
99
+ return True
100
+
101
+ if conf.trace_ignore_url_set and service_name in conf.trace_ignore_url_set:
102
+ return True
103
+
104
+ return False
105
+
106
+
107
+ def interceptor(rn_environ, *args, **kwargs):
108
+ if not isinstance(rn_environ, tuple):
109
+ rn_environ = (rn_environ, args[1])
110
+ fn, environ = rn_environ
111
+
112
+ ctx = TraceContext()
113
+ ctx.host = environ.get('HTTP_HOST', '').split(':')[0]
114
+ ctx.service_name = parseServiceName(environ)
115
+ ctx.http_method = environ.get('REQUEST_METHOD', '')
116
+ ctx.remoteIp = userid_util.getRemoteAddr(args)
117
+
118
+ ctx.userAgentString = environ.get('HTTP_USER_AGENT', '')
119
+ ctx.referer = environ.get('HTTP_REFERER', '')
120
+
121
+ if conf.trace_user_enabled:
122
+ if conf.trace_user_using_ip:
123
+ ctx.userid = userid_util.getRemoteAddr(args)
124
+ else:
125
+ ctx.userid, ctx._rawuserid = userid_util.getUserId(args, ctx.remoteIp)
126
+
127
+ mstt = environ.get('HTTP_{}'.format(
128
+ conf._trace_mtrace_caller_key.upper().replace('-', '_')), '')
129
+
130
+ if mstt:
131
+ ctx.setTransfer(mstt)
132
+ if conf.stat_mtrace_enabled:
133
+ val = environ.get('HTTP_{}'.format(
134
+ conf._trace_mtrace_info_key.upper().replace('-', '_')), '')
135
+ if val and len(val):
136
+ ctx.setTransferInfo(val)
137
+ pass
138
+
139
+ myid = environ.get('HTTP_{}'.format(
140
+ conf._trace_mtrace_callee_key.upper().replace('-', '_')), '')
141
+ if myid:
142
+ ctx.setTxid(myid)
143
+ caller_poid = environ.get('HTTP_{}'.format(
144
+ conf._trace_mtrace_caller_poid_key.upper().replace('-', '_')), '')
145
+
146
+ if caller_poid:
147
+ ctx.mcaller_poid = caller_poid
148
+
149
+ try:
150
+ if isIgnore(ctx.service_name):
151
+ ctx.is_ignored = True
152
+ TraceContextManager.end(ctx.id)
153
+ return fn(*args, **kwargs)
154
+ except Exception as e:
155
+ pass
156
+
157
+ start_interceptor(ctx)
158
+
159
+ try:
160
+
161
+ callback = fn(*args, **kwargs)
162
+ query_string = environ.get('QUERY_STRING', '')
163
+ if query_string:
164
+ ctx.service_name += '?{}'.format(query_string)
165
+
166
+ if ctx.service_name.find('.') > -1 and ctx.service_name.split('.')[
167
+ 1] in conf.web_static_content_extensions:
168
+ ctx.isStaticContents = 'true'
169
+
170
+ if getattr(callback, 'status_code', None):
171
+ status_code = callback.status_code
172
+
173
+ if (status_code >= 400):
174
+ errors = [callback.__class__.__name__, callback.reason_phrase]
175
+ interceptor_error(status_code, errors, ctx=ctx)
176
+
177
+ if conf.profile_http_header_enabled:
178
+ keys = []
179
+ for key, value in environ.items():
180
+ if key.startswith('HTTP_'):
181
+ keys.append(key)
182
+ keys.sort()
183
+
184
+ text = ''
185
+ for key in keys:
186
+ text += '{}={}\n'.format(key.split('HTTP_')[1].lower(),
187
+ environ[key])
188
+
189
+ datas = ['HTTP-HEADERS', 'HTTP-HEADERS', text]
190
+ ctx.start_time = DateUtil.nowSystem()
191
+ async_sender.send_packet(PacketTypeEnum.TX_MSG, ctx, datas)
192
+ return callback
193
+ finally:
194
+ end_interceptor(ctx=ctx)
195
+
File without changes
@@ -0,0 +1,49 @@
1
+ from whatap.trace import get_dict
2
+ from whatap.trace.trace_handler import trace_handler
3
+ from whatap.trace.mod.database.util import interceptor_db_con, interceptor_db_execute, interceptor_db_close
4
+
5
+ db_info = {}
6
+
7
+ def _preload_oracle_db_info(*args, **kwargs):
8
+ global db_info
9
+ db_info = {'type': 'oracle'}
10
+ db_info.update(kwargs)
11
+
12
+ def instrument_oracle_client(module):
13
+
14
+ def wrapper(fn):
15
+ @trace_handler(fn, preload=_preload_oracle_db_info)
16
+ def trace(*args, **kwargs):
17
+ callback = interceptor_db_con(fn, db_info, *args, **kwargs)
18
+ return callback
19
+
20
+ return trace
21
+
22
+ if hasattr(module, "connect"):
23
+ module.connect = wrapper(module.connect)
24
+
25
+ def wrapper(fn):
26
+ @trace_handler(fn)
27
+ def trace(*args, **kwargs):
28
+ callback = interceptor_db_close(fn, *args, **kwargs)
29
+ return callback
30
+
31
+ return trace
32
+
33
+ if hasattr(module, "Connection") and hasattr(module.Connection, "close"):
34
+ get_dict(module.Connection)['close'] = wrapper(
35
+ module.Connection.close)
36
+
37
+ # def wrapper(fn):
38
+ # @trace_handler(fn)
39
+ # def trace(*args, **kwargs):
40
+ # callback = interceptor_db_execute(fn, db_info, *args, **kwargs)
41
+ # return callback
42
+ #
43
+ # return trace
44
+ #
45
+ # if hasattr(module, 'Cursor') and hasattr(module.Cursor, "execute"):
46
+ # get_dict(module.Cursor)['execute'] = wrapper(module.Cursor.execute)
47
+
48
+
49
+