Skip to content

Commit 366cd6f

Browse files
author
Ilyas Gasanov
committed
[DOP-19925] Add GET v1/monitoring/metrics endpoint
1 parent fda0ed7 commit 366cd6f

File tree

15 files changed

+284
-73
lines changed

15 files changed

+284
-73
lines changed

docker-compose.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ services:
3636
context: .
3737
ports:
3838
- 8000:8000
39+
# PROMETHEUS_MULTIPROC_DIR is required for multiple workers, see:
40+
# https://prometheus.github.io/client_python/multiprocess/
41+
environment:
42+
PROMETHEUS_MULTIPROC_DIR: /tmp/prometheus-metrics
43+
# tmpfs dir is cleaned up each container restart
44+
tmpfs:
45+
- /tmp/prometheus-metrics
3946
env_file: .env.docker
4047
depends_on:
4148
db:

docs/backend/configuration/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Configuration
1313
logging
1414
cors
1515
debug
16+
monitoring
1617

1718
.. autopydantic_settings:: syncmaster.settings.Settings
1819
.. autopydantic_settings:: syncmaster.settings.server.ServerSettings
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
.. _configuration-server-monitoring:
2+
3+
Setup monitoring
4+
================
5+
6+
REST API server provides the following endpoints with Prometheus compatible metrics:
7+
8+
* ``GET /monitoring/metrics`` - server metrics, like number of requests per path and response status, CPU and RAM usage, and so on.
9+
10+
.. dropdown:: Example
11+
12+
.. literalinclude:: ../../_static/metrics.prom
13+
14+
These endpoints are enabled and configured using settings below:
15+
16+
.. autopydantic_model:: syncmaster.settings.server.monitoring.MonitoringSettings

poetry.lock

Lines changed: 101 additions & 70 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,15 @@ coloredlogs = {version = "*", optional = true}
6767
python-json-logger = {version = "*", optional = true}
6868
asyncpg = { version = ">=0.29,<0.31", optional = true }
6969
apscheduler = { version = "^3.10.4", optional = true }
70+
starlette-exporter = {version = "^0.23.0", optional = true}
7071

7172
[tool.poetry.extras]
7273
backend = [
7374
"pydantic-settings",
7475
"sqlalchemy",
7576
"sqlalchemy-utils",
7677
"fastapi",
78+
"starlette-exporter",
7779
"uvicorn",
7880
"alembic",
7981
"python-multipart",

syncmaster/backend/api/monitoring.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
from fastapi import APIRouter
44

55
from syncmaster.errors.registration import get_error_responses
6+
from syncmaster.schemas import PingResponse
67

7-
router = APIRouter(tags=["monitoring"], prefix="/monitoring", responses=get_error_responses())
8+
router = APIRouter(tags=["Monitoring"], prefix="/monitoring", responses=get_error_responses())
89

910

1011
@router.get("/ping")
11-
async def ping():
12-
return {"status": "ok"}
12+
async def ping() -> PingResponse:
13+
return PingResponse()

syncmaster/backend/middlewares/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
from syncmaster.backend.middlewares.cors import apply_cors_middleware
77
from syncmaster.backend.middlewares.logging import setup_logging
8+
from syncmaster.backend.middlewares.monitoring.metrics import (
9+
apply_monitoring_metrics_middleware,
10+
)
811
from syncmaster.backend.middlewares.request_id import apply_request_id_middleware
912
from syncmaster.settings import Settings
1013

@@ -19,6 +22,7 @@ def apply_middlewares(
1922
setup_logging(settings.server.logging.get_log_config_path())
2023

2124
apply_cors_middleware(application, settings.server.cors)
25+
apply_monitoring_metrics_middleware(application, settings.server.monitoring)
2226
apply_request_id_middleware(application, settings.server.request_id)
2327

2428
return application
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-FileCopyrightText: 2023-2024 MTS PJSC
2+
# SPDX-License-Identifier: Apache-2.0
3+
from syncmaster.backend.middlewares.monitoring.metrics import (
4+
apply_monitoring_metrics_middleware,
5+
)
6+
7+
__all__ = ["apply_monitoring_metrics_middleware"]
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# SPDX-FileCopyrightText: 2023-2024 MTS PJSC
2+
# SPDX-License-Identifier: Apache-2.0
3+
from fastapi import APIRouter, FastAPI
4+
from starlette.responses import PlainTextResponse
5+
from starlette_exporter import PrometheusMiddleware, handle_metrics
6+
7+
from syncmaster.backend.utils.slug import slugify
8+
from syncmaster.settings.server.monitoring import MonitoringSettings
9+
10+
DEFAULT_SKIP_PATHS = {
11+
"/monitoring/metrics",
12+
"/monitoring/ping",
13+
"/static",
14+
"/docs",
15+
"/redoc",
16+
"/openapi.json",
17+
"/favicon.ico",
18+
}
19+
20+
router = APIRouter(tags=["Monitoring"], prefix="/monitoring")
21+
22+
23+
router.get(
24+
"/metrics",
25+
summary="Get server metrics",
26+
description="Return server metrics in Prometheus format, using Starlette Exporter",
27+
response_class=PlainTextResponse,
28+
)(handle_metrics)
29+
30+
31+
def apply_monitoring_metrics_middleware(app: FastAPI, settings: MonitoringSettings) -> FastAPI:
32+
"""Add monitoring metrics middleware & endpoint to the application."""
33+
if not settings.enabled:
34+
return app
35+
36+
skip_paths = DEFAULT_SKIP_PATHS | settings.skip_paths
37+
app.add_middleware(
38+
PrometheusMiddleware,
39+
app_name=slugify(app.title),
40+
skip_paths=skip_paths,
41+
**settings.model_dump(exclude={"enabled", "skip_paths"}),
42+
)
43+
app.include_router(router)
44+
return app
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# SPDX-FileCopyrightText: 2023-2024 MTS PJSC
2+
# SPDX-License-Identifier: Apache-2.0

0 commit comments

Comments
 (0)