mirror of
https://github.com/langgenius/dify.git
synced 2026-02-09 23:20:12 -05: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
84 lines
2.3 KiB
Python
84 lines
2.3 KiB
Python
"""Telemetry gateway contracts and data structures.
|
|
|
|
This module defines the envelope format for telemetry events and the routing
|
|
configuration that determines how each event type is processed.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from enum import StrEnum
|
|
from typing import Any
|
|
|
|
from pydantic import BaseModel, field_validator
|
|
|
|
|
|
class TelemetryCase(StrEnum):
|
|
"""Enumeration of all known telemetry event cases."""
|
|
|
|
WORKFLOW_RUN = "workflow_run"
|
|
NODE_EXECUTION = "node_execution"
|
|
DRAFT_NODE_EXECUTION = "draft_node_execution"
|
|
MESSAGE_RUN = "message_run"
|
|
TOOL_EXECUTION = "tool_execution"
|
|
MODERATION_CHECK = "moderation_check"
|
|
SUGGESTED_QUESTION = "suggested_question"
|
|
DATASET_RETRIEVAL = "dataset_retrieval"
|
|
GENERATE_NAME = "generate_name"
|
|
PROMPT_GENERATION = "prompt_generation"
|
|
APP_CREATED = "app_created"
|
|
APP_UPDATED = "app_updated"
|
|
APP_DELETED = "app_deleted"
|
|
FEEDBACK_CREATED = "feedback_created"
|
|
|
|
|
|
class SignalType(StrEnum):
|
|
"""Signal routing type for telemetry cases."""
|
|
|
|
TRACE = "trace"
|
|
METRIC_LOG = "metric_log"
|
|
|
|
|
|
class CaseRoute(BaseModel):
|
|
"""Routing configuration for a telemetry case.
|
|
|
|
Attributes:
|
|
signal_type: The type of signal (trace or metric_log).
|
|
ce_eligible: Whether this case is eligible for community edition tracing.
|
|
"""
|
|
|
|
signal_type: SignalType
|
|
ce_eligible: bool
|
|
|
|
|
|
class TelemetryEnvelope(BaseModel):
|
|
"""Envelope for telemetry events.
|
|
|
|
Attributes:
|
|
case: The telemetry case type.
|
|
tenant_id: The tenant identifier.
|
|
event_id: Unique event identifier for deduplication.
|
|
payload: The main event payload.
|
|
payload_fallback: Fallback payload (max 64KB).
|
|
metadata: Optional metadata dictionary.
|
|
"""
|
|
|
|
case: TelemetryCase
|
|
tenant_id: str
|
|
event_id: str
|
|
payload: dict[str, Any]
|
|
payload_fallback: bytes | None = None
|
|
metadata: dict[str, Any] | None = None
|
|
|
|
@field_validator("payload_fallback")
|
|
@classmethod
|
|
def validate_payload_fallback_size(cls, v: bytes | None) -> bytes | None:
|
|
"""Validate that payload_fallback does not exceed 64KB."""
|
|
if v is not None and len(v) > 65536: # 64 * 1024
|
|
raise ValueError("payload_fallback must not exceed 64KB")
|
|
return v
|
|
|
|
class Config:
|
|
"""Pydantic configuration."""
|
|
|
|
use_enum_values = False
|