Skip to content

Commit bc58e78

Browse files
committed
refactor(metrics): use prometheus client and labels
1 parent dcf2dc4 commit bc58e78

File tree

7 files changed

+296
-349
lines changed

7 files changed

+296
-349
lines changed

app/metrics/daily_metrics_test.go

Lines changed: 55 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package metrics
22

33
import (
4-
"bytes"
54
"fmt"
5+
"net/http/httptest"
66
"strings"
77
"testing"
88
"time"
@@ -14,150 +14,85 @@ func TestDailyMetrics(t *testing.T) {
1414
AutoCleanup: false,
1515
})
1616

17-
today := time.Now().UTC().Format("2006-01-02")
18-
1917
// Test daily increment methods
2018
m.IncrementDaily("tool_calls_quotes")
2119
m.IncrementDaily("tool_calls_quotes")
2220
m.IncrementDailyBy("tool_calls_login", 3)
2321
m.IncrementDaily("tool_errors_quotes_api_error")
2422

25-
// Test regular increment (non-daily)
26-
m.Increment("legacy_counter")
23+
// Test that metrics were created by checking HTTP handler output
24+
handler := m.HTTPHandler()
25+
req := httptest.NewRequest("GET", "/metrics", nil)
26+
w := httptest.NewRecorder()
27+
handler(w, req)
2728

28-
// Check internal storage with date suffix
29-
expectedQuotesKey := fmt.Sprintf("tool_calls_quotes_%s", today)
30-
expectedLoginKey := fmt.Sprintf("tool_calls_login_%s", today)
31-
expectedErrorKey := fmt.Sprintf("tool_errors_quotes_api_error_%s", today)
29+
output := w.Body.String()
3230

33-
if got := m.GetCounterValue(expectedQuotesKey); got != 2 {
34-
t.Errorf("Expected tool_calls_quotes_%s = 2, got %d", today, got)
35-
}
36-
37-
if got := m.GetCounterValue(expectedLoginKey); got != 3 {
38-
t.Errorf("Expected tool_calls_login_%s = 3, got %d", today, got)
39-
}
31+
today := time.Now().UTC().Format("2006-01-02")
4032

