whatap-python 1.8.9.post0__tar.gz → 1.8.10__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.

Files changed (147) hide show
  1. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/PKG-INFO +1 -1
  2. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/agent/darwin/amd64/whatap_python +0 -0
  3. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/agent/darwin/arm64/whatap_python +0 -0
  4. whatap_python-1.8.10/whatap/build.py +4 -0
  5. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/wsgi.py +1 -226
  6. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/database/cxoracle.py +2 -2
  7. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/database/mysql.py +2 -3
  8. whatap_python-1.8.10/whatap/trace/mod/database/neo4j.py +90 -0
  9. whatap_python-1.8.9.post0/whatap/trace/mod/database/postgresql.py → whatap_python-1.8.10/whatap/trace/mod/database/psycopg2.py +2 -2
  10. whatap_python-1.8.10/whatap/trace/mod/database/psycopg3.py +251 -0
  11. whatap_python-1.8.9.post0/whatap/trace/mod/database/toolkit.py → whatap_python-1.8.10/whatap/trace/mod/database/sqlalchemy.py +1 -1
  12. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/database/sqlite3.py +2 -2
  13. whatap_python-1.8.10/whatap/trace/mod/database/util.py +494 -0
  14. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/trace_module_definition.py +9 -2
  15. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap_python.egg-info/PKG-INFO +1 -1
  16. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap_python.egg-info/SOURCES.txt +4 -2
  17. whatap_python-1.8.9.post0/whatap/build.py +0 -4
  18. whatap_python-1.8.9.post0/whatap/trace/mod/database/neo4j.py +0 -126
  19. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/README.md +0 -0
  20. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/setup.cfg +0 -0
  21. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/setup.py +0 -0
  22. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/LICENSE +0 -0
  23. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/README.rst +0 -0
  24. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/__init__.py +0 -0
  25. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/__main__.py +0 -0
  26. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/agent/linux/amd64/whatap_python +0 -0
  27. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/agent/linux/arm64/whatap_python +0 -0
  28. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/bootstrap/__init__.py +0 -0
  29. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/bootstrap/sitecustomize.py +0 -0
  30. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/conf/__init__.py +0 -0
  31. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/conf/configuration.py +0 -0
  32. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/conf/configure.py +0 -0
  33. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/conf/license.py +0 -0
  34. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/control/__init__.py +0 -0
  35. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/counter/__init__.py +0 -0
  36. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/counter/counter_manager.py +0 -0
  37. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/counter/tasks/__init__.py +0 -0
  38. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/counter/tasks/openfiledescriptor.py +0 -0
  39. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/io/__init__.py +0 -0
  40. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/io/data_inputx.py +0 -0
  41. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/io/data_outputx.py +0 -0
  42. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/net/__init__.py +0 -0
  43. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/net/async_sender.py +0 -0
  44. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/net/packet_enum.py +0 -0
  45. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/net/packet_type_enum.py +0 -0
  46. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/net/param_def.py +0 -0
  47. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/net/stackhelper.py +0 -0
  48. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/net/udp_session.py +0 -0
  49. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/net/udp_thread.py +0 -0
  50. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/pack/__init__.py +0 -0
  51. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/pack/logSinkPack.py +0 -0
  52. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/pack/pack.py +0 -0
  53. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/pack/pack_enum.py +0 -0
  54. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/pack/tagCountPack.py +0 -0
  55. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/scripts/__init__.py +0 -0
  56. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/__init__.py +0 -0
  57. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/__init__.py +0 -0
  58. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/amqp/__init__.py +0 -0
  59. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/amqp/kombu.py +0 -0
  60. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/amqp/pika.py +0 -0
  61. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/__init__.py +0 -0
  62. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/bottle.py +0 -0
  63. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/celery.py +0 -0
  64. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/cherrypy.py +0 -0
  65. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/django.py +0 -0
  66. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/django_asgi.py +0 -0
  67. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/django_py3.py +0 -0
  68. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/fastapi.py +0 -0
  69. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/flask.py +0 -0
  70. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/frappe.py +0 -0
  71. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/graphql.py +0 -0
  72. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/nameko.py +0 -0
  73. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/odoo.py +0 -0
  74. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/starlette.py +0 -0
  75. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/application/tornado.py +0 -0
  76. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/database/__init__.py +0 -0
  77. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/database/mongo.py +0 -0
  78. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/database/redis.py +0 -0
  79. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/email/__init__.py +0 -0
  80. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/email/smtp.py +0 -0
  81. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/httpc/__init__.py +0 -0
  82. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/httpc/django.py +0 -0
  83. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/httpc/httplib.py +0 -0
  84. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/httpc/httpx.py +0 -0
  85. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/httpc/requests.py +0 -0
  86. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/httpc/urllib3.py +0 -0
  87. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/llm/__init__.py +0 -0
  88. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/llm/openai.py +0 -0
  89. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/logging.py +0 -0
  90. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/plugin.py +0 -0
  91. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/standalone/__init__.py +0 -0
  92. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/standalone/multiple.py +0 -0
  93. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/mod/standalone/single.py +0 -0
  94. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/simple_trace_context.py +0 -0
  95. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/trace_context.py +0 -0
  96. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/trace_context_manager.py +0 -0
  97. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/trace/trace_import.py +0 -0
  98. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/__init__.py +0 -0
  99. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/bit_util.py +0 -0
  100. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/cardinality/__init__.py +0 -0
  101. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/cardinality/hyperloglog.py +0 -0
  102. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/cardinality/murmurhash.py +0 -0
  103. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/cardinality/registerset.py +0 -0
  104. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/compare_util.py +0 -0
  105. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/date_util.py +0 -0
  106. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/debug_util.py +0 -0
  107. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/escape_literal_sql.py +0 -0
  108. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/hash_util.py +0 -0
  109. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/hexa32.py +0 -0
  110. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/int_set.py +0 -0
  111. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/ip_util.py +0 -0
  112. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/keygen.py +0 -0
  113. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/linked_list.py +0 -0
  114. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/linked_map.py +0 -0
  115. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/metering_util.py +0 -0
  116. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/request_double_queue.py +0 -0
  117. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/request_queue.py +0 -0
  118. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/string_util.py +0 -0
  119. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/throttle_util.py +0 -0
  120. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/util/userid_util.py +0 -0
  121. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/__init__.py +0 -0
  122. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/blob_value.py +0 -0
  123. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/boolean_value.py +0 -0
  124. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/decimal_value.py +0 -0
  125. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/double_summary.py +0 -0
  126. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/double_value.py +0 -0
  127. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/float_array.py +0 -0
  128. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/float_value.py +0 -0
  129. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/int_array.py +0 -0
  130. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/ip4_value.py +0 -0
  131. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/list_value.py +0 -0
  132. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/long_array.py +0 -0
  133. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/long_summary.py +0 -0
  134. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/map_value.py +0 -0
  135. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/null_value.py +0 -0
  136. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/number_value.py +0 -0
  137. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/summary_value.py +0 -0
  138. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/text_array.py +0 -0
  139. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/text_hash_value.py +0 -0
  140. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/text_value.py +0 -0
  141. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/value.py +0 -0
  142. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/value/value_enum.py +0 -0
  143. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap/whatap.conf +0 -0
  144. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap_python.egg-info/dependency_links.txt +0 -0
  145. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap_python.egg-info/entry_points.txt +0 -0
  146. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap_python.egg-info/not-zip-safe +0 -0
  147. {whatap_python-1.8.9.post0 → whatap_python-1.8.10}/whatap_python.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: whatap-python
