Skip to content

Commit badfb63

Browse files
feat: enhance monitor info with live status, summary metrics, and assertions (#20)
- Fix missing fields in httpMonitorToLocal/tcpMonitorToLocal (DegradedAfter, Body, Headers, Assertions) - Add parallel GetMonitorStatus and GetMonitorSummary RPC calls with graceful degradation - Display global status (active/degraded/error) color-coded in config table - Add per-region status table with provider labels - Add summary metrics table (success/degraded/failed counts, P50-P99 latency, last ping) - Add assertions table for HTTP monitors - Add --time-range flag (1d/7d/14d) for summary period selection - New JSON output wrapper struct with monitor, status, regions, and summary sections Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 8525485 commit badfb63

3 files changed

Lines changed: 501 additions & 74 deletions

File tree

internal/monitors/monitor_create.go

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -68,19 +68,53 @@ func httpMonitorToLocal(m *monitorv1.HTTPMonitor) (Monitor, error) {
6868
if err != nil {
6969
return Monitor{}, fmt.Errorf("invalid monitor ID %q: %w", m.GetId(), err)
7070
}
71+
72+
var headers []Header
73+
for _, h := range m.GetHeaders() {
74+
headers = append(headers, Header{Key: h.GetKey(), Value: h.GetValue()})
75+
}
76+
77+
var assertions []Assertion
78+
for _, a := range m.GetStatusCodeAssertions() {
79+
assertions = append(assertions, Assertion{
80+
Type: "status_code",
81+
Compare: string(convertNumberComparator(a.GetComparator())),
82+
Target: int(a.GetTarget()),
83+
})
84+
}
85+
for _, a := range m.GetBodyAssertions() {
86+
assertions = append(assertions, Assertion{
87+
Type: "text_body",
88+
Compare: string(convertStringComparator(a.GetComparator())),
89+
Target: a.GetTarget(),
90+
})
91+
}
92+
for _, a := range m.GetHeaderAssertions() {
93+
assertions = append(assertions, Assertion{
94+
Type: "header",
95+
Compare: string(convertStringComparator(a.GetComparator())),
96+
Target: a.GetTarget(),
97+
Key: a.GetKey(),
98+
})
99+
}
100+
71101
return Monitor{
72-
ID: id,
73-
Name: m.GetName(),
74-
Description: m.GetDescription(),
75-
URL: m.GetUrl(),
76-
Periodicity: periodicityToString(m.GetPeriodicity()),
77-
Method: httpMethodToString(m.GetMethod()),
78-
Regions: regionsToStrings(m.GetRegions()),
79-
Active: m.GetActive(),
80-
Public: m.GetPublic(),
81-
Timeout: int(m.GetTimeout()),
82-
Retry: int(m.GetRetry()),
83-
JobType: "http",
102+
ID: id,
103+
Name: m.GetName(),
104+
Description: m.GetDescription(),
105+
URL: m.GetUrl(),
106+
Periodicity: periodicityToString(m.GetPeriodicity()),
107+
Method: httpMethodToString(m.GetMethod()),
108+
Regions: regionsToStrings(m.GetRegions()),
109+
Active: m.GetActive(),
110+
Public: m.GetPublic(),
111+
Timeout: int(m.GetTimeout()),
112+
DegradedAfter: int(m.GetDegradedAt()),
113+
Body: m.GetBody(),
114+
Headers: headers,
115+
Assertions: assertions,
116+
Retry: int(m.GetRetry()),
117+
JobType: "http",
84118
}, nil
85119
}
86120

@@ -90,17 +124,18 @@ func tcpMonitorToLocal(m *monitorv1.TCPMonitor) (Monitor, error) {
90124
return Monitor{}, fmt.Errorf("invalid monitor ID %q: %w", m.GetId(), err)
91125
}
92126
return Monitor{
93-
ID: id,
94-
Name: m.GetName(),
95-
Description: m.GetDescription(),
96-
URL: m.GetUri(),
97-
Periodicity: periodicityToString(m.GetPeriodicity()),
98-
Regions: regionsToStrings(m.GetRegions()),
99-
Active: m.GetActive(),
100-
Public: m.GetPublic(),
101-
Timeout: int(m.GetTimeout()),
102-
Retry: int(m.GetRetry()),
103-
JobType: "tcp",
127+
ID: id,
128+
Name: m.GetName(),
129+
Description: m.GetDescription(),
130+
URL: m.GetUri(),
131+
Periodicity: periodicityToString(m.GetPeriodicity()),
132+
Regions: regionsToStrings(m.GetRegions()),
133+
Active: m.GetActive(),
134+
Public: m.GetPublic(),
135+
Timeout: int(m.GetTimeout()),
136+
DegradedAfter: int(m.GetDegradedAt()),
137+
Retry: int(m.GetRetry()),
138+
JobType: "tcp",
104139
}, nil
105140
}
106141

0 commit comments

Comments
 (0)