mirror of
https://github.com/langgenius/dify.git
synced 2026-02-10 21:14:25 +08:00
**Problem:**
The telemetry system had unnecessary abstraction layers and bad practices
from the last 3 commits introducing the gateway implementation:
- TelemetryFacade class wrapper around emit() function
- String literals instead of SignalType enum
- Dictionary mapping enum → string instead of enum → enum
- Unnecessary ENTERPRISE_TELEMETRY_GATEWAY_ENABLED feature flag
- Duplicate guard checks scattered across files
- Non-thread-safe TelemetryGateway singleton pattern
- Missing guard in ops_trace_task.py causing RuntimeError spam
**Solution:**
1. Deleted TelemetryFacade - replaced with thin emit() function in core/telemetry/__init__.py
2. Added SignalType enum ('trace' | 'metric_log') to enterprise/telemetry/contracts.py
3. Replaced CASE_TO_TRACE_TASK_NAME dict with CASE_TO_TRACE_TASK: dict[TelemetryCase, TraceTaskName]
4. Deleted is_gateway_enabled() and _emit_legacy() - using existing ENTERPRISE_ENABLED + ENTERPRISE_TELEMETRY_ENABLED instead
5. Extracted _should_drop_ee_only_event() helper to eliminate duplicate checks
6. Moved TelemetryGateway singleton to ext_enterprise_telemetry.py:
- Init once in init_app() for thread-safety
- Access via get_gateway() function
7. Re-added guard to ops_trace_task.py to prevent RuntimeError when EE=OFF but CE tracing enabled
8. Updated 11 caller files to import 'emit as telemetry_emit' instead of 'TelemetryFacade'
**Result:**
- 322 net lines deleted (533 removed, 211 added)
- All 91 tests pass
- Thread-safe singleton pattern
- Cleaner API surface: from TelemetryFacade.emit() to telemetry_emit()
- Proper enum usage throughout
- No RuntimeError spam in EE=OFF + CE=ON scenario
59 lines
1.6 KiB
Python
59 lines
1.6 KiB
Python
"""Flask extension for enterprise telemetry lifecycle management.
|
|
|
|
Initializes the EnterpriseExporter and TelemetryGateway singletons during
|
|
``create_app()`` (single-threaded), registers blinker event handlers,
|
|
and hooks atexit for graceful shutdown.
|
|
|
|
Skipped entirely when ``ENTERPRISE_ENABLED`` and ``ENTERPRISE_TELEMETRY_ENABLED``
|
|
are false (``is_enabled()`` gate).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import atexit
|
|
import logging
|
|
from typing import TYPE_CHECKING
|
|
|
|
from configs import dify_config
|
|
|
|
if TYPE_CHECKING:
|
|
from dify_app import DifyApp
|
|
from enterprise.telemetry.exporter import EnterpriseExporter
|
|
from enterprise.telemetry.gateway import TelemetryGateway
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
_exporter: EnterpriseExporter | None = None
|
|
_gateway: TelemetryGateway | None = None
|
|
|
|
|
|
def is_enabled() -> bool:
|
|
return bool(dify_config.ENTERPRISE_ENABLED and dify_config.ENTERPRISE_TELEMETRY_ENABLED)
|
|
|
|
|
|
def init_app(app: DifyApp) -> None:
|
|
global _exporter, _gateway
|
|
|
|
if not is_enabled():
|
|
return
|
|
|
|
from enterprise.telemetry.exporter import EnterpriseExporter
|
|
from enterprise.telemetry.gateway import TelemetryGateway
|
|
|
|
_exporter = EnterpriseExporter(dify_config)
|
|
_gateway = TelemetryGateway()
|
|
atexit.register(_exporter.shutdown)
|
|
|
|
# Import to trigger @signal.connect decorator registration
|
|
import enterprise.telemetry.event_handlers # noqa: F401 # type: ignore[reportUnusedImport]
|
|
|
|
logger.info("Enterprise telemetry initialized")
|
|
|
|
|
|
def get_enterprise_exporter() -> EnterpriseExporter | None:
|
|
return _exporter
|
|
|
|
|
|
def get_gateway() -> TelemetryGateway | None:
|
|
return _gateway
|