3
- Version: 1.8.9.post0
3
+ Version: 1.8.10
4
4
  Summary: Monitoring and Profiling Service
5
5
  Home-page: https://www.whatap.io
6
6
  Author: whatap
@@ -0,0 +1,4 @@
1
+ app = 'Python'
2
+ name = 'whatap-python'
3
+ version = '1.8.10'
4
+ release_date = '20250821'
@@ -263,6 +263,7 @@ def interceptor_error(status_code, errors, ctx=None):
263
263
 
264
264
 
265
265
  def interceptor_step_error(e, ctx=None):
266
+ from whatap.trace.mod.database.util import extract_db_error_message
266
267
  if not ctx:
267
268
  ctx = TraceContextManager.getLocalContext()
268
269
  if not ctx:
@@ -301,25 +302,6 @@ def interceptor_step_error(e, ctx=None):
301
302
  async_sender.send_packet(PacketTypeEnum.TX_MSG, ctx, datas)
302
303
 
303
304
 
304
- def extract_db_error_message(e):
305
- try:
306
- # PostgreSQL (psycopg2)
307
- if hasattr(e, 'pgcode') and hasattr(e, 'pgerror'):
308
- return str(e.pgerror)
309
-
310
- # MySQL (PyMySQL, mysql-connector-python)
311
- if hasattr(e, 'args') and len(e.args) > 1 and isinstance(e.args[1], str):
312
- return e.args[1]
313
-
314
- # 기본 에러 메시지
315
- if hasattr(e, 'args') and len(e.args) > 0:
316
- if isinstance(e.args[0], str):
317
- return e.args[0]
318
- return str(e.args[0])
319
-
320
- return str(e)
321
- except:
322
- return "Unknown database error"
323
305
 
