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,133 @@
1
+ from collections import defaultdict
2
+
3
+ from whatap.llm.stats.base_stat import BaseStat
4
+ from whatap.util.hash_util import HashUtil
5
+
6
+ _TOKEN_TYPES = [
7
+ 'input_tokens', 'output_tokens', 'cached_tokens', 'reasoning_tokens',
8
+ 'cache_creation_input_tokens', 'cache_read_input_tokens',
9
+ ]
10
+
11
+ _TOKEN_COST_MAP = {
12
+ 'input_tokens': 'input_cost',
13
+ 'output_tokens': 'output_cost',
14
+ 'cached_tokens': 'cached_cost',
15
+ }
16
+
17
+
18
+ class TokenUsageStat(BaseStat):
19
+ _category = "llm_token_usage"
20
+ _is_listed = True
21
+
22
+ def _empty_stats(self):
23
+ return {
24
+ 'calls': defaultdict(int),
25
+ 'tokens': defaultdict(lambda: defaultdict(int)),
26
+ 'token_costs': defaultdict(lambda: defaultdict(float)),
27
+ }
28
+
29
+ def _get_keys(self, stats):
30
+ # call 은 집계됐지만 토큰이 전부 0 인 key (에러 응답, usage 미수신 스트리밍
31
+ # 등) 는 제외한다. 포함하면 _build_fields_listed 에서 한 row 도 추가되지
32
+ # 않아 평행 배열이 비어 있는 채로 pack 이 송출되고, 백엔드에서 빈 칸 row 로
33
+ # 나타난다.
34
+ tokens = stats['tokens']
35
+ return [k for k in stats['calls'].keys()
36
+ if any(v > 0 for v in tokens[k].values())]
37
+
38
+ def update_stats(self, input_tokens, output_tokens,
39
+ model_name, host='', operation_type='default', url='',
40
+ cached_tokens=0, reasoning_tokens=0,
41
+ cache_creation_input_tokens=0, cache_read_input_tokens=0,
42
+ input_cost=0.0, output_cost=0.0, cached_cost=0.0,
43
+ prompt_version='v1'):
44
+ key = (model_name or 'unknown', host or '', operation_type or 'default',
45
+ url or '', prompt_version or 'v1')
46
+ with self._lock:
47
+ self._stats['calls'][key] += 1
48
+ t = self._stats['tokens'][key]
49
+ t['input_tokens'] += input_tokens
50
+ t['output_tokens'] += output_tokens
51
+ t['cached_tokens'] += cached_tokens
52
+ t['reasoning_tokens'] += reasoning_tokens
53
+ t['cache_creation_input_tokens'] += cache_creation_input_tokens
54
+ t['cache_read_input_tokens'] += cache_read_input_tokens
55
+ c = self._stats['token_costs'][key]
56
+ c['input_cost'] += input_cost
57
+ c['output_cost'] += output_cost
58
+ c['cached_cost'] += cached_cost
59
+
60
+ def update_from_pack(self, pack):
61
+ self.update_stats(
62
+ pack.input_tokens or 0,
63
+ pack.output_tokens or 0,
64
+ pack.model or 'unknown',
65
+ host=pack.provider or '',
66
+ operation_type=pack.operation_type or 'default',
67
+ url=pack.url or '',
68
+ cached_tokens=pack.cached_tokens or 0,
69
+ reasoning_tokens=pack.reasoning_tokens or 0,
70
+ cache_creation_input_tokens=pack.cache_creation_input_tokens or 0,
71
+ cache_read_input_tokens=pack.cache_read_input_tokens or 0,
72
+ input_cost=pack.input_cost or 0.0,
73
+ output_cost=pack.output_cost or 0.0,
74
+ cached_cost=pack.cached_cost or 0.0,
75
+ prompt_version=getattr(pack, 'prompt_version', 'v1') or 'v1',
76
+ )
77
+
78
+ def _build_fields_listed(self, pack, stats, keys, pid):
79
+ """리스트형 메트릭. 모든 key 의 (token_type) row 를 평행 배열로 평탄화.
80
+
81
+ Layout:
82
+ - 키 차원 (row 단위): pid / model / provider / operation_type / url / prompt_version
83
+ - 토큰 차원 (row 단위): tokens / tokens_count / tokens_cost / @id
84
+
85
+ key-level scalar 은 두지 않는다:
86
+ - call_count / error_count / stream_count → llm_perf_stat 으로 이전
87
+ - total_tokens / total_cost → tokens_count / tokens_cost list 합으로
88
+ 백엔드에서 도출 (리스트 평행 배열에서 "첫 row 에만 값" 표현은 의미가
89
+ 깨지고, 이미 list 필드로 derivable 이라 중복)
90
+ """
91
+ # 평행 배열 column 들
92
+ id_list = pack.fields.newList("@id")
93
+ pid_list = pack.fields.newList("pid")
94
+ model_list = pack.fields.newList("model")
95
+ provider_list = pack.fields.newList("provider")
96
+ op_type_list = pack.fields.newList("operation_type")
97
+ url_list = pack.fields.newList("url")
98
+ prompt_version_list = pack.fields.newList("prompt_version")
99
+
100
+ tokens_list = pack.fields.newList("tokens")
101
+ tokens_count_list = pack.fields.newList("tokens_count")
102
+ tokens_cost_list = pack.fields.newList("tokens_cost")
103
+
104
+ for key in keys:
105
+ try:
106
+ model, provider, op_type, url, prompt_version = key
107
+ except ValueError:
108
+ model, provider, op_type, url = key
109
+ prompt_version = 'v1'
110
+
111
+ t = stats['tokens'][key]
112
+ c = stats['token_costs'][key]
113
+
114
+ for token_type in _TOKEN_TYPES:
115
+ count = t.get(token_type, 0)
116
+ if count <= 0:
117
+ continue
118
+
119
+ # 토큰 차원
120
+ id_list.addLong(HashUtil.hashFromString(
121
+ "{}:{}:{}:{}:{}".format(model, provider, op_type, prompt_version, token_type)))
122
+ tokens_list.addString(token_type)
123
+ tokens_count_list.addLong(count)
124
+ cost_key = _TOKEN_COST_MAP.get(token_type)
125
+ tokens_cost_list.addFloat(round(c.get(cost_key, 0.0), 6) if cost_key else 0.0)
126
+
127
+ # 키 차원 (모든 row 에 반복)
128
+ pid_list.addLong(pid)
129
+ model_list.addString(model)
130
+ provider_list.addString(provider)
131
+ op_type_list.addString(op_type)
132
+ url_list.addString(url)
133
+ prompt_version_list.addString(prompt_version)
@@ -0,0 +1,10 @@
1
+ """llm_eval_toxicity 카테고리 — Toxicity 평가 점수 히스토그램.
2
+
3
+ 11-bucket 분포 (value0~value10). 자세한 동작은 ``eval_stat.ScoreHistogramStat``
4
+ docstring 참고.
5
+ """
6
+ from whatap.llm.stats.eval_stat import ScoreHistogramStat
7
+
8
+
9
+ class ToxicityEvalStat(ScoreHistogramStat):
10
+ _category = 'llm_eval_toxicity'
@@ -0,0 +1,12 @@
1
+ """llm_eval_url_scan 카테고리 — URL Scan suspicious 점수 히스토그램.
2
+
3
+ 11-bucket 분포 (value0~value10). 자세한 동작은 ``eval_stat.ScoreHistogramStat``
4
+ docstring 참고.
5
+
6
+ 값 의미: 0.0 = URL 없거나 모두 안전, 1.0 = 모든 URL 이 suspicious.
7
+ """
8
+ from whatap.llm.stats.eval_stat import ScoreHistogramStat
9
+
10
+
11
+ class URLScanEvalStat(ScoreHistogramStat):
12
+ _category = 'llm_eval_url_scan'
whatap/net/__init__.py ADDED
File without changes
@@ -0,0 +1,107 @@
1
+ import copy
2
+ import queue, time, threading
3
+ from . import udp_session
4
+ from whatap.conf.configure import Configure as conf
5
+ from whatap.trace.simple_trace_context import SimpleTraceContext
6
+ from whatap.net.packet_type_enum import PacketTypeEnum
7
+
8
+ q = queue.Queue(conf.max_send_queue_size)
9
+
10
+ from enum import Enum
11
+ class SendType(Enum):
12
+ DATAS = 1
13
+ RELAY = 2
14
+ LLM_RELAY = 3
15
+ LLM_FLUSH = 4
16
+
17
+ _LLM_IDLE_FLUSH_SEC = 0.1
18
+
19
+ _STEP_TYPES = {
20
+ PacketTypeEnum.TX_DB_CONN, PacketTypeEnum.TX_DB_FETCH,
21
+ PacketTypeEnum.TX_SQL, PacketTypeEnum.TX_HTTPC,
22
+ PacketTypeEnum.TX_ERROR, PacketTypeEnum.TX_MSG,
23
+ PacketTypeEnum.TX_METHOD,
24
+ }
25
+
26
+
27
+ def send_packet( packet_type, ctx, datas=[]):
28
+
29
+ ctx = SimpleTraceContext(ctx)
30
+
31
+ # deep coopy TraceContext object before adding it to the queue, preventing potential data overwriting issues caused by concurrent modifications
32
+ copied_ctx = ctx.getDeepCopiedContext()
33
+ _initThread()
34
+ global q
35
+ if q.full():
36
+ return
37
+ q.put((SendType.DATAS, (packet_type, copied_ctx, datas)))
38
+
39
+ def send_relaypack( packbytes):
40
+ _initThread()
41
+ global q
42
+ if q.full():
43
+ return
44
+ q.put((SendType.RELAY, packbytes))
45
+
46
+ def send_llm_relaypack( packbytes):
47
+ """LLM 데이터 전용. LLM Go Agent 소켓으로만 전송."""
48
+ _initThread()
49
+ global q
50
+ if q.full():
51
+ return
52
+ q.put((SendType.LLM_RELAY, packbytes))
53
+
54
+ def flush_llm_relaypack():
55
+ """LLM 버퍼 명시적 flush 요청. 큐를 거치므로 이전에 enqueue된 LLM_RELAY들이 모두 처리된 뒤 flush된다."""
56
+ _initThread()
57
+ global q
58
+ if q.full():
59
+ return
60
+ q.put((SendType.LLM_FLUSH, None))
61
+
62
+ def startWhatapThread():
63
+ def __sendPackets():
64
+ global q
65
+ while True:
66
+ try:
67
+ packet_env = q.get(timeout=_LLM_IDLE_FLUSH_SEC)
68
+ except queue.Empty:
69
+ # idle 상태에서 LLM 버퍼에 남아있는 데이터 flush
70
+ udp_session.UdpSession.flush_llm_buffer()
71
+ continue
72
+ if not packet_env:
73
+ continue
74
+ sendType,params = packet_env
75
+ if sendType == SendType.DATAS:
76
+ packet_type, ctx, datas = params
77
+ udp_session.UdpSession.send_packet(packet_type, ctx, datas)
78
+ elif sendType == SendType.RELAY:
79
+ packbytes = params
80
+ udp_session.UdpSession.send_relaypack(packbytes)
81
+ elif sendType == SendType.LLM_RELAY:
82
+ packbytes = params
83
+ udp_session.UdpSession.send_llm_relaypack(packbytes)
84
+ elif sendType == SendType.LLM_FLUSH:
85
+ udp_session.UdpSession.flush_llm_buffer()
86
+ t = threading.Thread(target=__sendPackets)
87
+ t.setDaemon(True)
88
+ t.start()
89
+
90
+ _lock = threading.Lock()
91
+ _initialized = False
92
+
93
+ def _initThread():
94
+ global _lock, _initialized
95
+ if _initialized:
96
+ return
97
+ try:
98
+ if _initialized:
99
+ return
100
+ _lock.acquire()
101
+ if _initialized:
102
+ return
103
+ _initialized=True
104
+ startWhatapThread()
105
+ finally:
106
+ _lock.release()
107
+
@@ -0,0 +1,44 @@
1
+ class PacketEnum(object):
2
+ PACKET_BUFFER_SIZE = 48 * 1024
3
+ PACKET_SEND_BUFFER_SIZE = 64 * 1024
4
+ DATA_SIZE_LIMIT = 30*1024 +1
5
+
6
+ SERVER = "127.0.0.1"
7
+ PORT = 6600
8
+ PACKET_VERSION = 20106
9
+
10
+ # PACKET_HEADER
11
+ PACKET_HEADER_TYPE_POS = 0
12
+ PACKET_HEADER_TYPE_SIZE = 1
13
+
14
+ PACKET_HEADER_VERSION_POS = 1
15
+ PACKET_HEADER_VERSION_SIZE = 4
16
+
17
+ PACKET_HEADER_LEN_POS = 5
18
+ PACKET_HEADER_LEN_SIZE = 4
19
+
20
+ # PACKET_BODY
21
+ PACKET_BODY_ID_POS = 9
22
+ PACKET_BODY_ID_SIZE = 8
23
+
24
+ PACKET_BODY_START_TIME_POS = 17
25
+ PACKET_BODY_START_TIME_SIZE = 8
26
+
27
+ PACKET_BODY_ELAPSED_POS = 25
28
+ PACKET_BODY_ELAPSED_SIZE = 4
29
+
30
+ PACKET_BODY_CPU_POS = 29
31
+ PACKET_BODY_CPU_SIZE = 8
32
+
33
+ PACKET_BODY_MEMOERY_POS = 37
34
+ PACKET_BODY_MEMOERY_SIZE = 8
35
+
36
+ PACKET_BODY_THREAD_ID_POS = 45
37
+ PACKET_BODY_THREAD_ID_SIZE = 8
38
+
39
+ PACKET_BODY_TRACE_DATA_POS = 53
40
+
41
+ # PACKET_SIZE
42
+ PACKET_HEADER_SIZE = PACKET_HEADER_TYPE_SIZE + PACKET_HEADER_VERSION_SIZE + PACKET_HEADER_LEN_SIZE
43
+ PACKET_BODY_REQUIRED_SIZE = PACKET_BODY_ID_SIZE + PACKET_BODY_START_TIME_SIZE + PACKET_BODY_ELAPSED_SIZE \
44
+ + PACKET_BODY_CPU_SIZE + PACKET_BODY_MEMOERY_SIZE + PACKET_BODY_THREAD_ID_SIZE
@@ -0,0 +1,31 @@
1
+ class PacketTypeEnum(object):
2
+ TX_BLANK = 0
3
+ TX_START = 1
4
+ TX_DB_CONN = 2
5
+ TX_DB_FETCH = 3
6
+ TX_SQL = 4
7
+ TX_SQL_START = 5
8
+ TX_SQL_END = 6
9
+
10
+ TX_HTTPC = 7
11
+ TX_HTTPC_START = 8
12
+ TX_HTTPC_END = 9
13
+
14
+ TX_ERROR = 10
15
+ TX_MSG = 11
16
+ TX_METHOD = 12
17
+
18
+ # secure msg
19
+ TX_SECURE_MSG = 13
20
+
21
+ TX_WEB_SOCKET = 16
22
+ TX_END = 255
23
+
24
+ TX_PARAM = 30
25
+ ACTIVE_STACK = 40
26
+ ACTIVE_STATS = 41
27
+ DBCONN_POOL = 42
28
+
29
+ EVENT = 50
30
+
31
+ RELAY_PACK = 244
@@ -0,0 +1,69 @@
1
+ class ParamDef(object):
2
+ KEEPALIVE = 1
3
+ AGENT_BOOT_ENV = 2
4
+ CONFIGURE_UPDATE = 3
5
+ CONFIGURE_GET = 4
6
+ COMPO_VERSIONS = 5
7
+ THREAD_LIST = 7
8
+ THREAD_DETAIL = 8
9
+ GET_ACTIVE_STACK = 9
10
+ HEAP_HISTO = 10
11
+ LOADED_CLASS_LIST = 11
12
+ GET_ENV = 12
13
+ SYSTEM_GC = 13
14
+ SET_CONFIG = 14
15
+ OPEN_SOCKET_LIST = 15
16
+ LOADED_CLASS_DETAIL = 16
17
+ LOADED_CLASS_REDEFINE = 17
18
+ AGENT_JAR_LIST = 18
19
+ AGENT_JAR_SAVE = 19
20
+ AGENT_JAR_DELETE = 20
21
+ RESET_STRING_SENT_MARK = 21
22
+ AGENT_LOG_LIST = 22
23
+ AGENT_LOG_READ = 23
24
+ THREAD_CONTROL = 24
25
+ GET_ACTIVE_TRANSACTION_LIST = 25
26
+ GET_ACTIVE_TRANSACTION_DETAIL = 26
27
+ GET_TOPOLOGY = 27
28
+ INFRA_NET_STAT=28
29
+ INFRA_PS_EF=29
30
+ INFRA_DOCKER_LIST=30
31
+ INFRA_REMOTE_CMD=33
32
+ INFRA_PEER_LIST = 34
33
+ INFRA_AGENT_UPDATE = 36
34
+ AGENT_DUMP_LIST = 31
35
+ AGENT_DUMP_READ = 32
36
+ AGENT_STAT = 35
37
+ JVM_THREAD_DUMP = 37
38
+ JVM_HEAP_DUMP = 38
39
+ KUBENETES = 39
40
+ GET_ACTIVE_STATS = 40
41
+ GET_DBCONN_POOL = 41
42
+ MODULE_DEPENDENCY = 101
43
+ DBX_INFO = 201
44
+ DBX_SETTINGS = 202
45
+ DBX_USER_SCRIPT = 207
46
+ DBX_SCRIPT_LIST = 208
47
+ DBX_SCRIPT_SQL = 209
48
+ DBX_KILL_SESSION = 210
49
+ DBX_GET_ALERT = 211
50
+ DBX_SET_ALERT = 212
51
+ DBX_PLAN = 213
52
+ DBX_SESSION_LIST = 214
53
+ DBX_SET_CPUCORES = 215
54
+ DBX_SESSION_STAT = 203
55
+ DBX_SESSION_EVENT = 204
56
+ DBX_TOPSTAT = 205
57
+ DBX_TOPEVENT = 206
58
+ CONFIG_DBC = 301
59
+ METHOD_PERF_STAT = 302
60
+ BLOCKING_DETECT = 303
61
+ CW_INFO = 401
62
+ CW_EVENTS = 402
63
+ CW_CREDENTIAL = 403
64
+ CW_REGIONS = 404
65
+ CW_METRIC_NAMES = 405
66
+ CW_AWS_RESOURCE_IDS = 406
67
+ CW_STATISTICS = 407
68
+ CW_UNITS = 408
69
+ CW_METRICS = 409
@@ -0,0 +1,87 @@
1
+ import shlex
2
+ import faulthandler
3
+ import tempfile
4
+ import os
5
+ class StackParser:
6
+
7
+ parsers = {}
8
+ @staticmethod
9
+ def onNewParser(parser):
10
+ StackParser.parsers[parser.getThreadId()] =parser
11
+
12
+ @staticmethod
13
+ def listAll():
14
+ for p in StackParser.parsers:
15
+ yield p
16
+
17
+ @classmethod
18
+ def find(cls, thread_id):
19
+ if thread_id in cls.parsers:
20
+ p = cls.parsers.get(thread_id)
21
+ return p.iterateStacks()
22
+ else:
23
+ return iter([])
24
+
25
+ @staticmethod
26
+ def parse():
27
+ with tempfile.NamedTemporaryFile() as buf:
28
+ faulthandler.dump_traceback(buf)
29
+ if buf.tell() < 1:
30
+ return
31
+ buf.seek(0)
32
+ stackdump = buf.read().decode("utf-8")
33
+ stackParser = None
34
+ for stack in stackdump.split('\n'):
35
+ if not stack:
36
+ stackParser.onComplete()
37
+ stackParser = None
38
+ continue
39
+ if not stackParser:
40
+ stackParser = StackParser(stack)
41
+ else:
42
+ stackParser.add(stack)
43
+
44
+ def __init__(self, threadBegin):
45
+ self.__stacks = []
46
+ tokens = shlex.split(threadBegin)
47
+ if tokens and len(tokens) > 2:
48
+ try:
49
+ if 'Thread' == tokens[0] and int(tokens[1],0) > 0:
50
+ threadid = int(tokens[1],0)
51
+ self.__threadid = threadid
52
+
53
+ StackParser.onNewParser(self)
54
+ elif 'Current' == tokens[0] and 'thread' == tokens[1] and int(tokens[2],0):
55
+ threadid = int(tokens[2],0)
56
+ self.__threadid = threadid
57
+
58
+ StackParser.onNewParser(self)
59
+ except ValueError:
60
+ pass
61
+
62
+ def getThreadId(self):
63
+ return self.__threadid
64
+
65
+ def add(self, line):
66
+ tokens = shlex.split(line)
67
+ if len(tokens) == 6:
68
+ _, module, _, lineno, _, method = tokens
69
+ self.__stacks.append((module.strip(','), lineno, method))
70
+
71
+ def iterateStacks(self):
72
+ return iter(self.__stacks)
73
+
74
+ def toString(self):
75
+ return """Thread: {}
76
+ {}""".format(self.__threadid, "\n".join([ "{} {} {}".format(stack[0],stack[1],stack[2]) for stack in self.__stacks]))
77
+
78
+ def onComplete(self):
79
+ pass
80
+
81
+ def getThreadStackFaultHandler( thread_id):
82
+ StackParser.parse()
83
+ for line, line_num, method_name in StackParser.find(thread_id):
84
+ if 'whatap' + os.sep + 'trace' in line or 'threading.py' in line:
85
+ continue
86
+ yield '{} ({}:{})\n'.format(method_name, line, line_num)
87
+