Skip to content

Commit 21fc0ce

Browse files
authored
feat(Option): Prometheus (#53)
1 parent a00abb0 commit 21fc0ce

11 files changed

Lines changed: 77 additions & 7 deletions

File tree

fastapi_forge/dtos.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ class ProjectSpec(_Base):
363363
use_redis: bool = False
364364
use_rabbitmq: bool = False
365365
use_taskiq: bool = False
366+
use_prometheus: bool = False
366367
models: list[Model] = []
367368
custom_enums: list[CustomEnum] = []
368369

fastapi_forge/example-projects/game_zone.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ project:
66
use_redis: true
77
use_rabbitmq: true
88
use_taskiq: true
9+
use_prometheus: true
910

1011
custom_enums:
1112
- name: UserRole

fastapi_forge/frontend/panels/project_config_panel.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,10 @@ def _build(self) -> None:
209209
with ui.column().classes("w-full gap-2"):
210210
ui.label("Metrics").classes("text-lg font-bold")
211211
self.use_prometheus = (
212-
ui.checkbox("Prometheus")
212+
ui.checkbox("Prometheus", value=state.use_prometheus)
213213
.classes("w-full")
214-
.tooltip("Coming soon!")
215-
.set_enabled(False)
214+
.bind_value_from(state, "use_prometheus")
215+
.tooltip("Collect and query metrics with Prometheus")
216216
)
217217

218218
with ui.column().classes("w-full gap-2"):
@@ -247,6 +247,7 @@ def _bind_state_to_ui(self) -> None:
247247
"change", self._update_taskiq_state
248248
)
249249
self.use_taskiq.bind_value_to(state, "use_taskiq")
250+
self.use_prometheus.bind_value_to(state, "use_prometheus")
250251

251252
def _update_taskiq_state(self, *_) -> None:
252253
"""Enable or disable Taskiq based on Redis and RabbitMQ."""
@@ -421,6 +422,7 @@ async def _create_project(self) -> None:
421422
state.use_redis = self.use_redis.value
422423
state.use_rabbitmq = self.use_rabbitmq.value
423424
state.use_taskiq = self.use_taskiq.value
425+
state.use_prometheus = self.use_prometheus.value
424426

425427
project_spec = state.get_project_spec()
426428
await build_project(project_spec)

fastapi_forge/frontend/state.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class ProjectState(BaseModel):
5151
use_redis: bool = False
5252
use_rabbitmq: bool = False
5353
use_taskiq: bool = False
54+
use_prometheus: bool = False
5455

5556
def switch_item_editor(
5657
self,
@@ -79,6 +80,7 @@ def initialize_from_project(self, project: ProjectSpec) -> None:
7980
self.use_redis = project.use_redis
8081
self.use_rabbitmq = project.use_rabbitmq
8182
self.use_taskiq = project.use_taskiq
83+
self.use_prometheus = project.use_prometheus
8284
self.models = project.models.copy()
8385
self.custom_enums = project.custom_enums.copy()
8486

@@ -191,6 +193,7 @@ def get_project_spec(self) -> ProjectSpec:
191193
use_redis=self.use_redis,
192194
use_rabbitmq=self.use_rabbitmq,
193195
use_taskiq=self.use_taskiq,
196+
use_prometheus=self.use_prometheus,
194197
models=self.models,
195198
custom_enums=self.custom_enums,
196199
)

fastapi_forge/template/cookiecutter.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
"use_taskiq": {
2121
"default": true
2222
},
23+
"use_prometheus": {
24+
"default": true
25+
},
2326
"models": {
2427
"models": []
2528
},

fastapi_forge/template/{{cookiecutter.project_name}}/docker-compose.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ services:
5151
{{ cookiecutter.project_name|upper|replace('-', '_') }}_RABBITMQ_CONNECTION_POOL_SIZE: 2
5252
{{ cookiecutter.project_name|upper|replace('-', '_') }}_RABBITMQ_CHANNEL_POOL_SIZE: 10
5353
{% endif %}
54+
{%- if cookiecutter.use_rabbitmq -%}
55+
{{ cookiecutter.project_name|upper|replace('-', '_') }}_PROMETHEUS_ENABLED: true
56+
{% endif %}
5457
{%- if cookiecutter.use_alembic %}
5558
volumes:
5659
- ./migrations:/app/migrations
@@ -139,6 +142,17 @@ services:
139142
volumes:
140143
- {{ cookiecutter.project_name }}-rabbitmq-data:/var/lib/rabbitmq
141144
{% endif %}
145+
{%- if cookiecutter.use_prometheus -%}
146+
prometheus:
147+
image: prom/prometheus:latest
148+
restart: always
149+
volumes:
150+
- ./observability/prometheus/prometheus.yaml:/etc/prometheus/prometheus.yaml
151+
command:
152+
- "--config.file=/etc/prometheus/prometheus.yaml"
153+
ports:
154+
- 9090:9090
155+
{% endif %}
142156
{%- if cookiecutter.use_postgres or cookiecutter.use_redis or cookiecutter.use_rabbitmq %}
143157
volumes:
144158
{%- if cookiecutter.use_postgres %}

fastapi_forge/template/{{cookiecutter.project_name}}/forge-config.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ paths:
3333
enabled: {{cookiecutter.use_taskiq | lower}}
3434
paths:
3535
- src/services/taskiq
36+
37+
use_prometheus:
38+
enabled: {{cookiecutter.use_prometheus | lower}}
39+
paths:
40+
- observability/prometheus
3641

3742
constants:
3843
requires_all:
@@ -41,4 +46,12 @@ paths:
4146
paths:
4247
- src/constants.py
4348

49+
observability:
50+
requires_all:
51+
- use_prometheus
52+
paths:
53+
- observability
54+
55+
56+
4457

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
global:
2+
scrape_interval: 15s
3+
4+
scrape_configs:
5+
- job_name: "metrics"
6+
metrics_path: /metrics
7+
static_configs:
8+
- targets: ["{{ cookiecutter.project_name }}-api:8000"]

fastapi_forge/template/{{cookiecutter.project_name}}/pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ dependencies = [
4141
"taskiq-fastapi>=0.3.4",
4242
"orjson>=3.10.16",
4343
{%- endif %}
44+
{%- if cookiecutter.use_prometheus -%}
45+
"prometheus-fastapi-instrumentator>=7.1.0",
46+
{%- endif %}
4447
]
4548

4649
[tool.pytest.ini_options]
Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
11
from fastapi.middleware.cors import CORSMiddleware
22
from fastapi import FastAPI
3+
from src.settings import settings
4+
{% if cookiecutter.use_prometheus %}
5+
from prometheus_fastapi_instrumentator import Instrumentator
6+
{% endif %}
37

48
def _add_cors_middleware(app: FastAPI) -> None:
59
"""Add CORS Middleware."""
610
app.add_middleware(CORSMiddleware, allow_origins=["*"])
7-
8-
11+
{% if cookiecutter.use_prometheus %}
12+
def _add_prometheus_middleware(app: FastAPI) -> None:
13+
"""Add Prometheus Middleware."""
14+
if settings.prometheus.enabled:
15+
instrumenter = Instrumentator().instrument(app)
16+
instrumenter.expose(app)
17+
{% endif %}
918
def add_middleware(app: FastAPI) -> None:
1019
"""Add all middlewares."""
11-
12-
_add_cors_middleware(app)
20+
_add_cors_middleware(app)
21+
{%- if cookiecutter.use_prometheus %}
22+
_add_prometheus_middleware(app)
23+
{% endif %}

0 commit comments

Comments
 (0)