324
306
 
325
307
  def interceptor_httpc_request(fn, httpc_url, *args, **kwargs):
@@ -385,213 +367,6 @@ def interceptor_sock_connect(fn, *args, **kwargs):
385
367
  ctx.socket_connecting = False
386
368
 
387
369
 
388
- def interceptor_db_con(fn, db_info, *args, **kwargs):
389
- ctx = TraceContextManager.getLocalContext()
390
- if not ctx:
391
- return fn(*args, **kwargs)
392
-
393
- start_time = DateUtil.nowSystem()
394
- ctx.start_time = start_time
395
-
396
- ctx.db_opening = True
397
- try:
398
- callback = fn(*args, **kwargs)
399
- finally:
400
- ctx.db_opening = False
401
-
402
- if not kwargs:
403
- kwargs = dict(
404
- x.split('=') for x in re.sub(r'\s*=\s*', '=', args[0]).split())
405
-
406
- db_type = db_info.get('type')
407
-
408
- if db_type == "sqlite":
409
- text = "sqlite:"
410
- else:
411
- text = '{}://'.format(db_type)
412
- text += kwargs.get('user', '')
413
- text += "@"
414
- text += kwargs.get('host', kwargs.get('dsn', ''))
415
- text += '/'
416
-
417
- text += kwargs.get('database', kwargs.get('db', kwargs.get('dbname', '')))
418
- ctx.active_dbc = text
419
- ctx.lctx['dbc'] = text
420
-
421
- ctx.active_dbc = 0
422
-
423
- datas = [text]
424
- ctx.elapsed = DateUtil.nowSystem() - start_time
425
- async_sender.send_packet(PacketTypeEnum.TX_DB_CONN, ctx, datas)
426
-
427
- return callback
428
-
429
-
430
- def addQuoteDict(arg_dict):
431
- quoted_dict = dict()
432
-
433
- for k, v in arg_dict.items():
434
- if isinstance(v, str):
435
- quoted_dict[k] = "'" + v.replace("'", "\\'") + "'"
436
- else:
437
- quoted_dict[k] = v
438
-
439
- return quoted_dict
440
-
441
-
442
- def addQuoteList(arg_list):
443
- quoted_list = list()
444
-
445
- for v in arg_list:
446
- if isinstance(v, str):
447
- quoted_list.append("'" + v.replace("'", "\\'") + "'")
448
- else:
449
- quoted_list.append("'" + str(v) + "'")
450
-
451
- return tuple(quoted_list)
452
-
453
- def neo4jQuery(query,paremeter):
454
- neo4j_query = query
455
-
456
- for key, value in paremeter.items():
457
- placeholder = f"${key}"
458
- replacement = f"'{str(value)}'"
459
- neo4j_query = neo4j_query.replace(placeholder, replacement)
460
-
461
- return neo4j_query
462
-
463
- def sqliteQuery(query, paremeter):
464
- sqlite_query = query
465
-
466
- def quote(v):
467
- if v is None: return "NULL"
468
- if isinstance(v, (bytes, bytearray)): return "X'" + v.hex() + "'"
469
- return "'" + str(v).replace("'", "''") + "'"
470
-
471
- # 이름 기반: :name / @name / $name (단일 세트)
472
- if isinstance(paremeter, dict):
473
- for pfx in (':', '@', '$'):
474
- for k, v in paremeter.items():
475
- sqlite_query = sqlite_query.replace(f"{pfx}{k}", quote(v))
476
- return sqlite_query
477
-
478
- # 포지셔널 + executemany 분기
479
- if isinstance(paremeter, (list, tuple)):
480
- # ── executemany: [tuple|dict, ...] ──
481
- if isinstance(paremeter, list) and paremeter and isinstance(paremeter[0], (tuple, dict)):
482
- stmts = []
483
- for params in paremeter:
484
- sqlite_query = query
485
- if isinstance(params, dict):
486
- for pfx in (':', '@', '$'):
487
- for k, v in params.items():
488
- sqlite_query = sqlite_query.replace(f"{pfx}{k}", quote(v))
489
- else: # tuple
490
- for i, v in enumerate(params, 1):
491
- sqlite_query = sqlite_query.replace(f"?{i}", quote(v))
492
- for v in params:
493
- sqlite_query = sqlite_query.replace('?', quote(v), 1)
494
- stmts.append(sqlite_query)
495
- return ";\n".join(stmts)
496
-
497
- # ── 단일 포지셔널 세트 (tuple 또는 스칼라 list) ──
498
- seq = paremeter if isinstance(paremeter, tuple) else tuple(paremeter)
499
- for i, v in enumerate(seq, 1):
500
- sqlite_query = sqlite_query.replace(f"?{i}", quote(v))
501
- for v in seq:
502
- sqlite_query = sqlite_query.replace('?', quote(v), 1)
503
- return sqlite_query
504
-
505
- return sqlite_query
506
-
507
- def interceptor_db_execute(fn, db_info, *args, **kwargs):
508
- ctx = TraceContextManager.getLocalContext()
509
- # sendDebugProfile(ctx, 'interceptor_db_execute step -1')
510
- self = args[0]
511
- db_type = db_info.get('type')
512
- query = None
513
-
514
- if db_type == "neo4j":
515
- try:
516
- query = neo4jQuery(args[1], kwargs)
517
- except Exception as e:
518
- pass
519
-
520
- elif db_type == "sqlite" and len(args) > 2:
521
- try:
522
- query = sqliteQuery(args[1],args[2])
523
- except Exception as e:
524
- pass
525
-
526
- else:
527
- if len(args) > 2 and type(args[2]) == dict and args[2]:
528
- try:
529
- query = args[1] % addQuoteDict(args[2])
530
- except Exception as e:
531
- pass
532
- if len(args) > 2 and type(args[2]) in (list, tuple) and args[2]:
533
- try:
534
- query = args[1] % addQuoteList(args[2])
535
- except Exception as e:
536
- pass
537
- try:
538
- if not query:
539
- query = args[1].decode()
540
- except Exception as e:
541
- query = args[1]
542
-
543
- if not query:
544
- return fn(*args, **kwargs)
545
-
546
- start_time = DateUtil.nowSystem()
547
- ctx.start_time = start_time
548
- ctx.active_sqlhash = query
549
- try:
550
- callback = fn(*args, **kwargs)
551
- return callback
552
- except Exception as e:
553
- interceptor_step_error(e)
554
- finally:
555
- datas = [ctx.lctx.get('dbc', ''), query, str(self.rowcount)]
556
- ctx.elapsed = DateUtil.nowSystem() - start_time
557
- async_sender.send_packet(PacketTypeEnum.TX_SQL, ctx, datas)
558
- count = self.rowcount
559
-
560
- if (count is not None) and (count > -1):
561
- desc = '{0}: {1}'.format('Fetch count', count)
562
- datas = [' ', ' ', desc]
563
- ctx.elapsed = 0
564
- async_sender.send_packet(PacketTypeEnum.TX_MSG, ctx, datas)
565
-
566
- ctx.active_sqlhash = 0
567
-
568
-
569
- def interceptor_db_close(fn, *args, **kwargs):
570
- ctx = TraceContextManager.getLocalContext()
571
- ctx.db_opening = False
572
-
573
- if not conf.profile_dbc_close:
574
- try:
575
- return fn(*args, **kwargs)
576
- except Exception as e:
577
- interceptor_step_error(e)
578
- finally:
579
- return
580
- start_time = DateUtil.nowSystem()
581
- ctx.start_time = start_time
582
-
583
- try:
584
- callback = fn(*args, **kwargs)
585
- return callback
586
- except Exception as e:
587
- interceptor_step_error(e)
588
- finally:
589
- text = 'DB: Close Connection.'
590
- datas = [' ', ' ', text]
591
- ctx.elapsed = DateUtil.nowSystem() - start_time
592
- async_sender.send_packet(PacketTypeEnum.TX_MSG, ctx, datas)
593
-
594
-
595
370
  check_seq = 1
