/ src / evidently / legacy / ui / local_service.py
local_service.py
  1  import logging
  2  import time
  3  from typing import Dict
  4  
  5  from litestar import Request
  6  from litestar import Response
  7  from litestar.di import Provide
  8  from litestar.logging import LoggingConfig
  9  
 10  from evidently.errors import EvidentlyError
 11  from evidently.legacy.ui.api.projects import create_projects_api
 12  from evidently.legacy.ui.api.projects import projects_api_dependencies
 13  from evidently.legacy.ui.api.service import service_api
 14  from evidently.legacy.ui.api.static import assets_router
 15  from evidently.legacy.ui.components.base import AppBuilder
 16  from evidently.legacy.ui.components.base import ComponentContext
 17  from evidently.legacy.ui.components.base import ServiceComponent
 18  from evidently.legacy.ui.components.security import NoSecurityComponent
 19  from evidently.legacy.ui.components.security import SecurityComponent
 20  from evidently.legacy.ui.components.storage import LocalStorageComponent
 21  from evidently.legacy.ui.components.storage import StorageComponent
 22  from evidently.legacy.ui.components.telemetry import TelemetryComponent
 23  from evidently.legacy.ui.config import AppConfig
 24  from evidently.legacy.ui.config import ConfigContext
 25  from evidently.legacy.ui.errors import EvidentlyServiceError
 26  
 27  
 28  def evidently_service_exception_handler(_: Request, exc: EvidentlyServiceError) -> Response:
 29      return exc.to_response()
 30  
 31  
 32  def evidently_exception_handler(_: Request, exc: EvidentlyError) -> Response:
 33      return Response(content={"detail": exc.get_message()}, status_code=500)
 34  
 35  
 36  class LocalServiceComponent(ServiceComponent):
 37      debug: bool = False
 38  
 39      def get_api_route_handlers(self, ctx: ComponentContext):
 40          guard = ctx.get_component(SecurityComponent).get_auth_guard()
 41          return [create_projects_api(guard), service_api()]
 42  
 43      def get_dependencies(self, ctx: ComponentContext) -> Dict[str, Provide]:
 44          deps = super().get_dependencies(ctx)
 45          deps.update(projects_api_dependencies)
 46          return deps
 47  
 48      def get_route_handlers(self, ctx: ComponentContext):
 49          return [assets_router()]
 50  
 51      def apply(self, ctx: ComponentContext, builder: AppBuilder):
 52          super().apply(ctx, builder)
 53          assert isinstance(ctx, ConfigContext)
 54          builder.exception_handlers[EvidentlyServiceError] = evidently_service_exception_handler
 55          builder.exception_handlers[EvidentlyError] = evidently_exception_handler
 56          builder.kwargs["debug"] = self.debug
 57          if self.debug:
 58              log_config = create_logging()
 59              builder.kwargs["logging_config"] = LoggingConfig(**log_config)
 60  
 61  
 62  def create_logging() -> dict:
 63      logging.Formatter.converter = time.gmtime
 64      return {
 65          "version": 1,
 66          "log_exceptions": "always",
 67          "disable_existing_loggers": False,
 68          "formatters": {
 69              "default": {
 70                  "()": "logging.Formatter",
 71                  "format": "%(asctime)s %(levelname)-8s %(name)-15s %(message)s",
 72                  "datefmt": "%Y-%m-%dT%H:%M:%SZ",
 73              },
 74              "access": {
 75                  "()": "logging.Formatter",
 76                  "format": "%(asctime)s %(levelname)-8s %(name)-15s %(message)s",
 77                  "datefmt": "%Y-%m-%dT%H:%M:%SZ",
 78              },
 79              "standard": {
 80                  "()": "logging.Formatter",
 81                  "format": "%(asctime)s %(levelname)-8s %(name)-15s %(message)s",
 82                  "datefmt": "%Y-%m-%dT%H:%M:%SZ",
 83              },
 84          },
 85          "handlers": {
 86              "default": {
 87                  "formatter": "default",
 88                  "class": "logging.StreamHandler",
 89                  "stream": "ext://sys.stdout",
 90              },
 91              "access": {
 92                  "formatter": "access",
 93                  "class": "logging.StreamHandler",
 94                  "stream": "ext://sys.stdout",
 95              },
 96          },
 97          "loggers": {
 98              "litestar": {"handlers": ["default"]},
 99              "uvicorn": {"handlers": ["default"], "level": "INFO", "propagate": False},
100              "uvicorn.error": {"level": "INFO"},
101              "uvicorn.access": {"handlers": ["access"], "level": "INFO", "propagate": False},
102          },
103      }
104  
105  
106  class LocalConfig(AppConfig):
107      security: SecurityComponent = NoSecurityComponent()
108      service: ServiceComponent = LocalServiceComponent()
109      storage: StorageComponent = LocalStorageComponent()
110      telemetry: TelemetryComponent = TelemetryComponent()