rjorgec commited on
Commit
f6b5e8d
·
unverified ·
1 Parent(s): c651e57

Add Prometheus metrics for Chord-Bot

Browse files
Files changed (1) hide show
  1. metrics.py +115 -0
metrics.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # metrics.py
2
+ import os
3
+ import time
4
+
5
+ from prometheus_client import (
6
+ Counter,
7
+ Histogram,
8
+ Gauge,
9
+ Summary,
10
+ start_http_server,
11
+ )
12
+
13
+ SERVICE_NAME = os.getenv("SERVICE_NAME", "chord-bot-local")
14
+
15
+ #tot requests by status
16
+ REQUEST_COUNT = Counter(
17
+ "chordbot_requests_total",
18
+ "Total number of Chord-Bot requests",
19
+ ["service", "endpoint", "status"], # status: success | invalid_input | error
20
+ )
21
+
22
+ #latency
23
+ REQUEST_LATENCY = Histogram(
24
+ "chordbot_request_latency_seconds",
25
+ "Latency of Chord-Bot requests in seconds",
26
+ ["service", "endpoint"],
27
+ )
28
+
29
+ # Number of note tokens per request
30
+ NOTES_PER_REQUEST = Histogram(
31
+ "chordbot_notes_per_request",
32
+ "Number of note tokens received per request",
33
+ ["service", "endpoint"],
34
+
35
+ buckets=(1, 2, 3, 4, 5, 6, 8, 12, 16),
36
+ )
37
+
38
+ INVALID_REQUESTS = Counter(
39
+ "chordbot_invalid_requests_total",
40
+ "Number of Chord-Bot requests with invalid input",
41
+ ["service", "endpoint"],
42
+ )
43
+
44
+ #counts of predicted chords by label
45
+ CHORD_PREDICTIONS = Counter(
46
+ "chordbot_chord_predictions_total",
47
+ "Number of times each chord label is predicted",
48
+ ["service", "endpoint", "chord_label"],
49
+ )
50
+
51
+ #how many requests
52
+ ACTIVE_REQUESTS = Gauge(
53
+ "chordbot_active_requests",
54
+ "Number of active Chord-Bot requests being processed",
55
+ ["service", "endpoint"],
56
+ )
57
+
58
+
59
+ def init_metrics(port: int = 8000, service_name: str | None = None) -> None:
60
+ """
61
+ Start the Prometheus metrics HTTP server on `port`.
62
+
63
+ Call this once at app startup (before serving requests).
64
+ """
65
+ global SERVICE_NAME
66
+
67
+ if service_name is not None:
68
+ SERVICE_NAME = service_name
69
+
70
+ #expose on http://0.0.0.0:port/metrics
71
+ start_http_server(port)
72
+ print(f"[metrics] Prometheus metrics server started on :{port} for service={SERVICE_NAME}")
73
+
74
+
75
+ def instrument_chord_request(endpoint: str, note_tokens, chord_label: str | None, status: str, elapsed_seconds: float) -> None:
76
+ """
77
+ Helper you can call from your endpoint / handler *after* processing a request.
78
+
79
+ Parameters:
80
+ endpoint - logical endpoint name, e.g. "analyze" or "predict"
81
+ note_tokens - list of parsed notes (e.g., ["C", "E", "G"]) or None
82
+ chord_label - predicted chord label (e.g., "Cmaj") or None if invalid/failed
83
+ status - "success", "invalid_input", or "error"
84
+ elapsed_seconds - wall-clock latency for the request
85
+ """
86
+
87
+ REQUEST_COUNT.labels(
88
+ service=SERVICE_NAME,
89
+ endpoint=endpoint,
90
+ status=status,
91
+ ).inc()
92
+
93
+ REQUEST_LATENCY.labels(
94
+ service=SERVICE_NAME,
95
+ endpoint=endpoint,
96
+ ).observe(elapsed_seconds)
97
+
98
+ if note_tokens is not None:
99
+ NOTES_PER_REQUEST.labels(
100
+ service=SERVICE_NAME,
101
+ endpoint=endpoint,
102
+ ).observe(len(note_tokens))
103
+
104
+ if status == "invalid_input":
105
+ INVALID_REQUESTS.labels(
106
+ service=SERVICE_NAME,
107
+ endpoint=endpoint,
108
+ ).inc()
109
+
110
+ if status == "success" and chord_label is not None:
111
+ CHORD_PREDICTIONS.labels(
112
+ service=SERVICE_NAME,
113
+ endpoint=endpoint,
114
+ chord_label=chord_label,
115
+ ).inc()