41-
if got := m.GetCounterValue(expectedErrorKey); got != 1 {
42-
t.Errorf("Expected tool_errors_quotes_api_error_%s = 1, got %d", today, got)
33+
expectedMetrics := []struct {
34+
name string
35+
value string
36+
}{
37+
{"tool_calls_quotes", "2"}, // incremented twice
38+
{"tool_calls_login", "3"}, // incremented by 3
39+
{"tool_errors_quotes_api_error", "1"}, // incremented once
4340
}
4441

45-
if got := m.GetCounterValue("legacy_counter"); got != 1 {
46-
t.Errorf("Expected legacy_counter = 1, got %d", got)
42+
for _, metric := range expectedMetrics {
43+
expectedPattern := fmt.Sprintf(`%s{date="%s",service="test-service"} %s`, metric.name, today, metric.value)
44+
if !strings.Contains(output, expectedPattern) {
45+
t.Errorf("Expected output to contain: %s\nGot: %s", expectedPattern, output)
46+
}
4747
}
4848
}
4949

50-
func TestDailyMetricsPrometheusOutput(t *testing.T) {
50+
func TestDailyMetricsWithLabels(t *testing.T) {
5151
m := New(Config{
5252
ServiceName: "test-service",
5353
AutoCleanup: false,
5454
})
5555

56-
today := time.Now().UTC().Format("2006-01-02")
57-
58-
// Add some daily metrics
59-
m.IncrementDaily("tool_calls_quotes")
60-
m.IncrementDaily("tool_calls_quotes")
61-
m.IncrementDaily("tool_errors_quotes_api_error")
62-
63-
// Add a regular metric
64-
m.Increment("legacy_counter")
65-
66-
// Generate Prometheus output
67-
var buf bytes.Buffer
68-
m.WritePrometheus(&buf)
69-
output := buf.String()
70-
71-
// Check that daily metrics have date labels
72-
expectedQuotesLine := fmt.Sprintf(`tool_calls_quotes_total{date="%s",service="test-service"} 2`, today)
73-
expectedErrorLine := fmt.Sprintf(`tool_errors_quotes_api_error_total{date="%s",service="test-service"} 1`, today)
74-
expectedLegacyLine := `legacy_counter_total{service="test-service"} 1`
75-
76-
if !strings.Contains(output, expectedQuotesLine) {
77-
t.Errorf("Expected output to contain: %s\nGot: %s", expectedQuotesLine, output)
78-
}
79-
80-
if !strings.Contains(output, expectedErrorLine) {
81-
t.Errorf("Expected output to contain: %s\nGot: %s", expectedErrorLine, output)
82-
}
83-
84-
if !strings.Contains(output, expectedLegacyLine) {
85-
t.Errorf("Expected output to contain: %s\nGot: %s", expectedLegacyLine, output)
86-
}
87-
}
88-
89-
func TestIsDailyMetric(t *testing.T) {
90-
m := New(Config{ServiceName: "test"})
91-
92-
tests := []struct {
93-
key string
94-
expected bool
95-
}{
96-
{"tool_calls_quotes_2025-08-05", true},
97-
{"tool_errors_login_session_error_2025-12-31", true},
98-
{"legacy_counter", false},
99-
{"tool_calls_quotes", false},
100-
{"tool_calls_quotes_20250805", false}, // Wrong date format
101-
{"tool_calls_quotes_2025-8-5", false}, // Wrong date format
102-
{"", false},
103-
{"_2025-08-05", false}, // Empty base name
104-
}
105-
106-
for _, tt := range tests {
107-
t.Run(tt.key, func(t *testing.T) {
108-
if got := m.isDailyMetric(tt.key); got != tt.expected {
109-
t.Errorf("isDailyMetric(%q) = %v, want %v", tt.key, got, tt.expected)
110-
}
111-
})
112-
}
113-
}
56+
m.IncrementDailyWithLabels("tool_calls", map[string]string{
57+
"tool": "quotes",
58+
"session_type": "mcp",
59+
})
60+
m.IncrementDailyWithLabels("tool_calls", map[string]string{
61+
"tool": "quotes",
62+
"session_type": "mcp",
63+
})
11464

115-
func TestParseDailyMetric(t *testing.T) {
116-
m := New(Config{ServiceName: "test"})
65+
m.IncrementDailyWithLabels("tool_errors", map[string]string{
66+
"tool": "quotes",
67+
"error_type": "api_error",
68+
"session_type": "mcp",
69+
})
11770

118-
tests := []struct {
119-
key string
120-
expectedBase string
121-
expectedDate string
122-
}{
123-
{"tool_calls_quotes_2025-08-05", "tool_calls_quotes", "2025-08-05"},
124-
{"tool_errors_login_session_error_2025-12-31", "tool_errors_login_session_error", "2025-12-31"},
125-
{"legacy_counter", "", ""}, // Not a daily metric
126-
{"tool_calls_quotes_20250805", "", ""}, // Wrong date format
127-
}
71+
handler := m.HTTPHandler()
72+
req := httptest.NewRequest("GET", "/metrics", nil)
73+
w := httptest.NewRecorder()
74+
handler(w, req)
12875

129-
for _, tt := range tests {
130-
t.Run(tt.key, func(t *testing.T) {
131-
gotBase, _, gotDate := m.parseDailyMetric(tt.key)
132-
if gotBase != tt.expectedBase || gotDate != tt.expectedDate {
133-
t.Errorf("parseDailyMetric(%q) = (%q, %q), want (%q, %q)",
134-
tt.key, gotBase, gotDate, tt.expectedBase, tt.expectedDate)
135-
}
136-
})
137-
}
76+
output := w.Body.String()
77+
today := time.Now().UTC().Format("2006-01-02")
13878

139-
// Test session type parsing
140-
sessionTypeTests := []struct {
141-
key string
142-
expectedBase string
143-
expectedSession string
144-
expectedDate string
79+
expectedPatterns := []struct {
80+
description string
81+
pattern string
14582
}{
146-
{"tool_calls_quotes_sse_2025-08-05", "tool_calls_quotes", "sse", "2025-08-05"},
147-
{"tool_calls_quotes_mcp_2025-08-05", "tool_calls_quotes", "mcp", "2025-08-05"},
148-
{"tool_calls_quotes_stdio_2025-08-05", "tool_calls_quotes", "stdio", "2025-08-05"},
149-
{"tool_calls_quotes_unknown_2025-08-05", "tool_calls_quotes", "unknown", "2025-08-05"},
150-
{"tool_calls_quotes_2025-08-05", "tool_calls_quotes", "", "2025-08-05"}, // No session type
151-
{"tool_errors_login_session_error_sse_2025-12-31", "tool_errors_login_session_error", "sse", "2025-12-31"},
83+
{
84+
"tool calls with correct value and labels",
85+
fmt.Sprintf(`tool_calls_total{date="%s",service="test-service",session_type="mcp",tool="quotes"} 2`, today),
86+
},
87+
{
88+
"tool errors with correct value and labels",
89+
fmt.Sprintf(`tool_errors_total{date="%s",error_type="api_error",service="test-service",session_type="mcp",tool="quotes"} 1`, today),
90+
},
15291
}
15392

154-
for _, tt := range sessionTypeTests {
155-
t.Run(tt.key+"_session_type", func(t *testing.T) {
156-
gotBase, gotSession, gotDate := m.parseDailyMetric(tt.key)
157-
if gotBase != tt.expectedBase || gotSession != tt.expectedSession || gotDate != tt.expectedDate {
158-
t.Errorf("parseDailyMetric(%q) = (%q, %q, %q), want (%q, %q, %q)",
159-
tt.key, gotBase, gotSession, gotDate, tt.expectedBase, tt.expectedSession, tt.expectedDate)
160-
}
161-
})
93+
for _, expected := range expectedPatterns {
94+
if !strings.Contains(output, expected.pattern) {
95+
t.Errorf("Expected output to contain %s: %s\nFull output: %s", expected.description, expected.pattern, output)
96+
}
16297
}
16398
}

0 commit comments

Comments
 (0)