decomposer: generate deliverable files for Define the service contract and project architecture for the FastAPI endpoint monitoring service.; Implement the typed monitor CRUD API and concurrency-safe in-memory state according to the service design.; Implement secure on-demand endpoint checks with status updates, latency measurement, robust error handling, and redacted structured logs.; Add operational API endpoints and environment-driven runtime configuration to the monitoring service.; Create automated tests for the monitoring service.; Package the service with Docker and developer documentation.; Validate the complete project.
Some checks are pending
ci / test (push) Has started running

This commit is contained in:
2026-08-09 15:54:53 +00:00
parent 16d6b7e7ce
commit 00ff53324a

View File

@@ -1,36 +1,37 @@
from datetime import datetime, timezone from datetime import UTC, datetime
from enum import StrEnum from enum import StrEnum
from uuid import UUID from uuid import UUID
from pydantic import AnyHttpUrl, BaseModel, ConfigDict, Field from pydantic import BaseModel, ConfigDict, Field, field_validator
from pydantic.networks import AnyHttpUrl
def utc_now() -> datetime: class State(StrEnum):
return datetime.now(timezone.utc)
class HealthState(StrEnum):
unknown = "unknown" unknown = "unknown"
up = "up" up = "up"
down = "down" down = "down"
error = "error"
class MonitorCreate(BaseModel): class MonitorInput(BaseModel):
name: str = Field(min_length=1, max_length=120) name: str = Field(min_length=1, max_length=100)
url: AnyHttpUrl url: AnyHttpUrl
timeout_seconds: float | None = Field(default=None, gt=0, le=30)
@field_validator("url")
@classmethod
def reject_credentials(cls, value: AnyHttpUrl) -> AnyHttpUrl:
if value.username or value.password:
raise ValueError("URL credentials are not allowed")
return value
class MonitorUpdate(MonitorCreate): class CheckSnapshot(BaseModel):
pass state: State = State.unknown
checked_at: datetime | None = None
latency_ms: float | None = None
class CurrentStatus(BaseModel):
state: HealthState
checked_at: datetime
latency_ms: float = Field(ge=0)
http_status: int | None = None http_status: int | None = None
error_code: str | None = None error: str | None = None
error_message: str | None = None
class Monitor(BaseModel): class Monitor(BaseModel):
@@ -39,18 +40,16 @@ class Monitor(BaseModel):
id: UUID id: UUID
name: str name: str
url: AnyHttpUrl url: AnyHttpUrl
timeout_seconds: float | None
created_at: datetime created_at: datetime
updated_at: datetime updated_at: datetime
revision: int revision: int
current_status: CurrentStatus | None = None status: CheckSnapshot
class CheckResponse(BaseModel): class CheckResult(CheckSnapshot):
monitor_id: UUID monitor_id: UUID
status: CurrentStatus
applied: bool
class ErrorDetail(BaseModel): def now() -> datetime:
code: str return datetime.now(UTC)
message: str