whatap-python 2.1.2__tar.gz → 2.1.3rc1__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.
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/PKG-INFO +1 -1
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/__init__.py +105 -2
- whatap_python-2.1.3rc1/whatap/build.py +4 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/conf/configuration.py +4 -0
- whatap_python-2.1.3rc1/whatap/trace/mod/application/odoo.py +77 -0
- whatap_python-2.1.3rc1/whatap/trace/mod/hook_service_patterns.py +72 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/trace_context_manager.py +11 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/trace_import.py +5 -1
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/trace_module_definition.py +1 -1
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap_python.egg-info/PKG-INFO +1 -1
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap_python.egg-info/SOURCES.txt +1 -0
- whatap_python-2.1.2/whatap/build.py +0 -4
- whatap_python-2.1.2/whatap/trace/mod/application/odoo.py +0 -63
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/README.md +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/pyproject.toml +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/setup.cfg +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/setup.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/tests/test_stream_ttft.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/LICENSE +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/README.rst +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/__main__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/agent/darwin/amd64/whatap_python +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/agent/darwin/arm64/whatap_python +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/agent/linux/amd64/whatap_python +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/agent/linux/arm64/whatap_python +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/agent/windows/whatap_python.exe +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/bootstrap/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/bootstrap/sitecustomize.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/conf/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/conf/configure.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/conf/license.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/control/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/counter/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/counter/counter_manager.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/counter/tasks/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/counter/tasks/base_task.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/counter/tasks/llm_evaluator_task.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/counter/tasks/llm_log_sink_task.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/counter/tasks/llm_stat_task.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/counter/tasks/openfiledescriptor.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/io/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/io/data_inputx.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/io/data_outputx.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/definitions.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/base.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/answer_relevance.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/combined_judge.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/factuality.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/hallucination.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/llm_judge.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/pii_leak.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/prompt_injection.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/toxicity.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/url_scan.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/registry.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/sampler.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/scope.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/features.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_input_message.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_log_sink_pack.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_output_message.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_step_eval_status.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_step_status.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_system_message.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_tool_calls.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_tool_results.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_tx_status.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/pricing.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/prompt_meta.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/anthropic/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/anthropic/messages/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/anthropic/messages/messages.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/anthropic/messages/messages_context.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/anthropic/messages/messages_extractor.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/interceptor.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/chat/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/chat/chat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/chat/chat_context.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/chat/chat_extractor.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/completions/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/completions/completions.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/completions/completions_context.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/completions/completions_extractor.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/content_parser.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/embeddings/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/embeddings/embeddings.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/embeddings/embeddings_context.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/embeddings/embeddings_extractor.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/responses/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/responses/responses.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/responses/responses_context.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/responses/responses_extractor.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/stream_accumulator.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/active_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/answer_relevance_eval_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/api_status_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/base_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/combined_judge_eval_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/error_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/eval_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/factuality_eval_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/feature_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/finish_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/hallucination_eval_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/meter.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/perf_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/pii_leak_eval_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/prompt_injection_eval_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/token_usage_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/toxicity_eval_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/stats/url_scan_eval_stat.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/net/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/net/async_sender.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/net/packet_enum.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/net/packet_type_enum.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/net/param_def.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/net/stackhelper.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/net/udp_session.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/net/udp_thread.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/pack/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/pack/logSinkPack.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/pack/pack.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/pack/pack_enum.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/pack/tagCountPack.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/scripts/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/amqp/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/amqp/kombu.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/amqp/pika.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/bottle.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/celery.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/cherrypy.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/django.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/django_asgi.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/django_py3.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/fastapi/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/fastapi/endpoint.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/fastapi/exception_log.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/fastapi/instrumentation.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/fastapi/scope.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/fastapi/transaction.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/flask.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/frappe.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/graphql.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/nameko.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/starlette.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/tornado.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/application/wsgi.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/database/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/database/cxoracle.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/database/mongo.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/database/mysql.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/database/neo4j.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/database/psycopg2.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/database/psycopg3.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/database/redis.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/database/sqlalchemy.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/database/sqlite3.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/database/util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/email/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/email/smtp.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/httpc/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/httpc/django.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/httpc/httplib.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/httpc/httpx.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/httpc/requests.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/httpc/urllib3.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/httpc/util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/logging.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/plugin.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/standalone/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/standalone/multiple.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/mod/standalone/single.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/simple_trace_context.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/trace_context.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/trace_error.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/trace/trace_handler.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/bit_util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/cardinality/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/cardinality/hyperloglog.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/cardinality/murmurhash.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/cardinality/registerset.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/compare_util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/date_util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/debug_util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/escape_literal_sql.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/frame_util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/hash_util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/hexa32.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/int_set.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/ip_util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/keygen.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/linked_list.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/linked_map.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/metering_util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/request_double_queue.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/request_queue.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/string_util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/throttle_util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/util/userid_util.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/__init__.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/blob_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/boolean_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/decimal_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/double_summary.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/double_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/float_array.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/float_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/int_array.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/ip4_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/list_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/long_array.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/long_summary.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/map_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/null_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/number_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/summary_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/text_array.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/text_hash_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/text_value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/value.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/value/value_enum.py +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/whatap.conf +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap_python.egg-info/dependency_links.txt +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap_python.egg-info/entry_points.txt +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap_python.egg-info/not-zip-safe +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap_python.egg-info/requires.txt +0 -0
- {whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap_python.egg-info/top_level.txt +0 -0
|
@@ -389,6 +389,25 @@ def hooks(home):
|
|
|
389
389
|
'mod',
|
|
390
390
|
key)}
|
|
391
391
|
|
|
392
|
+
# 서비스(트랜잭션) 진입점 자동 래핑 (conf 방법). hook_method_patterns 와 같은
|
|
393
|
+
# import-hook 플러밍, 래퍼만 트랜잭션 open/close (whatap.trace.mod.hook_service_patterns).
|
|
394
|
+
# @method_profiling 을 소스 수정 없이 conf 로 적용하는 경로.
|
|
395
|
+
if conf.hook_service_patterns:
|
|
396
|
+
for pattern in conf.hook_service_patterns.split(','):
|
|
397
|
+
pattern = pattern.strip()
|
|
398
|
+
if not pattern or ':' not in pattern:
|
|
399
|
+
continue
|
|
400
|
+
module_name, class_def = pattern.split(':', 1)
|
|
401
|
+
module_name = module_name.strip()
|
|
402
|
+
class_def = class_def.strip()
|
|
403
|
+
if not PLUGIN.get(module_name):
|
|
404
|
+
PLUGIN[module_name] = []
|
|
405
|
+
PLUGIN[module_name].append(class_def)
|
|
406
|
+
# 대상 모듈이 PLUGIN 에 등록되면 ImportFinder 가 class_defs 패키징.
|
|
407
|
+
IMPORT_HOOKS[module_name] = {
|
|
408
|
+
'def': 'instrument_service',
|
|
409
|
+
'module': 'whatap.trace.mod.hook_service_patterns'}
|
|
410
|
+
|
|
392
411
|
if conf.standalone_enabled:
|
|
393
412
|
if conf.standalone_type == 'multiple-transaction':
|
|
394
413
|
from whatap.trace.mod.standalone.multiple import instrument_standalone_multiple
|
|
@@ -644,6 +663,7 @@ def go(batch=False, opts={}, llm=False):
|
|
|
644
663
|
|
|
645
664
|
|
|
646
665
|
import signal
|
|
666
|
+
import functools
|
|
647
667
|
|
|
648
668
|
from whatap.trace.trace_handler import trace_handler
|
|
649
669
|
from whatap.trace.trace_error import interceptor_step_error
|
|
@@ -671,7 +691,90 @@ def register_app(fn):
|
|
|
671
691
|
return trace
|
|
672
692
|
|
|
673
693
|
|
|
694
|
+
def _service_trace(fn, service_name=None):
|
|
695
|
+
"""fn 을 하나의 트랜잭션(TX_START~TX_END)으로 감싼 래퍼를 반환한다.
|
|
696
|
+
|
|
697
|
+
``@method_profiling`` 데코레이터와 conf ``hook_service_patterns``
|
|
698
|
+
(whatap.trace.mod.hook_service_patterns) 의 **공용 코어**. 여기엔 agent() 부팅이
|
|
699
|
+
없다 (데코레이터/부트 경로가 각자 처리).
|
|
700
|
+
|
|
701
|
+
코루틴 함수는 동기 래퍼로 감싸면 트랜잭션이 start_interceptor → 코루틴 생성 →
|
|
702
|
+
end_interceptor 로 즉시 열렸다 닫히고, 실제 본문은 호출자가 await 할 때 트랜잭션
|
|
703
|
+
밖에서 실행된다. async def 래퍼로 await 경계 안에서 트랜잭션을 열고 닫는다.
|
|
704
|
+
"""
|
|
705
|
+
import inspect
|
|
706
|
+
|
|
707
|
+
name = service_name or fn.__name__
|
|
708
|
+
|
|
709
|
+
# 트랜잭션 종료 후 컨텍스트 정리. end_interceptor 는 TX_END 패킷만 보내고
|
|
710
|
+
# entry 맵/로컬 컨텍스트를 비우지 않는다(프레임워크 훅은 별도로 end 를 호출함).
|
|
711
|
+
# 스스로 트랜잭션을 열고 닫으므로 여기서 직접 정리한다:
|
|
712
|
+
# - entry 맵에서 제거(안 하면 활성 트랜잭션 카운트/메모리 누수)
|
|
713
|
+
# - 부모가 있으면(중첩 호출) 복원, 없으면(루트) 로컬 컨텍스트 클리어
|
|
714
|
+
# (안 하면 종료된 ctx 를 계속 가리켜 이후 스텝이 죽은 트랜잭션에 붙음)
|
|
715
|
+
def _finish(ctx, parent):
|
|
716
|
+
try:
|
|
717
|
+
end_interceptor(ctx=ctx)
|
|
718
|
+
if ctx:
|
|
719
|
+
TraceContextManager.end(ctx.id)
|
|
720
|
+
finally:
|
|
721
|
+
if parent:
|
|
722
|
+
TraceContextManager.setLocalContext(parent)
|
|
723
|
+
else:
|
|
724
|
+
TraceContextManager.clearLocalContext()
|
|
725
|
+
|
|
726
|
+
# 감싼 함수의 예외는 기록만 하고 반드시 다시 던진다. 과거엔 예외를 삼키고 None 을
|
|
727
|
+
# 반환해, 호출자가 예외로 에러를 판별하는 코드(예: ASGI 핸들러가 500 을 내보내는 경로)
|
|
728
|
+
# 를 망가뜨렸다(200 + null 응답). 계측 기록 자체가 실패해도 원본 예외를 가리지 않도록
|
|
729
|
+
# 기록부는 감싼다. finally 에서 return 하면 예외가 억제되므로 정리만 한다.
|
|
730
|
+
def _record_error(ctx, e, args, kwargs):
|
|
731
|
+
try:
|
|
732
|
+
interceptor_step_error(e, ctx=ctx)
|
|
733
|
+
if ctx:
|
|
734
|
+
interceptor_error_log(ctx.id, e, fn, args, kwargs)
|
|
735
|
+
logging.debug('WHATAP(@method_profiling): ' + str(e),
|
|
736
|
+
extra={'id': 'WA776'}, exc_info=True)
|
|
737
|
+
except Exception:
|
|
738
|
+
pass
|
|
739
|
+
|
|
740
|
+
if inspect.iscoroutinefunction(fn):
|
|
741
|
+
@functools.wraps(fn)
|
|
742
|
+
async def trace(*args, **kwargs):
|
|
743
|
+
parent = TraceContextManager.getLocalContext()
|
|
744
|
+
ctx = TraceContext()
|
|
745
|
+
try:
|
|
746
|
+
ctx.service_name = name
|
|
747
|
+
start_interceptor(ctx)
|
|
748
|
+
return await fn(*args, **kwargs)
|
|
749
|
+
except Exception as e:
|
|
750
|
+
_record_error(ctx, e, args, kwargs)
|
|
751
|
+
raise
|
|
752
|
+
finally:
|
|
753
|
+
_finish(ctx, parent)
|
|
754
|
+
|
|
755
|
+
return trace
|
|
756
|
+
|
|
757
|
+
@functools.wraps(fn)
|
|
758
|
+
def trace(*args, **kwargs):
|
|
759
|
+
parent = TraceContextManager.getLocalContext()
|
|
760
|
+
ctx = TraceContext()
|
|
761
|
+
try:
|
|
762
|
+
ctx.service_name = name
|
|
763
|
+
start_interceptor(ctx)
|
|
764
|
+
return fn(*args, **kwargs)
|
|
765
|
+
except Exception as e:
|
|
766
|
+
_record_error(ctx, e, args, kwargs)
|
|
767
|
+
raise
|
|
768
|
+
finally:
|
|
769
|
+
_finish(ctx, parent)
|
|
770
|
+
|
|
771
|
+
return trace
|
|
772
|
+
|
|
773
|
+
|
|
674
774
|
def method_profiling(fn):
|
|
775
|
+
# NOTE: 의도적으로 _service_trace 를 쓰지 않는다. 이 데코레이터는 이미 배포된
|
|
776
|
+
# 공개 API 라, 예외 재전파/컨텍스트 정리/async 지원으로 바꾸면 기존 사용자의
|
|
777
|
+
# 동작이 달라진다. 해당 수정은 dev 에 있고 정식 머지 때 함께 들어온다.
|
|
675
778
|
def trace(*args, **kwargs):
|
|
676
779
|
callback = None
|
|
677
780
|
try:
|
|
@@ -689,10 +792,10 @@ def method_profiling(fn):
|
|
|
689
792
|
ctx = TraceContextManager.getLocalContext()
|
|
690
793
|
end_interceptor(ctx=ctx)
|
|
691
794
|
return callback
|
|
692
|
-
|
|
795
|
+
|
|
693
796
|
if not os.environ.get('whatap.enabled'):
|
|
694
797
|
agent()
|
|
695
|
-
|
|
798
|
+
|
|
696
799
|
return trace
|
|
697
800
|
|
|
698
801
|
|
|
@@ -37,6 +37,10 @@ Configuration = {
|
|
|
37
37
|
"profile_http_parameter_enabled": False,
|
|
38
38
|
"profile_sql_param_enabled": False,
|
|
39
39
|
"hook_method_patterns": "",
|
|
40
|
+
# 트랜잭션(서비스) 진입점으로 자동 래핑할 메서드 패턴 (module:Class.method, 콤마 구분).
|
|
41
|
+
# 해당 메서드 호출이 하나의 트랜잭션이 된다(= @method_profiling 의 conf 버전).
|
|
42
|
+
# 프레임워크 자동계측이 안 되는 진입점용. hook_service_patterns 모듈 참조.
|
|
43
|
+
"hook_service_patterns": "",
|
|
40
44
|
|
|
41
45
|
"mtrace_rate": 10,
|
|
42
46
|
"mtrace_spec": '',
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import traceback
|
|
2
|
+
from whatap import logging
|
|
3
|
+
from whatap.trace.trace_handler import trace_handler
|
|
4
|
+
from whatap.trace.trace_error import interceptor_error
|
|
5
|
+
from whatap.trace.mod.application.wsgi import interceptor
|
|
6
|
+
from whatap.trace.trace_context_manager import TraceContextManager
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def instrument(module):
|
|
10
|
+
# module is odoo.http (hooked as 'odoo.http' so that `root`/`HttpDispatcher`
|
|
11
|
+
# already exist when the hook fires; on Odoo 18+ `odoo.http` is no longer
|
|
12
|
+
# imported during `import odoo`, so hooking the top-level package fired too
|
|
13
|
+
# early and silently failed).
|
|
14
|
+
root = module.root
|
|
15
|
+
AppClass = root.__class__
|
|
16
|
+
original_call = AppClass.__call__
|
|
17
|
+
|
|
18
|
+
def wrapper(fn):
|
|
19
|
+
@trace_handler(fn, True)
|
|
20
|
+
def trace(self, environ, start_response):
|
|
21
|
+
def custom_start_response(status, headers, exc_info=None):
|
|
22
|
+
ctx = TraceContextManager.getLocalContext()
|
|
23
|
+
try:
|
|
24
|
+
ctx.status = int(status.split()[0])
|
|
25
|
+
except Exception as e:
|
|
26
|
+
logging.warning('[ODOO] status parse failed: %s' % e, extra={'id': 'ODOO001'})
|
|
27
|
+
ctx.status = 0
|
|
28
|
+
return start_response(status, headers, exc_info)
|
|
29
|
+
try:
|
|
30
|
+
callback = interceptor(fn, self, environ, custom_start_response)
|
|
31
|
+
except Exception as e:
|
|
32
|
+
interceptor_error(
|
|
33
|
+
500 , #해당 status 값은 에러 처리용으로만 사용됩니다.
|
|
34
|
+
[e.__class__.__name__, str(e)]
|
|
35
|
+
)
|
|
36
|
+
raise
|
|
37
|
+
return callback
|
|
38
|
+
|
|
39
|
+
return trace
|
|
40
|
+
|
|
41
|
+
AppClass.__call__ = wrapper(original_call)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
HTTP 요청 경로의 예외 단일 처리 지점을 후킹한다.
|
|
46
|
+
- Odoo 16+ : HttpDispatcher.handle_error(self, exc)
|
|
47
|
+
- Odoo 14/15 : HttpRequest._handle_exception(self, exception)
|
|
48
|
+
(dispatcher 구조 도입 이전이라 HttpDispatcher 가 없다.
|
|
49
|
+
두 메서드 모두 시그니처가 (self, <exc>) 라 래퍼를 공유한다.)
|
|
50
|
+
실제 응답 status 는 custom_start_response 가 이후에 갱신하므로, 여기서 넘기는
|
|
51
|
+
500 은 interceptor_error 의 에러 기록 트리거 용도로만 사용된다.
|
|
52
|
+
"""
|
|
53
|
+
def error_wrapper(fn):
|
|
54
|
+
@trace_handler(fn)
|
|
55
|
+
def trace(self, exception):
|
|
56
|
+
ctx = TraceContextManager.getLocalContext()
|
|
57
|
+
interceptor_error(
|
|
58
|
+
500, # 해당 status 값은 에러 처리용으로만 사용됩니다.
|
|
59
|
+
[exception.__class__.__name__,
|
|
60
|
+
str(exception)],
|
|
61
|
+
ctx=ctx
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
callback = fn(self, exception)
|
|
65
|
+
return callback
|
|
66
|
+
|
|
67
|
+
return trace
|
|
68
|
+
|
|
69
|
+
Dispatcher = getattr(module, 'HttpDispatcher', None)
|
|
70
|
+
if Dispatcher:
|
|
71
|
+
# Odoo 16+
|
|
72
|
+
Dispatcher.handle_error = error_wrapper(Dispatcher.handle_error)
|
|
73
|
+
else:
|
|
74
|
+
# Odoo 14/15
|
|
75
|
+
HttpRequest = getattr(module, 'HttpRequest', None)
|
|
76
|
+
if HttpRequest and hasattr(HttpRequest, '_handle_exception'):
|
|
77
|
+
HttpRequest._handle_exception = error_wrapper(HttpRequest._handle_exception)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""conf ``hook_service_patterns`` — 지정 메서드를 트랜잭션(서비스) 진입점으로 자동 래핑.
|
|
2
|
+
|
|
3
|
+
whatap.conf 예:
|
|
4
|
+
|
|
5
|
+
hook_service_patterns=myapp.infer:RunwayModel.predict, myapp.jobs:run_batch
|
|
6
|
+
|
|
7
|
+
각 패턴 ``module:Class.method`` / ``module:func`` / ``module:Class.*`` / ``module:*.*``
|
|
8
|
+
의 메서드를 import 시점에 ``@method_profiling`` 과 동일하게 감싼다. 그 메서드 호출이
|
|
9
|
+
곧 하나의 트랜잭션(TX_START~TX_END)이 된다. raw ASGI·커스텀 워커처럼 프레임워크
|
|
10
|
+
자동계측이 안 되는 진입점을 **소스 수정 없이** 트랜잭션으로 잡는 선언적 경로.
|
|
11
|
+
|
|
12
|
+
계열 비교 (모두 동일한 import-hook 플러밍, 래퍼만 다름):
|
|
13
|
+
- hook_method_patterns → 메서드를 기존 트랜잭션 안의 **스텝**(TX_METHOD) 으로
|
|
14
|
+
- workflow_method_patterns → 메서드를 LLM **워크플로우** 경계로
|
|
15
|
+
- hook_service_patterns → 메서드를 **트랜잭션** 진입점으로 (이 모듈)
|
|
16
|
+
|
|
17
|
+
대상 모듈이 PLUGIN 에 class_defs 를 등록하면 ImportFinder 가 그 목록을 패키징해
|
|
18
|
+
넘겨준다 (trace_import.load_module).
|
|
19
|
+
"""
|
|
20
|
+
import inspect
|
|
21
|
+
|
|
22
|
+
from whatap.trace import get_dict
|
|
23
|
+
from whatap import logging
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def instrument_service(module_dict):
|
|
27
|
+
"""module_dict = {'module': <module>, 'class_defs': [<class.method ...>]}."""
|
|
28
|
+
# 트랜잭션 래핑 코어(@method_profiling 과 공용). 예외 재전파 + 컨텍스트 정리 포함.
|
|
29
|
+
from whatap import _service_trace
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
module = module_dict['module']
|
|
33
|
+
for class_def in module_dict['class_defs']:
|
|
34
|
+
parts = class_def.split('.')
|
|
35
|
+
|
|
36
|
+
# 대상 클래스/모듈 목록 + 타깃 메서드명 해석 (instrument_plugin 과 동일 규칙).
|
|
37
|
+
if len(parts) == 2:
|
|
38
|
+
if parts[0] == '*':
|
|
39
|
+
m_list = [
|
|
40
|
+
getattr(module, attr) for attr in dir(module)
|
|
41
|
+
if not attr.startswith('__')
|
|
42
|
+
and inspect.isclass(getattr(module, attr))
|
|
43
|
+
and getattr(getattr(module, attr), '__module__', None) == module.__name__
|
|
44
|
+
]
|
|
45
|
+
else:
|
|
46
|
+
m_list = [getattr(module, parts[0])]
|
|
47
|
+
target = parts[1]
|
|
48
|
+
else:
|
|
49
|
+
m_list = [module]
|
|
50
|
+
target = parts[0]
|
|
51
|
+
|
|
52
|
+
for m in m_list:
|
|
53
|
+
if target == '*':
|
|
54
|
+
t_list = [
|
|
55
|
+
attr for attr in dir(m)
|
|
56
|
+
if not attr.startswith('__')
|
|
57
|
+
and hasattr(m, attr)
|
|
58
|
+
and inspect.isfunction(getattr(m, attr))
|
|
59
|
+
]
|
|
60
|
+
else:
|
|
61
|
+
t_list = [target]
|
|
62
|
+
|
|
63
|
+
for t in t_list:
|
|
64
|
+
if not hasattr(m, t):
|
|
65
|
+
continue
|
|
66
|
+
wrapped = _service_trace(getattr(m, t))
|
|
67
|
+
try:
|
|
68
|
+
setattr(m, t, wrapped)
|
|
69
|
+
except Exception:
|
|
70
|
+
get_dict(m)[t] = wrapped
|
|
71
|
+
except Exception as e:
|
|
72
|
+
logging.debug(e, extra={'id': 'hook_service_patterns ERROR'})
|
|
@@ -177,6 +177,17 @@ class TraceContextManager(object):
|
|
|
177
177
|
cls.local.context = None
|
|
178
178
|
cls.entry.remove(key)
|
|
179
179
|
|
|
180
|
+
@classmethod
|
|
181
|
+
def clearLocalContext(cls):
|
|
182
|
+
"""현재 로컬 컨텍스트를 비운다 — threading.local + contextvars 양쪽.
|
|
183
|
+
|
|
184
|
+
복원할 부모가 없는 **루트 트랜잭션 종료**용. ``setLocalContext(None)`` 은 None 에
|
|
185
|
+
thread 속성을 세팅하다 터지고, ``end()`` 는 contextvars(py3.7+ getLocalContext 가
|
|
186
|
+
우선 참조) 를 비우지 않아 컨텍스트가 누수된다. 둘 다 안전하게 None 으로 만든다."""
|
|
187
|
+
if contextvars:
|
|
188
|
+
cls.whatap_coroutine_context.set(None)
|
|
189
|
+
cls.local.context = None
|
|
190
|
+
|
|
180
191
|
@classmethod
|
|
181
192
|
def getTxProfile(cls, n):
|
|
182
193
|
ctx = cls.getLocalContext()
|
|
@@ -24,7 +24,11 @@ def load_module(module, fullname):
|
|
|
24
24
|
__import__(wfullname)
|
|
25
25
|
wmodule = sys.modules.get(wfullname)
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
# 대상 모듈이 PLUGIN 에 class_defs 를 등록했으면(hook_method_patterns /
|
|
28
|
+
# workflow_method_patterns / hook_service_patterns 계열) 패턴 목록을 함께
|
|
29
|
+
# 넘긴다. 과거엔 인스트루먼트 모듈명이 'plugin' 으로 끝나는지로 판별했으나,
|
|
30
|
+
# 파일명 규칙과 디커플하기 위해 PLUGIN 등록 여부로 판별한다.
|
|
31
|
+
if fullname in PLUGIN:
|
|
28
32
|
module = {'module': module, 'class_defs': PLUGIN[fullname]}
|
|
29
33
|
|
|
30
34
|
getattr(wmodule,
|
|
@@ -130,6 +130,7 @@ whatap/trace/trace_handler.py
|
|
|
130
130
|
whatap/trace/trace_import.py
|
|
131
131
|
whatap/trace/trace_module_definition.py
|
|
132
132
|
whatap/trace/mod/__init__.py
|
|
133
|
+
whatap/trace/mod/hook_service_patterns.py
|
|
133
134
|
whatap/trace/mod/logging.py
|
|
134
135
|
whatap/trace/mod/plugin.py
|
|
135
136
|
whatap/trace/mod/amqp/__init__.py
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import traceback
|
|
2
|
-
from whatap import logging
|
|
3
|
-
from whatap.trace.trace_handler import trace_handler
|
|
4
|
-
from whatap.trace.trace_error import interceptor_error
|
|
5
|
-
from whatap.trace.mod.application.wsgi import interceptor
|
|
6
|
-
from whatap.trace.trace_context_manager import TraceContextManager
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def instrument(module):
|
|
10
|
-
root = module.http.root
|
|
11
|
-
AppClass = root.__class__
|
|
12
|
-
original_call = AppClass.__call__
|
|
13
|
-
|
|
14
|
-
def wrapper(fn):
|
|
15
|
-
@trace_handler(fn, True)
|
|
16
|
-
def trace(self, environ, start_response):
|
|
17
|
-
def custom_start_response(status, headers, exc_info=None):
|
|
18
|
-
ctx = TraceContextManager.getLocalContext()
|
|
19
|
-
try:
|
|
20
|
-
ctx.status = int(status.split()[0])
|
|
21
|
-
except Exception as e:
|
|
22
|
-
logging.warning('[ODOO] status parse failed: %s' % e, extra={'id': 'ODOO001'})
|
|
23
|
-
ctx.status = 0
|
|
24
|
-
return start_response(status, headers, exc_info)
|
|
25
|
-
try:
|
|
26
|
-
callback = interceptor(fn, self, environ, custom_start_response)
|
|
27
|
-
except Exception as e:
|
|
28
|
-
interceptor_error(
|
|
29
|
-
500 , #해당 status 값은 에러 처리용으로만 사용됩니다.
|
|
30
|
-
[e.__class__.__name__, str(e)]
|
|
31
|
-
)
|
|
32
|
-
raise
|
|
33
|
-
return callback
|
|
34
|
-
|
|
35
|
-
return trace
|
|
36
|
-
|
|
37
|
-
AppClass.__call__ = wrapper(original_call)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"""
|
|
41
|
-
Odoo 16+ HttpDispatcher.handle_error 패치
|
|
42
|
-
"""
|
|
43
|
-
Dispatcher = getattr(module.http, 'HttpDispatcher', None)
|
|
44
|
-
|
|
45
|
-
if Dispatcher:
|
|
46
|
-
original_handle_error = Dispatcher.handle_error
|
|
47
|
-
|
|
48
|
-
def wrapper(fn):
|
|
49
|
-
@trace_handler(fn)
|
|
50
|
-
def trace(self,exception):
|
|
51
|
-
ctx = TraceContextManager.getLocalContext()
|
|
52
|
-
interceptor_error(
|
|
53
|
-
500, # 해당 status 값은 에러 처리용으로만 사용됩니다.
|
|
54
|
-
[exception.__class__.__name__,
|
|
55
|
-
str(exception)],
|
|
56
|
-
ctx=ctx
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
callback = fn(self, exception)
|
|
60
|
-
return callback
|
|
61
|
-
|
|
62
|
-
return trace
|
|
63
|
-
Dispatcher.handle_error = wrapper(Dispatcher.handle_error)
|
|
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-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/answer_relevance.py
RENAMED
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/combined_judge.py
RENAMED
|
File without changes
|
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/hallucination.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/evaluators/builtins/prompt_injection.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
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_input_message.py
RENAMED
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_log_sink_pack.py
RENAMED
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_output_message.py
RENAMED
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_step_eval_status.py
RENAMED
|
File without changes
|
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_system_message.py
RENAMED
|
File without changes
|
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/log_sink_packs/llm_tool_results.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/anthropic/messages/__init__.py
RENAMED
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/anthropic/messages/messages.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/chat/chat_context.py
RENAMED
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/chat/chat_extractor.py
RENAMED
|
File without changes
|
{whatap_python-2.1.2 → whatap_python-2.1.3rc1}/whatap/llm/providers/openai/completions/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|