[feat] setup master from fork with fastapi + otel

This commit is contained in:
Azamat 2026-03-26 21:29:41 +03:00
parent 597eae9b97
commit 1fbf77f879
8 changed files with 310 additions and 1 deletions

View file

@ -0,0 +1,16 @@
# 001 Composition Root and Lifetimes
Context
- The template must initialize repository and usecase objects once and reuse them across requests.
- FastAPI integration must not leak framework concerns into inner layers.
Decision
- Keep a single composition root in `adapter/di/container.py`.
- Build repositories, usecases, config, and observability adapters during application startup.
- Store the container in application state and expose instances through thin HTTP dependencies.
- Do not create repository or usecase objects per request.
Consequences
- Object lifetimes stay explicit and testable.
- Replacing the web framework affects only the HTTP adapter layer.
- Startup failures surface early instead of during request handling.

View file

@ -0,0 +1,16 @@
# 002 Config From YAML and Env
Context
- The service needs readable project configuration and safe handling of sensitive values.
- The final configuration object should be easy to inject and test.
Decision
- Keep non-sensitive defaults in YAML files under `config/`.
- Read sensitive values only from environment variables.
- Merge YAML and env sources into one `AppConfig` dataclass tree in `adapter/config/`.
- Keep configuration parsing and validation outside `domain/` and `usecase/`.
Consequences
- Local configuration remains simple to inspect and version.
- Secrets stay out of committed files.
- Inner layers depend on typed config data, not on env or YAML readers.

View file

@ -0,0 +1,17 @@
# 003 Observability Via Interfaces
Context
- Logging, metrics, and tracing are required, but inner layers must stay independent from OpenTelemetry.
- The project needs request logging and metrics middleware.
Decision
- Define observability interfaces in `usecase/interface.py`.
- Implement those interfaces with OpenTelemetry adapters in `adapter/otel/`.
- Use request logging middleware and metrics middleware in the FastAPI adapter.
- Do not add a custom trace middleware by default.
- Use standard ASGI/FastAPI OpenTelemetry instrumentation for request spans.
Consequences
- Usecases stay portable and framework-agnostic.
- Trace behavior remains consistent with OpenTelemetry defaults.
- Extra span enrichment can be added later without changing inner-layer contracts.

View file

@ -0,0 +1,16 @@
# 004 Versioned HTTP API
Context
- The template needs explicit API versioning and an HTTP boundary that can be replaced later.
- FastAPI is the initial framework, but it must not become a hard dependency for core logic.
Decision
- Place HTTP transport code under `adapter/http/fastapi/`.
- Mount routers under `/api/v1` and keep version-specific routers in `routers/v1/`.
- Map HTTP requests to usecase calls through thin dependencies and handlers only.
- Keep framework-specific request and response models in the HTTP adapter layer.
Consequences
- New API versions can be introduced without changing usecase contracts.
- Replacing FastAPI means rewriting only the HTTP adapter.
- Domain and usecase layers remain free from transport concerns.

View file

@ -0,0 +1,17 @@
# 005 Early FastAPI OTel Instrumentation
Context
- HTTP spans and HTTP metrics are provided by FastAPI/ASGI OpenTelemetry middleware.
- Starlette caches `middleware_stack` on first ASGI entry, including lifespan startup.
- Instrumenting FastAPI inside lifespan is too late for the initial middleware stack.
Decision
- Build the application container before returning the FastAPI app from `create_app`.
- Configure FastAPI OpenTelemetry instrumentation in the app factory, not in lifespan.
- Pass the configured tracer and meter providers directly to `FastAPIInstrumentor.instrument_app(...)`.
- Keep lifespan focused on shutdown and resource cleanup.
Consequences
- `OpenTelemetryMiddleware` is present in the runtime stack without manual stack rebuilds.
- HTTP traces and HTTP metrics use the same startup wiring as other singleton adapters.
- Observability bootstrap stays explicit in the outer adapter layer.