Prometheus ও Grafana
এই পাঠে যা শিখবেন
- Prometheus pull model + service discovery
- ৪ metric types — কোনটা কখন
- FastAPI-এ ML metrics instrumentation
- PromQL basics + Grafana dashboard
১ · Pull-based architecture
Prometheus standard pull model — service expose HTTP /metrics; Prometheus periodically scrape (15-60 sec interval)।
- Pros: no metric server-overload (scrape rate Prometheus-controlled)।
- Pros: service-discovery friendly (K8s, Consul)।
- Cons: short-lived job tricky (Pushgateway alternative)।
২ · Metric types
- Counter: monotonically increasing — request count, error count।
- Gauge: goes up/down — queue depth, model accuracy।
- Histogram: distribution — latency p50/p95/p99 observable।
- Summary: pre-computed quantile — like histogram but server-side।
৩ · FastAPI-এ ML metrics
from fastapi import FastAPI
from prometheus_fastapi_instrumentator import Instrumentator
from prometheus_client import Counter, Histogram, Gauge
app = FastAPI()
# ML-specific custom metrics
predictions_total = Counter(
"ml_predictions_total",
"Total predictions made",
["model_version", "label"],
)
prediction_confidence = Histogram(
"ml_prediction_confidence",
"Confidence distribution",
["model_version"],
buckets=[0.1, 0.3, 0.5, 0.7, 0.9, 1.0],
)
inference_latency = Histogram(
"ml_inference_latency_seconds",
"Model inference time",
["model_version"],
buckets=[0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0],
)
data_drift_psi = Gauge(
"ml_data_drift_psi",
"Population Stability Index per feature",
["feature"],
)
# Auto-instrument HTTP metrics
Instrumentator().instrument(app).expose(app)
@app.post("/predict")
def predict(req):
import time
start = time.perf_counter()
proba = model.predict_proba([req.text])[0]
label = str(proba.argmax())
confidence = float(proba.max())
elapsed = time.perf_counter() - start
predictions_total.labels(
model_version=MODEL_VERSION, label=label
).inc()
prediction_confidence.labels(
model_version=MODEL_VERSION
).observe(confidence)
inference_latency.labels(
model_version=MODEL_VERSION
).observe(elapsed)
return {"label": label, "confidence": confidence}
# /metrics endpoint auto-exposed by Instrumentator
৪ · Prometheus config
global:
scrape_interval: 30s
scrape_configs:
- job_name: 'ml-services'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
regex: '.*ml-.*'
action: keep
- job_name: 'sentiment-api'
static_configs:
- targets: ['sentiment-api:8000']
alerting:
alertmanagers:
- static_configs:
- targets: ['alertmanager:9093']
rule_files:
- 'ml_alerts.yml'
৫ · PromQL basics
rate(http_requests_total[5m])— RPS over 5 min।histogram_quantile(0.99, rate(ml_inference_latency_seconds_bucket[5m]))— p99 latency।sum by (model_version) (rate(ml_predictions_total[5m]))— RPS per version।avg_over_time(ml_data_drift_psi{feature="age"}[1h])— recent drift trend।
৬ · Alert rules
groups:
- name: ml-alerts
rules:
- alert: HighErrorRate
expr: |
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m])) > 0.01
for: 5m
labels: { severity: page }
annotations:
summary: "ML service error rate > 1%"
- alert: HighLatency
expr: |
histogram_quantile(0.99,
rate(ml_inference_latency_seconds_bucket[5m])
) > 0.2
for: 10m
labels: { severity: warn }
- alert: DriftDetected
expr: ml_data_drift_psi > 0.25
for: 1h
labels: { severity: warn }
annotations:
summary: "Feature {{ $labels.feature }} PSI = {{ $value }}"
- alert: PredictionDistributionShift
expr: |
abs(
sum(rate(ml_predictions_total{label="positive"}[1h]))
/ sum(rate(ml_predictions_total[1h]))
- 0.3
) > 0.1
for: 30m
labels: { severity: page }
for: 5m — sustained, not flap।
৭ · Grafana dashboards
- Service overview: RPS, error rate, p99 latency।
- Model performance: accuracy time-series, confidence distribution।
- Drift dashboard: per-feature PSI heatmap।
- Business KPI: conversion rate (separate metric pipeline)।
Grafana JSON-based dashboards — version-control git-এ। Reusable templates।
৮ · Cardinality care
Each unique label combination = separate metric। High-cardinality labels (user_id) = explosion।
- OK: model_version (~5), label (~10)।
- Bad: user_id (millions), full URL paths।
- Bound cardinality — bucket high-card values।
ভাবনার প্রশ্ন
প্র ০১"Prometheus vs Datadog/CloudWatch — Bangladesh team-এর জন্য?"
Cost vs convenience tradeoff।
Prometheus + Grafana (OSS):
- Free; self-host।
- Powerful PromQL।
- Wide K8s integration।
- Cons: ops overhead, retention storage।
Datadog (SaaS):
- Easy setup, polished UI।
- APM + log + metric one platform।
- Cost: $15-30/host/month rapidly accumulates।
- BD: large fintech use; smaller skip।
CloudWatch (AWS):
- AWS-native, integrated।
- Cost: per-metric per-dashboard charge।
- Custom metric expensive at scale।
BD adoption:
- ~80% Prometheus + Grafana।
- ~10% Datadog (enterprise)।
- ~5% CloudWatch (AWS-locked)।
মূল উপলব্ধি: Prometheus + Grafana cost-effective default। Managed alternatives convenience cost-justified at large scale।
প্র ০২"Cardinality bombs — কীভাবে avoid?"
Cardinality issue Prometheus practical disaster।
Common bombs:
- user_id label — millions।
- request_path full URL — combinatorial।
- request_id, session_id — unique each।
- high-precision timestamps as labels।
Symptoms:
- Prometheus memory explosion।
- Slow queries।
- Disk fill।
Prevention:
- Bucket high-card values: user_id_bucket = id % 100।
- Path normalize: /api/users/{id} → /api/users/_।
- Allow-list labels in CI lint।
- Cardinality monitor:
count by (__name__) ({__name__=~".*"})।
Detection:
- Prometheus's
tsdb-statuspage — top metrics by series। - Alert: series count growing fast।
Bangladesh real:
- One BD startup — request_path label exploded ৫০০K series, Prometheus crash।
- Fix: relabel + drop high-cardinality।
মূল উপলব্ধি: Cardinality awareness essential। Label design critical। Quarterly review series count।
প্র ০৩"Retention strategy — কত দিন keep?"
Storage cost vs historical value।
Default Prometheus:
- 15 days local storage।
- Sufficient most operational debugging।
Long-term storage:
- Thanos, Cortex, VictoriaMetrics — Prometheus + S3 backing।
- Year-long retention possible।
- Cost: tiered storage (hot/cold)।
What needs long retention:
- Compliance audit (Bangladesh Bank ICT 5 years)।
- Long-term trend (year-over-year)।
- Capacity planning।
Tiered:
- 15 days full granularity।
- 3 months downsampled (5-min average)।
- 1 year downsampled (1-hour average)।
- Storage 100× less।
BD context:
- Most teams 30-90 days local।
- Critical metrics export to BigQuery/Snowflake।
- Compliance separate audit trail।
মূল উপলব্ধি: Tiered retention smart cost. Downsample aggressively. Compliance separate from operational।
প্র ০৪"SLO/SLI design ML service-এ?"
SLI = Service Level Indicator (metric)। SLO = target। SLA = contract।
SLI examples ML:
- Availability: % requests successful (200 status)।
- Latency: % requests p99 < threshold।
- Quality: % predictions confidence > threshold।
- Freshness: % requests using model less than X days old।
SLO target:
- 99.9% availability — 43 min downtime/month।
- 99% latency < 100ms।
- Error budget: 100% - SLO = max budget acceptable।
Error budget concept:
- SLO 99.9% → 0.1% budget = 43 min/month।
- If month consumed, freeze deployments।
- Below budget: ship freely।
- Self-regulating tension between feature + reliability।
BD context — bKash payment:
- SLO 99.95% extreme reliability।
- 4 min/month budget tight।
- ML model service must align।
SLA careful:
- SLO internal target। SLA contract with customer (stricter or looser)।
- Penalty risk; underpromise overdeliver।
মূল উপলব্ধি: SLO/SLI/SLA discipline ML team graduate stage। Error budget reliability + speed balance।
অনুশীলন
- Instrument: উপরের code নিজের FastAPI ML service-এ apply।
/metricsদেখুন।pip install prometheus-fastapi-instrumentator; instrument; localhost:8000/metrics check। - Local Prometheus: Docker-এ Prometheus run; service scrape; Grafana add data source।
Compose with Prometheus + Grafana; prometheus.yml-এ static_configs target add; Grafana DS Prometheus add।
- চিন্তা: Pathao ride matching — ৫টি SLI define করুন।
- Availability: % match request 200।
- Latency: % p99 < 200ms।
- Match quality: % rides with confidence > 0.7।
- Freshness: % decisions using model < 24h old।
- Fairness: subgroup acceptance gap < 5%।