92 lines
2.9 KiB
Python
92 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
from functools import lru_cache
|
|
|
|
from pydantic import Field
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
model_config = SettingsConfigDict(
|
|
env_file=".env",
|
|
env_file_encoding="utf-8",
|
|
extra="ignore",
|
|
)
|
|
|
|
app_name: str = "otel-bi-backend"
|
|
app_env: str = "dev"
|
|
log_level: str = "INFO"
|
|
|
|
api_host: str = "0.0.0.0"
|
|
api_port: int = 8000
|
|
|
|
cors_origins: str = "http://localhost:5173"
|
|
|
|
# Go analytics service
|
|
analytics_service_url: str = "http://localhost:8080"
|
|
|
|
# PostgreSQL — write store for derived data
|
|
postgres_host: str = "localhost"
|
|
postgres_port: int = 5432
|
|
postgres_database: str = "otel_bi"
|
|
postgres_username: str = "otel_bi"
|
|
postgres_password: str = "otel_bi"
|
|
postgres_sslmode: str = "prefer"
|
|
postgres_connection_string: str | None = None
|
|
|
|
# Frontend OIDC JWT validation
|
|
require_frontend_auth: bool = True
|
|
frontend_jwt_issuer_url: str = ""
|
|
frontend_jwt_audience: str = ""
|
|
frontend_jwt_jwks_url: str | None = None
|
|
frontend_jwt_algorithm: str = "RS256"
|
|
frontend_required_scopes: str = ""
|
|
frontend_clock_skew_seconds: int = Field(default=30, ge=0, le=300)
|
|
|
|
# Frontend OIDC client config (served via /api/config)
|
|
frontend_oidc_client_id: str = ""
|
|
frontend_oidc_scope: str = "openid profile email"
|
|
|
|
# OpenTelemetry
|
|
otel_service_name: str = "otel-bi-backend"
|
|
otel_service_namespace: str = "final-thesis"
|
|
otel_collector_endpoint: str = "http://localhost:4318"
|
|
otel_export_timeout_ms: int = 10000
|
|
|
|
# Report output — points at the K8s CSI / SMB mountpoint in production
|
|
report_output_dir: str = "/tmp/otel-bi-reports"
|
|
|
|
# Analytics defaults (forwarded to Go service as query params)
|
|
forecast_horizon_days: int = Field(default=30, ge=7, le=180)
|
|
default_history_days: int = Field(default=365, ge=30, le=1460)
|
|
ranking_default_top_n: int = Field(default=10, ge=3, le=100)
|
|
storage_default_limit: int = Field(default=50, ge=10, le=500)
|
|
|
|
@property
|
|
def cors_origins_list(self) -> list[str]:
|
|
return [o.strip() for o in self.cors_origins.split(",") if o.strip()]
|
|
|
|
@property
|
|
def frontend_required_scopes_list(self) -> list[str]:
|
|
return [s.strip() for s in self.frontend_required_scopes.split(" ") if s.strip()]
|
|
|
|
@property
|
|
def postgres_connection_url(self) -> str:
|
|
if self.postgres_connection_string:
|
|
return self.postgres_connection_string
|
|
from urllib.parse import quote_plus
|
|
user = quote_plus(self.postgres_username)
|
|
password = quote_plus(self.postgres_password)
|
|
return (
|
|
f"postgresql+psycopg://{user}:{password}@{self.postgres_host}:{self.postgres_port}"
|
|
f"/{self.postgres_database}?sslmode={self.postgres_sslmode}"
|
|
)
|
|
|
|
|
|
@lru_cache
|
|
def get_settings() -> Settings:
|
|
return Settings()
|
|
|
|
|
|
settings = get_settings()
|