mirror of
https://github.com/langgenius/dify.git
synced 2026-09-08 02:43:49 +08:00
231 lines
6.6 KiB
Python
231 lines
6.6 KiB
Python
"""Application boundary for app tracing provider configurations."""
|
|
|
|
from dataclasses import dataclass, replace
|
|
from datetime import datetime
|
|
from typing import Any, Protocol
|
|
|
|
from machinery.context import RequestContext
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class AppTracingConfigRecord:
|
|
id: str
|
|
app_id: str
|
|
tracing_provider: str | None
|
|
tracing_config: dict[str, Any] | None
|
|
is_active: bool
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
|
|
class AppTracingConfigStore(Protocol):
|
|
def get(
|
|
self,
|
|
*,
|
|
workspace_id: str,
|
|
app_id: str,
|
|
tracing_provider: str,
|
|
) -> AppTracingConfigRecord | None: ...
|
|
|
|
def create(
|
|
self,
|
|
*,
|
|
workspace_id: str,
|
|
app_id: str,
|
|
tracing_provider: str,
|
|
tracing_config: dict[str, Any],
|
|
) -> bool: ...
|
|
|
|
def update(
|
|
self,
|
|
*,
|
|
workspace_id: str,
|
|
app_id: str,
|
|
tracing_provider: str,
|
|
tracing_config: dict[str, Any],
|
|
) -> bool: ...
|
|
|
|
def delete(
|
|
self,
|
|
*,
|
|
workspace_id: str,
|
|
app_id: str,
|
|
tracing_provider: str,
|
|
) -> bool: ...
|
|
|
|
|
|
class TracingConfigProviderGateway(Protocol):
|
|
def validate_provider(self, tracing_provider: str) -> None: ...
|
|
|
|
def prepare_new_config(
|
|
self,
|
|
*,
|
|
workspace_id: str,
|
|
tracing_provider: str,
|
|
tracing_config: dict[str, Any],
|
|
) -> dict[str, Any]: ...
|
|
|
|
def prepare_updated_config(
|
|
self,
|
|
*,
|
|
workspace_id: str,
|
|
tracing_provider: str,
|
|
tracing_config: dict[str, Any],
|
|
current_tracing_config: dict[str, Any] | None,
|
|
) -> dict[str, Any]: ...
|
|
|
|
def present_config(
|
|
self,
|
|
*,
|
|
workspace_id: str,
|
|
tracing_provider: str,
|
|
tracing_config: dict[str, Any] | None,
|
|
) -> dict[str, Any]: ...
|
|
|
|
|
|
class AppTracingConfigError(Exception):
|
|
"""Base class for framework-neutral app tracing configuration failures."""
|
|
|
|
|
|
class AppTracingConfigAppNotFoundError(AppTracingConfigError):
|
|
def __init__(self) -> None:
|
|
super().__init__("App not found")
|
|
|
|
|
|
class AppTracingConfigAlreadyExistsError(AppTracingConfigError):
|
|
def __init__(self) -> None:
|
|
super().__init__("Trace config is exist.")
|
|
|
|
|
|
class AppTracingConfigNotFoundError(AppTracingConfigError):
|
|
def __init__(self) -> None:
|
|
super().__init__("Trace config not exist.")
|
|
|
|
|
|
class AppTracingConfigInvalidProviderError(AppTracingConfigError):
|
|
def __init__(self, tracing_provider: str) -> None:
|
|
super().__init__(f"Invalid tracing provider: {tracing_provider}")
|
|
|
|
|
|
class AppTracingConfigInvalidConfigurationError(AppTracingConfigError):
|
|
"""The submitted provider configuration does not match its schema."""
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__("Invalid tracing configuration")
|
|
|
|
|
|
class AppTracingConfigVerificationFailedError(AppTracingConfigError):
|
|
"""The submitted configuration could not be verified by its provider."""
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__("Tracing configuration verification failed")
|
|
|
|
|
|
class AppTracingConfigProcessingError(AppTracingConfigError):
|
|
"""A validated or stored configuration could not be processed internally."""
|
|
|
|
def __init__(self) -> None:
|
|
super().__init__("Tracing configuration processing failed")
|
|
|
|
|
|
class AppTracingConfigService:
|
|
def __init__(self, *, configs: AppTracingConfigStore, provider: TracingConfigProviderGateway) -> None:
|
|
self._configs = configs
|
|
self._provider = provider
|
|
|
|
def get(
|
|
self,
|
|
context: RequestContext,
|
|
app_id: str,
|
|
tracing_provider: str,
|
|
) -> AppTracingConfigRecord | None:
|
|
workspace_id = context.active_workspace_id
|
|
self._provider.validate_provider(tracing_provider)
|
|
record = self._configs.get(
|
|
workspace_id=workspace_id,
|
|
app_id=app_id,
|
|
tracing_provider=tracing_provider,
|
|
)
|
|
if record is None:
|
|
return None
|
|
|
|
tracing_config = self._provider.present_config(
|
|
workspace_id=workspace_id,
|
|
tracing_provider=tracing_provider,
|
|
tracing_config=record.tracing_config,
|
|
)
|
|
return replace(record, tracing_config=tracing_config)
|
|
|
|
def create(
|
|
self,
|
|
context: RequestContext,
|
|
app_id: str,
|
|
tracing_provider: str,
|
|
tracing_config: dict[str, Any],
|
|
) -> None:
|
|
workspace_id = context.active_workspace_id
|
|
current = self._configs.get(
|
|
workspace_id=workspace_id,
|
|
app_id=app_id,
|
|
tracing_provider=tracing_provider,
|
|
)
|
|
if current is not None:
|
|
raise AppTracingConfigAlreadyExistsError
|
|
|
|
encrypted_config = self._provider.prepare_new_config(
|
|
workspace_id=workspace_id,
|
|
tracing_provider=tracing_provider,
|
|
tracing_config=tracing_config,
|
|
)
|
|
|
|
created = self._configs.create(
|
|
workspace_id=workspace_id,
|
|
app_id=app_id,
|
|
tracing_provider=tracing_provider,
|
|
tracing_config=encrypted_config,
|
|
)
|
|
if not created:
|
|
raise AppTracingConfigAlreadyExistsError
|
|
|
|
def update(
|
|
self,
|
|
context: RequestContext,
|
|
app_id: str,
|
|
tracing_provider: str,
|
|
tracing_config: dict[str, Any],
|
|
) -> None:
|
|
workspace_id = context.active_workspace_id
|
|
current = self._configs.get(
|
|
workspace_id=workspace_id,
|
|
app_id=app_id,
|
|
tracing_provider=tracing_provider,
|
|
)
|
|
self._provider.validate_provider(tracing_provider)
|
|
if current is None:
|
|
raise AppTracingConfigNotFoundError
|
|
|
|
encrypted_config = self._provider.prepare_updated_config(
|
|
workspace_id=workspace_id,
|
|
tracing_provider=tracing_provider,
|
|
tracing_config=tracing_config,
|
|
current_tracing_config=current.tracing_config,
|
|
)
|
|
updated = self._configs.update(
|
|
workspace_id=workspace_id,
|
|
app_id=app_id,
|
|
tracing_provider=tracing_provider,
|
|
tracing_config=encrypted_config,
|
|
)
|
|
if not updated:
|
|
raise AppTracingConfigNotFoundError
|
|
|
|
def delete(self, context: RequestContext, app_id: str, tracing_provider: str) -> None:
|
|
self._provider.validate_provider(tracing_provider)
|
|
deleted = self._configs.delete(
|
|
workspace_id=context.active_workspace_id,
|
|
app_id=app_id,
|
|
tracing_provider=tracing_provider,
|
|
)
|
|
if not deleted:
|
|
raise AppTracingConfigNotFoundError
|