596
371
 
597
372
 
@@ -1,6 +1,6 @@
1
1
  from whatap.trace import get_dict
2
- from whatap.trace.mod.application.wsgi import trace_handler, \
3
- interceptor_db_con, interceptor_db_execute, interceptor_db_close
2
+ from whatap.trace.mod.application.wsgi import trace_handler
3
+ from whatap.trace.mod.database.util import interceptor_db_con, interceptor_db_execute, interceptor_db_close
4
4
 
5
5
  db_info = {}
6
6
 
@@ -1,7 +1,6 @@
1
1
  from whatap.trace import get_dict
2
- from whatap.trace.mod.application.wsgi import trace_handler, \
3
- interceptor_db_con, interceptor_db_execute, interceptor_db_close
4
-
2
+ from whatap.trace.mod.application.wsgi import trace_handler
3
+ from whatap.trace.mod.database.util import interceptor_db_con, interceptor_db_execute, interceptor_db_close
5
4
  db_info = {}
6
5
 
7
6
  def instrument_MySQLdb(module):
@@ -0,0 +1,90 @@
1
+ from whatap.trace.mod.application.wsgi import trace_handler
2
+ from whatap.trace.mod.database.util import interceptor_db_con, interceptor_db_execute, interceptor_db_close
3
+
4
+ db_info = {}
5
+
6
+
7
+
8
+
9
+
10
+ def instrument_neo4j(module):
11
+
12
+ if hasattr(module, 'GraphDatabase'):
13
+ orig_driver = module.GraphDatabase.driver
14
+ def wrapper(fn):
15
+ @trace_handler(fn)
16
+ def trace(*args, **kwargs):
17
+ db_info = {'type': 'neo4j'}
18
+
19
+ if args:
20
+ db_info['uri'] = args[0]
21
+
22
+ auth = kwargs.get('auth') or (args[1] if len(args) > 1 else None)
23
+ if auth:
24
+ user = getattr(auth, 'principal', None) or (auth[0] if isinstance(auth, tuple) else None)
25
+ if user:
26
+ db_info['user'] = user
27
+
28
+ callback = interceptor_db_con(fn, db_info, *args, **kwargs)
29
+ return callback
30
+
31
+ return trace
32
+ module.GraphDatabase.driver = wrapper(orig_driver)
33
+
34
+
35
+
36
+ if hasattr(module, 'Driver'):
37
+ orig_driver_close = module.Driver.close
38
+ def wrapper(fn):
39
+ @trace_handler(fn)
40
+ def trace(driver, *args, **kwargs):
41
+ callback = interceptor_db_close(fn, driver, *args, **kwargs)
42
+ return callback
43
+
44
+ return trace
45
+
46
+ module.Driver.close = wrapper(orig_driver_close)
47
+
48
+ orig = module.Session.run
49
+ def wrapper(fn):
50
+ @trace_handler(fn)
51
+ def trace(session, *args, **kwargs):
52
+ db_info = {'type': 'neo4j'}
53
+ try:
54
+ setattr(session, 'rowcount', -1)
55
+ except Exception as e:
56
+ raise e
57
+ callback = interceptor_db_execute(fn, db_info, session, *args, **kwargs)
58
+
59
+ return callback
60
+ return trace
61
+ module.Session.run = wrapper(orig)
62
+
63
+ def wrapper(fn):
64
+ @trace_handler(fn)
65
+ def trace(tx, *args, **kwargs):
66
+ session = None
67
+ try:
68
+ session = tx._on_closed.__self__
69
+ except AttributeError:
70
+ return fn(tx, *args, **kwargs)
71
+ db_info = {'type': 'neo4j'}
72
+ try:
73
+ setattr(tx, 'rowcount', -1)
74
+ except Exception:
75
+ pass
76
+ callback = interceptor_db_execute(fn, db_info, tx, *args, **kwargs)
77
+ return callback
78
+
79
+ return trace
80
+
81
+ tx_classes_to_patch = ['Transaction', 'ManagedTransaction', 'BoltTransaction']
82
+ for class_name in tx_classes_to_patch:
83
+ if hasattr(module, class_name):
84
+ TxClass = getattr(module, class_name)
85
+ if hasattr(TxClass, 'run'):
86
+ original_run = getattr(TxClass, 'run')
87
+ setattr(TxClass, 'run', wrapper(original_run))
88
+
89
+
90
+
@@ -1,6 +1,6 @@
1
1
  from whatap.trace import get_dict
