Files
LedgerLine/services/notifier/app.py
T

69 lines
2.0 KiB
Python
Raw Normal View History

from contextlib import asynccontextmanager
import asyncio
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
2026-10-13 19:48:27 +03:30
from opentelemetry import trace
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
2026-10-13 19:48:27 +03:30
from opentelemetry.trace import StatusCode
from common.db import engine
from common.logging_config import configure_logging
2026-10-19 16:05:40 +03:30
from common.metrics import observe_db_pools, observe_stream_lag
from common.redis_client import redis_client
from common.telemetry import setup_telemetry
from . import consumer
SERVICE_NAME = "notifier"
logger = configure_logging(SERVICE_NAME)
setup_telemetry(service_name=SERVICE_NAME)
@asynccontextmanager
async def lifespan(app: FastAPI):
task = asyncio.create_task(consumer.run())
yield
task.cancel()
app = FastAPI(title=SERVICE_NAME, lifespan=lifespan)
FastAPIInstrumentor.instrument_app(
app,
excluded_urls="/healthz",
exclude_spans=["receive", "send"],
)
SQLAlchemyInstrumentor().instrument(engines=[engine.sync_engine])
2026-10-19 16:05:40 +03:30
observe_db_pools({"default": engine})
observe_stream_lag(consumer.GROUP)
@app.get("/")
async def root():
return {"service": SERVICE_NAME, "version": "0.1.0"}
@app.get("/healthz")
async def healthz(request: Request):
if request.headers.get("X-Ledgerline-Probe") == "chatty-health":
logger.info("healthz_probe_received", probe="chatty-health")
return {"status": "ok", "service": SERVICE_NAME}
@app.get("/readyz")
async def readyz():
try:
async with engine.connect() as conn:
await conn.exec_driver_sql("SELECT 1")
await redis_client.ping()
except Exception as exc:
2026-10-13 19:48:27 +03:30
span = trace.get_current_span()
span.record_exception(exc)
span.set_status(StatusCode.ERROR, str(exc))
logger.exception("readyz_check_failed")
return JSONResponse(status_code=503, content={"status": "unavailable"})
return {"status": "ok"}