whatap-python 1.8.11.post0__tar.gz → 1.8.13__tar.gz
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.
Potentially problematic release.
This version of whatap-python might be problematic. Click here for more details.
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/PKG-INFO +1 -1
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/__init__.py +1 -1
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/agent/darwin/amd64/whatap_python +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/agent/darwin/arm64/whatap_python +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/agent/linux/amd64/whatap_python +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/agent/linux/arm64/whatap_python +0 -0
- whatap_python-1.8.13/whatap/build.py +4 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/conf/configuration.py +4 -1
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/counter/__init__.py +2 -2
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/counter/counter_manager.py +12 -5
- whatap_python-1.8.13/whatap/counter/tasks/llm_stat.py +111 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/fastapi.py +1 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/database/psycopg3.py +51 -22
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/database/util.py +26 -4
- whatap_python-1.8.13/whatap/trace/mod/httpc/httpx.py +36 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/llm/openai.py +25 -1
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap_python.egg-info/PKG-INFO +1 -1
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap_python.egg-info/SOURCES.txt +1 -0
- whatap_python-1.8.11.post0/whatap/build.py +0 -4
- whatap_python-1.8.11.post0/whatap/trace/mod/httpc/httpx.py +0 -24
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/README.md +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/setup.cfg +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/setup.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/LICENSE +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/README.rst +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/__main__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/bootstrap/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/bootstrap/sitecustomize.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/conf/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/conf/configure.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/conf/license.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/control/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/counter/tasks/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/counter/tasks/openfiledescriptor.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/io/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/io/data_inputx.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/io/data_outputx.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/net/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/net/async_sender.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/net/packet_enum.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/net/packet_type_enum.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/net/param_def.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/net/stackhelper.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/net/udp_session.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/net/udp_thread.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/pack/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/pack/logSinkPack.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/pack/pack.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/pack/pack_enum.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/pack/tagCountPack.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/scripts/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/amqp/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/amqp/kombu.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/amqp/pika.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/bottle.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/celery.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/cherrypy.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/django.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/django_asgi.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/django_py3.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/flask.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/frappe.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/graphql.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/nameko.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/odoo.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/starlette.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/tornado.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/wsgi.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/database/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/database/cxoracle.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/database/mongo.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/database/mysql.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/database/neo4j.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/database/psycopg2.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/database/redis.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/database/sqlalchemy.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/database/sqlite3.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/email/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/email/smtp.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/httpc/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/httpc/django.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/httpc/httplib.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/httpc/requests.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/httpc/urllib3.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/llm/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/logging.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/plugin.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/standalone/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/standalone/multiple.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/standalone/single.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/simple_trace_context.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/trace_context.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/trace_context_manager.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/trace_import.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/trace_module_definition.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/bit_util.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/cardinality/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/cardinality/hyperloglog.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/cardinality/murmurhash.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/cardinality/registerset.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/compare_util.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/date_util.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/debug_util.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/escape_literal_sql.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/hash_util.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/hexa32.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/int_set.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/ip_util.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/keygen.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/linked_list.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/linked_map.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/metering_util.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/request_double_queue.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/request_queue.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/string_util.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/throttle_util.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/util/userid_util.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/__init__.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/blob_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/boolean_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/decimal_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/double_summary.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/double_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/float_array.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/float_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/int_array.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/ip4_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/list_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/long_array.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/long_summary.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/map_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/null_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/number_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/summary_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/text_array.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/text_hash_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/text_value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/value.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/value/value_enum.py +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/whatap.conf +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap_python.egg-info/dependency_links.txt +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap_python.egg-info/entry_points.txt +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap_python.egg-info/not-zip-safe +0 -0
- {whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap_python.egg-info/top_level.txt +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -215,6 +215,9 @@ Configuration = {
|
|
|
215
215
|
"log_unhandled_exception": 'false',
|
|
216
216
|
"threadstack_faulthandler": False,
|
|
217
217
|
"max_send_queue_size": 1000,
|
|
218
|
-
"open_file_descriptor_enabled":False,
|
|
218
|
+
"open_file_descriptor_enabled": False,
|
|
219
219
|
"open_file_descriptor_interval":60,
|
|
220
|
+
"counter_thread_enabled": False,
|
|
221
|
+
"llm_stat_enabled" : False,
|
|
222
|
+
"llm_stat_interval" : 5
|
|
220
223
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from .counter_manager import CounterMgr # CounterMgr 클래스 import
|
|
2
2
|
from whatap import preview_whatap_conf
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
counter_thread_enabled = preview_whatap_conf("counter_thread_enabled")
|
|
5
5
|
|
|
6
|
-
if
|
|
6
|
+
if counter_thread_enabled != 'false':
|
|
7
7
|
mgr = CounterMgr()
|
|
8
8
|
mgr.setDaemon(True)
|
|
9
9
|
mgr.start()
|
|
@@ -3,20 +3,27 @@ import time
|
|
|
3
3
|
import logging
|
|
4
4
|
from threading import Thread
|
|
5
5
|
from .tasks.openfiledescriptor import OpenFileDescriptorTask
|
|
6
|
+
from .tasks.llm_stat import LLMStatTask
|
|
6
7
|
|
|
7
8
|
#현재 디렉토리 아래 tasks 가 있고 그안의 openfiledescriptor.py 파일에 OpenFileDescriptorTask 클래스를 import 하고싶어.
|
|
8
9
|
|
|
9
10
|
class CounterMgr(Thread):
|
|
11
|
+
_instance = None
|
|
10
12
|
def __init__(self):
|
|
11
13
|
super(CounterMgr, self).__init__() # Thread 초기화
|
|
12
14
|
self.tasks = list()
|
|
13
15
|
self.last_executed = {} # 각 task의 마지막 실행 시간을 기록하기 위한 딕셔너리
|
|
14
|
-
|
|
16
|
+
CounterMgr._instance = self
|
|
17
|
+
|
|
15
18
|
def run(self):
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
self.
|
|
19
|
-
|
|
19
|
+
ofd_task = OpenFileDescriptorTask()
|
|
20
|
+
self.tasks.append(ofd_task)
|
|
21
|
+
self.last_executed[ofd_task.name()] = 0 # 각 task의 마지막 실행 시간을 초기화
|
|
22
|
+
|
|
23
|
+
llm_task = LLMStatTask()
|
|
24
|
+
self.tasks.append(llm_task)
|
|
25
|
+
self.last_executed[llm_task.name()] = 0 # 각 task의 마지막 실행 시간을 초기화
|
|
26
|
+
|
|
20
27
|
while True:
|
|
21
28
|
current_time = time.time() # 현재 시간을 초 단위로 가져옴
|
|
22
29
|
time.sleep(1) # 0.1초마다 확인 (부하 줄이기)
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import whatap.net.async_sender as async_sender
|
|
2
|
+
import whatap.io as whatapio
|
|
3
|
+
from whatap.pack import tagCountPack
|
|
4
|
+
from whatap.pack.tagCountPack import TagCountPack
|
|
5
|
+
from whatap.util.hash_util import HashUtil
|
|
6
|
+
from whatap import DateUtil
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import time
|
|
10
|
+
from typing import List, Dict, Tuple
|
|
11
|
+
from collections import defaultdict
|
|
12
|
+
|
|
13
|
+
currentpid = os.getpid()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class LLMStatTask:
|
|
17
|
+
def __init__(self):
|
|
18
|
+
self.llm_stats = {
|
|
19
|
+
'model_calls': defaultdict(int),
|
|
20
|
+
'model_prompt_tokens': defaultdict(int),
|
|
21
|
+
'model_completion_tokens': defaultdict(int)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
def name(self):
|
|
25
|
+
return "LLMStatTask"
|
|
26
|
+
|
|
27
|
+
def interval(self):
|
|
28
|
+
from whatap.conf.configure import Configure as conf
|
|
29
|
+
return int(getattr(conf, 'llm_stat_interval', 5))
|
|
30
|
+
|
|
31
|
+
def process(self):
|
|
32
|
+
from whatap.conf.configure import Configure as conf
|
|
33
|
+
enabled = getattr(conf, 'llm_stat_enabled', False)
|
|
34
|
+
if not enabled:
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
stats = self.get_current_stats()
|
|
38
|
+
|
|
39
|
+
if not stats['model_calls']:
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
p = TagCountPack()
|
|
44
|
+
p.time = DateUtil.now() // 1000 * 1000
|
|
45
|
+
p.Category = "llm_stat"
|
|
46
|
+
p.tags.putAuto("pid", currentpid)
|
|
47
|
+
p.tags.putAuto("!rectype", 2)
|
|
48
|
+
|
|
49
|
+
model_id_list = p.fields.newList("@id")
|
|
50
|
+
model_name_list = p.fields.newList("model_name")
|
|
51
|
+
call_count_list = p.fields.newList("call_count")
|
|
52
|
+
prompt_tokens_list = p.fields.newList("prompt_tokens")
|
|
53
|
+
completion_tokens_list = p.fields.newList("completion_tokens")
|
|
54
|
+
total_tokens_list = p.fields.newList("total_tokens")
|
|
55
|
+
|
|
56
|
+
for model_name, count in stats['model_calls'].items():
|
|
57
|
+
prompt_tokens = stats['model_prompt_tokens'][model_name]
|
|
58
|
+
completion_tokens = stats['model_completion_tokens'][model_name]
|
|
59
|
+
total_tokens = prompt_tokens + completion_tokens
|
|
60
|
+
|
|
61
|
+
model_id_list.addLong(HashUtil.hashFromString(model_name))
|
|
62
|
+
model_name_list.addString(model_name)
|
|
63
|
+
call_count_list.addLong(count)
|
|
64
|
+
prompt_tokens_list.addLong(prompt_tokens)
|
|
65
|
+
completion_tokens_list.addLong(completion_tokens)
|
|
66
|
+
total_tokens_list.addLong(total_tokens)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
p.pcode = getattr(conf, 'PCODE', 0)
|
|
70
|
+
bout = whatapio.DataOutputX()
|
|
71
|
+
bout.writePack(p, None)
|
|
72
|
+
packbytes = bout.toByteArray()
|
|
73
|
+
|
|
74
|
+
async_sender.send_relaypack(packbytes)
|
|
75
|
+
self.reset_stats()
|
|
76
|
+
|
|
77
|
+
except Exception as e:
|
|
78
|
+
import traceback
|
|
79
|
+
traceback.print_exc()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def get_current_stats(self) -> Dict:
|
|
83
|
+
return {
|
|
84
|
+
'model_calls': dict(self.llm_stats['model_calls']),
|
|
85
|
+
'model_prompt_tokens': dict(self.llm_stats['model_prompt_tokens']),
|
|
86
|
+
'model_completion_tokens': dict(self.llm_stats['model_completion_tokens'])
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
def prepare_model_data(self, model_calls: Dict[str, int]) -> Tuple[List[str], List[int]]:
|
|
90
|
+
if not model_calls:
|
|
91
|
+
return [], []
|
|
92
|
+
|
|
93
|
+
models = list(model_calls.keys())
|
|
94
|
+
call_count = [model_calls[model] for model in models]
|
|
95
|
+
|
|
96
|
+
return models, call_count
|
|
97
|
+
|
|
98
|
+
def update_stats(self, prompt_tokens: int, completion_tokens: int,
|
|
99
|
+
model_name: str):
|
|
100
|
+
self.llm_stats['model_calls'][model_name] += 1
|
|
101
|
+
self.llm_stats['model_prompt_tokens'][model_name] += prompt_tokens
|
|
102
|
+
self.llm_stats['model_completion_tokens'][model_name] += completion_tokens
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def reset_stats(self):
|
|
107
|
+
self.llm_stats = {
|
|
108
|
+
'model_calls': defaultdict(int),
|
|
109
|
+
'model_prompt_tokens': defaultdict(int),
|
|
110
|
+
'model_completion_tokens': defaultdict(int)
|
|
111
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import inspect
|
|
2
2
|
|
|
3
|
-
from whatap.trace.mod.application.wsgi import trace_handler
|
|
3
|
+
from whatap.trace.mod.application.wsgi import trace_handler, async_trace_handler
|
|
4
4
|
from whatap.trace.mod.database.util import (
|
|
5
5
|
interceptor_db_con, interceptor_db_execute, interceptor_db_close,
|
|
6
6
|
async_interceptor_db_con, async_interceptor_db_execute, async_interceptor_db_close,
|
|
@@ -218,14 +218,17 @@ def _sync_wrapper(fn):
|
|
|
218
218
|
|
|
219
219
|
db_info = {"type": "postgresql"}
|
|
220
220
|
|
|
221
|
-
if args
|
|
221
|
+
if args:
|
|
222
222
|
conn_str = args[0]
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
223
|
+
if isinstance(args[0], str) and '=' in args[0]:
|
|
224
|
+
parsed_kwargs = dict(
|
|
225
|
+
x.split('=') for x in conn_str.split()
|
|
226
|
+
)
|
|
227
|
+
kwargs.update(parsed_kwargs)
|
|
228
|
+
db_info.update(kwargs)
|
|
229
|
+
else:
|
|
230
|
+
db_info.update({"db_con_stc": "completed"})
|
|
231
|
+
db_info.update({"db_str": args[0]})
|
|
229
232
|
|
|
230
233
|
connection = interceptor_db_con(fn, db_info, *args, **kwargs)
|
|
231
234
|
if hasattr(connection, '_is_wrapped'):
|
|
@@ -243,14 +246,18 @@ def _async_wrapper(fn):
|
|
|
243
246
|
|
|
244
247
|
db_info = {"type": "postgresql"}
|
|
245
248
|
|
|
246
|
-
if args
|
|
249
|
+
if args:
|
|
247
250
|
conn_str = args[0]
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
251
|
+
if isinstance(args[0], str) and '=' in args[0]:
|
|
252
|
+
parsed_kwargs = dict(
|
|
253
|
+
x.split('=') for x in conn_str.split()
|
|
254
|
+
)
|
|
255
|
+
kwargs.update(parsed_kwargs)
|
|
256
|
+
db_info.update(kwargs)
|
|
257
|
+
else:
|
|
258
|
+
db_info.update({"db_con_stc": "completed"})
|
|
259
|
+
db_info.update({"db_str": args[0]})
|
|
252
260
|
|
|
253
|
-
db_info.update(kwargs)
|
|
254
261
|
|
|
255
262
|
connection = await async_interceptor_db_con(fn, db_info, *args, **kwargs)
|
|
256
263
|
if hasattr(connection, '_is_wrapped'):
|
|
@@ -290,15 +297,34 @@ def _pool_getconn_wrapper(original_getconn):
|
|
|
290
297
|
return wrapper
|
|
291
298
|
|
|
292
299
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
300
|
+
class AsyncConnectionProxy:
|
|
301
|
+
"""AsyncConnectionPool.connection()이 반환하는 proxy 객체를 래핑"""
|
|
302
|
+
|
|
303
|
+
def __init__(self, proxy):
|
|
304
|
+
self._proxy = proxy
|
|
305
|
+
self._wrapped_connection = None
|
|
306
|
+
|
|
307
|
+
async def __aenter__(self):
|
|
308
|
+
connection = await self._proxy.__aenter__()
|
|
296
309
|
conn_info = _get_conn_info(connection)
|
|
297
310
|
db_info = {"type": "postgresql", "pool": True, **conn_info}
|
|
298
|
-
|
|
299
311
|
await async_interceptor_pool_get(db_info)
|
|
300
312
|
|
|
301
|
-
|
|
313
|
+
self._wrapped_connection = AsyncConnection(connection, db_info)
|
|
314
|
+
return self._wrapped_connection
|
|
315
|
+
|
|
316
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
317
|
+
if self._wrapped_connection:
|
|
318
|
+
await async_interceptor_pool_release()
|
|
319
|
+
return await self._proxy.__aexit__(exc_type, exc_val, exc_tb)
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def _async_pool_connection_wrapper(original_connection):
|
|
323
|
+
"""AsyncConnectionPool.connection() 메서드를 래핑"""
|
|
324
|
+
|
|
325
|
+
def wrapper(self, *args, **kwargs):
|
|
326
|
+
proxy = original_connection(self, *args, **kwargs)
|
|
327
|
+
return AsyncConnectionProxy(proxy)
|
|
302
328
|
|
|
303
329
|
return wrapper
|
|
304
330
|
|
|
@@ -313,7 +339,10 @@ def instrument_psycopg(module):
|
|
|
313
339
|
|
|
314
340
|
def instrument_psycopg_pool(pool_module):
|
|
315
341
|
if hasattr(pool_module, 'ConnectionPool'):
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
pool_module.AsyncConnectionPool.getconn = _async_pool_getconn_wrapper(pool_module.AsyncConnectionPool.getconn)
|
|
342
|
+
if hasattr(pool_module.ConnectionPool, 'getconn'):
|
|
343
|
+
pool_module.ConnectionPool.getconn = _pool_getconn_wrapper(pool_module.ConnectionPool.getconn)
|
|
319
344
|
|
|
345
|
+
if hasattr(pool_module, 'AsyncConnectionPool'):
|
|
346
|
+
if hasattr(pool_module.AsyncConnectionPool, 'connection'):
|
|
347
|
+
original_connection = pool_module.AsyncConnectionPool.connection
|
|
348
|
+
pool_module.AsyncConnectionPool.connection = _async_pool_connection_wrapper(original_connection)
|
|
@@ -200,6 +200,10 @@ def interceptor_db_con(fn, db_info, *args, **kwargs):
|
|
|
200
200
|
text += "/"
|
|
201
201
|
text += db_info.get('user', '')
|
|
202
202
|
|
|
203
|
+
elif db_type == "postgresql":
|
|
204
|
+
if db_info.get('db_con_stc', '') == 'completed':
|
|
205
|
+
text = db_info.get('db_str', '')
|
|
206
|
+
|
|
203
207
|
else:
|
|
204
208
|
text = '{}://'.format(db_type)
|
|
205
209
|
text += kwargs.get('user', '')
|
|
@@ -289,10 +293,17 @@ def interceptor_db_execute(fn, db_info, *args, **kwargs):
|
|
|
289
293
|
except Exception as e:
|
|
290
294
|
interceptor_step_error(e)
|
|
291
295
|
finally:
|
|
292
|
-
|
|
296
|
+
try:
|
|
297
|
+
if hasattr(args[0], 'rowcount'):
|
|
298
|
+
count = args[0].rowcount
|
|
299
|
+
else:
|
|
300
|
+
count = -1
|
|
301
|
+
except AttributeError:
|
|
302
|
+
count = -1
|
|
303
|
+
|
|
304
|
+
datas = [ctx.lctx.get('dbc', ''), query, str(count)]
|
|
293
305
|
ctx.elapsed = DateUtil.nowSystem() - start_time
|
|
294
306
|
async_sender.send_packet(PacketTypeEnum.TX_SQL, ctx, datas)
|
|
295
|
-
count = self.rowcount
|
|
296
307
|
|
|
297
308
|
if (count is not None) and (count > -1):
|
|
298
309
|
desc = '{0}: {1}'.format('Fetch count', count)
|
|
@@ -351,6 +362,10 @@ async def async_interceptor_db_con(fn, db_info, *args, **kwargs):
|
|
|
351
362
|
|
|
352
363
|
if db_type == "sqlite":
|
|
353
364
|
text = "sqlite:"
|
|
365
|
+
|
|
366
|
+
elif db_type == "postgresql":
|
|
367
|
+
if db_info.get('db_con_stc', '') == 'completed':
|
|
368
|
+
text = db_info.get('db_str', '')
|
|
354
369
|
else:
|
|
355
370
|
text = '{}://'.format(db_type)
|
|
356
371
|
text += kwargs.get('user', '')
|
|
@@ -445,10 +460,17 @@ async def async_interceptor_db_execute(fn, db_info, *args, **kwargs):
|
|
|
445
460
|
interceptor_step_error(e)
|
|
446
461
|
raise
|
|
447
462
|
finally:
|
|
448
|
-
|
|
463
|
+
try:
|
|
464
|
+
if hasattr(args[0], 'rowcount'):
|
|
465
|
+
count = args[0].rowcount
|
|
466
|
+
else:
|
|
467
|
+
count = -1
|
|
468
|
+
except AttributeError:
|
|
469
|
+
count = -1
|
|
470
|
+
|
|
471
|
+
datas = [ctx.lctx.get('dbc', ''), query, str(count)]
|
|
449
472
|
ctx.elapsed = DateUtil.nowSystem() - start_time
|
|
450
473
|
async_sender.send_packet(PacketTypeEnum.TX_SQL, ctx, datas)
|
|
451
|
-
count = self.rowcount
|
|
452
474
|
|
|
453
475
|
if (count is not None) and (count > -1):
|
|
454
476
|
desc = '{0}: {1}'.format('Fetch count', count)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from whatap.trace.mod.application.wsgi import transfer, trace_handler, \
|
|
2
|
+
interceptor_httpc_request
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def instrument_httpx(module):
|
|
6
|
+
def wrapper(fn):
|
|
7
|
+
@trace_handler(fn)
|
|
8
|
+
def trace(*args, **kwargs):
|
|
9
|
+
if len(args) >= 2 and hasattr(args[1], 'headers') and hasattr(args[1], 'url'):
|
|
10
|
+
request = args[1]
|
|
11
|
+
request.headers = transfer(request.headers)
|
|
12
|
+
httpc_url = str(request.url)
|
|
13
|
+
|
|
14
|
+
# 2. stream call: send(request=request, ...)
|
|
15
|
+
elif len(args) == 1 and 'request' in kwargs:
|
|
16
|
+
request = kwargs['request']
|
|
17
|
+
if hasattr(request, 'headers') and hasattr(request, 'url'):
|
|
18
|
+
request.headers = transfer(request.headers)
|
|
19
|
+
httpc_url = str(request.url)
|
|
20
|
+
else:
|
|
21
|
+
httpc_url = "invalid_request_object"
|
|
22
|
+
|
|
23
|
+
# 3. 예상치 못한 패턴
|
|
24
|
+
else:
|
|
25
|
+
httpc_url = "httpx_unknown_pattern"
|
|
26
|
+
|
|
27
|
+
return interceptor_httpc_request(fn, httpc_url, *args, **kwargs)
|
|
28
|
+
|
|
29
|
+
return trace
|
|
30
|
+
|
|
31
|
+
if hasattr(module, 'Client') and hasattr(module.Client, 'send'):
|
|
32
|
+
module.Client.send = wrapper(module.Client.send)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if hasattr(module, 'AsyncClient') and hasattr(module.AsyncClient, 'send'):
|
|
36
|
+
module.AsyncClient.send = wrapper(module.AsyncClient.send)
|
|
@@ -3,8 +3,9 @@ import logging
|
|
|
3
3
|
|
|
4
4
|
from openai import OpenAIError
|
|
5
5
|
|
|
6
|
-
from whatap import DateUtil
|
|
6
|
+
from whatap import DateUtil
|
|
7
7
|
from whatap.pack import logSinkPack
|
|
8
|
+
from whatap.conf.configure import Configure as conf
|
|
8
9
|
from whatap.trace.trace_context_manager import TraceContextManager
|
|
9
10
|
from whatap.trace.mod.application.wsgi import trace_handler
|
|
10
11
|
|
|
@@ -37,6 +38,7 @@ def __send_llm_pack(metadata):
|
|
|
37
38
|
'prompt_tokens': metadata.get('prompt_tokens'),
|
|
38
39
|
'completion_tokens': metadata.get('completion_tokens'),
|
|
39
40
|
'total_tokens': metadata.get('total_tokens'),
|
|
41
|
+
'@step_id' : ctx.mcallee
|
|
40
42
|
}
|
|
41
43
|
|
|
42
44
|
fields.update(llm_fields)
|
|
@@ -60,6 +62,28 @@ def __send_llm_pack(metadata):
|
|
|
60
62
|
tags = {k: v for k, v in tags.items() if v is not None}
|
|
61
63
|
fields = {k: v for k, v in fields.items() if v is not None}
|
|
62
64
|
|
|
65
|
+
|
|
66
|
+
# 4. LLM 통계 데이터 추가 (성공한 경우에만)
|
|
67
|
+
if metadata.get('success', False):
|
|
68
|
+
enabled = getattr(conf, 'llm_stat_enabled', False)
|
|
69
|
+
if not enabled:
|
|
70
|
+
return
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
from whatap.counter.counter_manager import CounterMgr
|
|
74
|
+
prompt_tokens = metadata.get('prompt_tokens', 0) or 0
|
|
75
|
+
completion_tokens = metadata.get('completion_tokens', 0) or 0
|
|
76
|
+
model_name = metadata.get('model', 'unknown')
|
|
77
|
+
|
|
78
|
+
# 글로벌 카운터 매니저 인스턴스에서 LLM 태스크 찾아서 업데이트
|
|
79
|
+
if hasattr(CounterMgr, '_instance') and CounterMgr._instance:
|
|
80
|
+
for task in CounterMgr._instance.tasks:
|
|
81
|
+
if hasattr(task, 'update_stats') and task.name() == 'LLMStatTask':
|
|
82
|
+
task.update_stats(prompt_tokens, completion_tokens, model_name)
|
|
83
|
+
break
|
|
84
|
+
except Exception as e:
|
|
85
|
+
pass
|
|
86
|
+
|
|
63
87
|
p = logSinkPack.getLogSinkPack(
|
|
64
88
|
t=DateUtil.now(),
|
|
65
89
|
category="LLMResponse",
|
|
@@ -21,6 +21,7 @@ whatap/control/__init__.py
|
|
|
21
21
|
whatap/counter/__init__.py
|
|
22
22
|
whatap/counter/counter_manager.py
|
|
23
23
|
whatap/counter/tasks/__init__.py
|
|
24
|
+
whatap/counter/tasks/llm_stat.py
|
|
24
25
|
whatap/counter/tasks/openfiledescriptor.py
|
|
25
26
|
whatap/io/__init__.py
|
|
26
27
|
whatap/io/data_inputx.py
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
from whatap.trace.mod.application.wsgi import transfer, trace_handler, \
|
|
2
|
-
interceptor_httpc_request
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def instrument_httpx(module):
|
|
6
|
-
def wrapper(fn):
|
|
7
|
-
@trace_handler(fn)
|
|
8
|
-
def trace(*args, **kwargs):
|
|
9
|
-
request = args[1]
|
|
10
|
-
request.headers = transfer(request.headers)
|
|
11
|
-
|
|
12
|
-
httpc_url = str(request.url)
|
|
13
|
-
callback = interceptor_httpc_request(fn, httpc_url, *args, **kwargs)
|
|
14
|
-
|
|
15
|
-
return callback
|
|
16
|
-
|
|
17
|
-
return trace
|
|
18
|
-
|
|
19
|
-
if hasattr(module, 'Client') and hasattr(module.Client, 'send'):
|
|
20
|
-
module.Client.send = wrapper(module.Client.send)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if hasattr(module, 'AsyncClient') and hasattr(module.AsyncClient, 'send'):
|
|
24
|
-
module.AsyncClient.send = wrapper(module.AsyncClient.send)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/counter/tasks/openfiledescriptor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/cherrypy.py
RENAMED
|
File without changes
|
|
File without changes
|
{whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/django_asgi.py
RENAMED
|
File without changes
|
{whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/django_py3.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap/trace/mod/application/starlette.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{whatap_python-1.8.11.post0 → whatap_python-1.8.13}/whatap_python.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|