2
- from whatap.trace.mod.application.wsgi import trace_handler, \
3
- interceptor_db_con, interceptor_db_execute, interceptor_db_close
2
+ from whatap.trace.mod.application.wsgi import trace_handler
3
+ from whatap.trace.mod.database.util import interceptor_db_con, interceptor_db_execute, interceptor_db_close
4
4
 
5
5
  db_info = {}
6
6
 
@@ -0,0 +1,251 @@
1
+ from whatap.trace.mod.application.wsgi import trace_handler
2
+ from whatap.trace.mod.database.util import (
3
+ interceptor_db_con, interceptor_db_execute, interceptor_db_close,
4
+ async_interceptor_db_con, async_interceptor_db_execute, async_interceptor_db_close
5
+ )
6
+
7
+ db_info = {}
8
+
9
+
10
+ class BaseCursor:
11
+ def __init__(self, cursor, db_info):
12
+ self._cursor = cursor
13
+ self._db_info = db_info
14
+
15
+ def __getattr__(self, name):
16
+ return getattr(self._cursor, name)
17
+
18
+ def __setattr__(self, name, value):
19
+ if name.startswith('_'):
20
+ object.__setattr__(self, name, value)
21
+ else:
22
+ setattr(self._cursor, name, value)
23
+
24
+ @property
25
+ def connection(self):
26
+ return self._cursor.connection
27
+
28
+ def _execute_wrapper(self, original_execute_method):
29
+ owner = getattr(original_execute_method, "__self__", None)
30
+
31
+ def safe_execute(*args, **kwargs):
32
+ if args and owner is not None and args[0] is owner:
33
+ args = args[1:]
34
+ return original_execute_method(*args, **kwargs)
35
+
36
+ return safe_execute
37
+
38
+
39
+ class SyncCursor(BaseCursor):
40
+ def __enter__(self):
41
+ self._cursor.__enter__()
42
+ return self
43
+
44
+ def __exit__(self, exc_type, exc_val, exc_tb):
45
+ return self._cursor.__exit__(exc_type, exc_val, exc_tb)
46
+
47
+ def execute(self, *args, **kwargs):
48
+ real_execute = self._cursor.execute
49
+ safe_fn = self._execute_wrapper(real_execute)
50
+
51
+ callback = interceptor_db_execute(safe_fn,self._db_info,self._cursor,*args,**kwargs)
52
+
53
+ return callback
54
+
55
+ def executemany(self, *args, **kwargs):
56
+ real_executemany = getattr(self._cursor, "executemany", None)
57
+
58
+ if real_executemany is None:
59
+ return self._cursor.executemany(*args, **kwargs)
60
+
61
+ safe_fn = self._execute_wrapper(real_executemany)
62
+
63
+ callback = interceptor_db_execute(safe_fn,self._db_info,self._cursor,*args,**kwargs)
64
+
65
+ return callback
66
+
67
+
68
+ class AsyncCursor(BaseCursor):
69
+
70
+ async def __aenter__(self):
71
+ await self._cursor.__aenter__()
72
+ return self
73
+
74
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
75
+ return await self._cursor.__aexit__(exc_type, exc_val, exc_tb)
76
+
77
+ def _async_execute_wrapper(self, original_execute_method):
78
+ owner = getattr(original_execute_method, "__self__", None)
79
+
80
+ async def async_safe_execute(*args, **kwargs):
81
+ if args and owner is not None and args[0] is owner:
82
+ args = args[1:]
83
+ return await original_execute_method(*args, **kwargs)
84
+
85
+ return async_safe_execute
86
+
87
+ async def execute(self, *args, **kwargs):
88
+ real_execute = self._cursor.execute
89
+ safe_fn = self._async_execute_wrapper(real_execute)
90
+
91
+
92
+ callback = await async_interceptor_db_execute(safe_fn,self._db_info,self._cursor,*args,**kwargs)
93
+
94
+ return callback
95
+
96
+ async def executemany(self, *args, **kwargs):
97
+ real_executemany = getattr(self._cursor, "executemany", None)
98
+
99
+ if real_executemany is None:
100
+ return await self._cursor.executemany(*args, **kwargs)
101
+
102
+ safe_fn = self._async_execute_wrapper(real_executemany)
103
+
104
+ callback = await async_interceptor_db_execute(safe_fn,self._db_info,self._cursor,*args,**kwargs)
105
+ return callback
106
+
107
+
108
+ class BaseConnection:
109
+ def __init__(self, connection, db_info):
110
+ self._connection = connection
111
+ self._db_info = db_info
112
+
113
+ def __getattr__(self, name):
114
+ return getattr(self._connection, name)
115
+
116
+ def __setattr__(self, name, value):
117
+ if name.startswith('_'):
118
+ object.__setattr__(self, name, value)
119
+ else:
120
+ setattr(self._connection, name, value)
121
+
122
+ def _execute_wrapper(self, original_execute_method):
123
+ owner = getattr(original_execute_method, "__self__", None)
124
+
125
+ def safe_execute(*args, **kwargs):
126
+ if args and owner is not None and args[0] is owner:
127
+ args = args[1:]
128
+ return original_execute_method(*args, **kwargs)
129
+
130
+ return safe_execute
131
+
132
+ def close(self, *args, **kwargs):
133
+ real_close = self._connection.close
134
+
135
+ callback = interceptor_db_close(real_close, *args, **kwargs)
136
+ return callback
137
+
138
+
139
+ class SyncConnection(BaseConnection):
140
+
141
+ def __enter__(self):
142
+ self._connection.__enter__()
143
+ return self
144
+
145
+ def __exit__(self, exc_type, exc_val, exc_tb):
146
+ return self._connection.__exit__(exc_type, exc_val, exc_tb)
147
+
148
+ def cursor(self, *args, **kwargs):
149
+ real_cursor = self._connection.cursor(*args, **kwargs)
150
+ return SyncCursor(real_cursor, self._db_info)
151
+
152
+ def execute(self, *args, **kwargs):
153
+ real_execute = getattr(self._connection, "execute", None)
154
+
155
+ if real_execute is None:
156
+ return self._connection.execute(*args, **kwargs)
157
+
158
+ safe_fn = self._execute_wrapper(real_execute)
159
+
160
+ callback = interceptor_db_execute(safe_fn,self._db_info,self._cursor,*args,**kwargs)
161
+
162
+ return callback
163
+
164
+
165
+ class AsyncConnection(BaseConnection):
166
+
167
+ async def __aenter__(self):
168
+ await self._connection.__aenter__()
169
+ return self
170
+
171
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
172
+ return await self._connection.__aexit__(exc_type, exc_val, exc_tb)
173
+
174
+ def cursor(self, *args, **kwargs):
175
+ real_cursor = self._connection.cursor(*args, **kwargs)
176
+ return AsyncCursor(real_cursor, self._db_info)
177
+
178
+ def _async_execute_wrapper(self, original_execute_method):
179
+ owner = getattr(original_execute_method, "__self__", None)
180
+
181
+ async def async_safe_execute(*args, **kwargs):
182
+ if args and owner is not None and args[0] is owner:
183
+ args = args[1:]
184
+ return await original_execute_method(*args, **kwargs)
185
+
186
+ return async_safe_execute
187
+
188
+ async def execute(self, *args, **kwargs):
189
+ real_execute = getattr(self._connection, "execute", None)
190
+
191
+ if real_execute is None:
192
+ return await self._connection.execute(*args, **kwargs)
193
+
194
+ safe_fn = self._async_execute_wrapper(real_execute)
195
+
196
+ callback = await async_interceptor_db_execute(safe_fn,self._db_info,self._connection,*args,**kwargs)
197
+
198
+ return callback
199
+
200
+ async def close(self, *args, **kwargs):
201
+ real_close = self._connection.close
202
+
203
+ callback = await async_interceptor_db_close(real_close, *args, **kwargs)
204
+
205
+ return callback
206
+
207
+
208
+ def _sync_wrapper(fn):
209
+
210
+ @trace_handler(fn)
211
+ def wrapper(*args, **kwargs):
212
+ global db_info
213
+
214
+ db_info = {"type": "postgresql"}
215
+ db_info.update(kwargs)
216
+
217
+ connection = interceptor_db_con(fn, db_info, *args, **kwargs)
218
+
219
+ return SyncConnection(connection, dict(db_info))
220
+
221
+ return wrapper
222
+
223
+
224
+ def _async_wrapper(fn):
225
+
226
+ @trace_handler(fn)
227
+ async def wrapper(*args, **kwargs):
228
+ global db_info
229
+
230
+ db_info = {"type": "postgresql"}
231
+ db_info.update(kwargs)
232
+
233
+ connection = await async_interceptor_db_con(fn,db_info,*args,**kwargs)
234
+
235
+ return AsyncConnection(connection, dict(db_info))
236
+
237
+ return wrapper
238
+
239
+
240
+ def instrument_psycopg3(module):
241
+ original_connect = module.connect
242
+
243
+ module.connect = _sync_wrapper(original_connect)
244
+
245
+ if hasattr(module, 'AsyncConnection'):
246
+ async_conn = module.AsyncConnection
247
+
248
+ if hasattr(async_conn, 'connect'):
249
+ original_async_connect = async_conn.connect
250
+ async_conn.connect = _async_wrapper(original_async_connect)
251
+
@@ -1,6 +1,6 @@
1
1
  from whatap.net.packet_type_enum import PacketTypeEnum
2
2
  import whatap.net.async_sender as async_sender
3
- from whatap.trace.mod.application.wsgi import trace_handler, interceptor_db_execute, interceptor_step_error, sendDebugProfile
3
+ from whatap.trace.mod.application.wsgi import trace_handler, interceptor_step_error, sendDebugProfile
4
4
  from whatap.util.date_util import DateUtil
5
5
  from whatap.trace.trace_context_manager import TraceContextManager
6
6
  import sys
@@ -1,5 +1,5 @@
1
- from whatap.trace.mod.application.wsgi import trace_handler, \
2
- interceptor_db_con, interceptor_db_execute, interceptor_db_close
1
+ from whatap.trace.mod.application.wsgi import trace_handler
2
+ from whatap.trace.mod.database.util import interceptor_db_con, interceptor_db_execute, interceptor_db_close
3
3
 
4
4
  class CursorProxy:
5
5
  def __init__(self, real_cursor, db_info):