@@ -20,6 +20,7 @@ import (
2020
2121var Version = "dev"
2222
23+ // CLI flags
2324type CLI struct {
2425 Endpoint string `help:"Metrics endpoint to poll" short:"x" env:"MET_ENDPOINT"`
2526 Interval time.Duration `help:"Poll interval" default:"2s" short:"s" env:"MET_INTERVAL"`
@@ -71,12 +72,10 @@ type model struct {
7172 includes []string
7273 excludes []string
7374 labelFilters []labelFilter
74-
75- showGraph bool
75+ showGraph bool
7676}
7777
7878type tickMsg time.Time
79-
8079type metricsMsg struct {
8180 families map [string ]* dto.MetricFamily
8281 err error
@@ -180,10 +179,8 @@ func (m model) renderList() string {
180179 cursor = ">"
181180 }
182181
183- var valStr string
184- if md .isCounter {
185- valStr = fmt .Sprintf ("%.2f" , md .lastScrapedVal )
186- } else {
182+ valStr := fmt .Sprintf ("%.2f" , md .lastScrapedVal )
183+ if ! md .isCounter {
187184 valStr = fmt .Sprintf ("%.2f" , md .gaugeVal )
188185 }
189186
@@ -200,11 +197,9 @@ func (m model) renderList() string {
200197 incDiffStr = "--"
201198 }
202199
203- var totalDiffStr string
200+ totalDiffStr := "--"
204201 if md .isCounter {
205202 totalDiffStr = fmt .Sprintf ("%.2f" , md .accumVal )
206- } else {
207- totalDiffStr = "--"
208203 }
209204
210205 keyStr := fmt .Sprintf ("%s %s" , cursor , md .key )
@@ -233,6 +228,8 @@ func (m model) renderGraph() string {
233228 return graph
234229}
235230
231+ // ---------- Fetch & Tick Commands ----------
232+
236233func fetchMetricsCmd (endpoint string ) tea.Cmd {
237234 return func () tea.Msg {
238235 fams , err := scrapeMetrics (endpoint )
@@ -263,6 +260,8 @@ func scrapeMetrics(url string) (map[string]*dto.MetricFamily, error) {
263260 return parser .TextToMetricFamilies (resp .Body )
264261}
265262
263+ // ---------- Updating Logic ----------
264+
266265func updateMetrics (m model , families map [string ]* dto.MetricFamily ) model {
267266 if m .metricsIndex == nil {
268267 m .metricsIndex = make (map [string ]int )
@@ -281,42 +280,42 @@ func updateMetrics(m model, families map[string]*dto.MetricFamily) model {
281280 continue
282281 }
283282
283+ raw := getRawValue (mf , pm )
284284 idx , found := m .metricsIndex [key ]
285285 if ! found {
286+ // It's brand new. Initialize so the first incremental diff is 0.
286287 md := metricData {
287288 key : key ,
288289 name : name ,
289290 labels : lblStr ,
290291 isCounter : mf .GetType () == dto .MetricType_COUNTER ,
291292 }
293+ if md .isCounter {
294+ md .prevVal = raw // make first diff = 0
295+ md .lastScrapedVal = raw // for the table's "Value"
296+ md .lastDelta = 0 // no increment yet
297+ // accumVal remains 0 until next scrape
298+ } else {
299+ md .gaugeVal = raw
300+ }
301+
292302 m .metricsList = append (m .metricsList , md )
293303 idx = len (m .metricsList ) - 1
294304 m .metricsIndex [key ] = idx
295305 }
296306
297307 md := m .metricsList [idx ]
298- var raw float64
299- switch mf .GetType () {
300- case dto .MetricType_COUNTER :
301- raw = pm .GetCounter ().GetValue ()
302- case dto .MetricType_GAUGE :
303- raw = pm .GetGauge ().GetValue ()
304- case dto .MetricType_UNTYPED :
305- raw = pm .GetUntyped ().GetValue ()
306- case dto .MetricType_SUMMARY :
307- raw = pm .GetSummary ().GetSampleSum ()
308- case dto .MetricType_HISTOGRAM :
309- raw = pm .GetHistogram ().GetSampleSum ()
310- }
311-
312308 if md .isCounter {
313309 diff := raw - md .prevVal
314310 if diff < 0 {
311+ // If the counter reset or decreased
315312 md .accumVal += raw
316313 md .lastDelta = raw
317314 } else if diff > 0 {
318315 md .accumVal += diff
319316 md .lastDelta = diff
317+ } else {
318+ // diff == 0 => no increment
320319 }
321320 md .prevVal = raw
322321 md .lastScrapedVal = raw
@@ -353,6 +352,26 @@ func updateMetrics(m model, families map[string]*dto.MetricFamily) model {
353352 return m
354353}
355354
355+ // getRawValue extracts the numeric value from a Prometheus metric family for a single Metric.
356+ func getRawValue (mf * dto.MetricFamily , pm * dto.Metric ) float64 {
357+ switch mf .GetType () {
358+ case dto .MetricType_COUNTER :
359+ return pm .GetCounter ().GetValue ()
360+ case dto .MetricType_GAUGE :
361+ return pm .GetGauge ().GetValue ()
362+ case dto .MetricType_UNTYPED :
363+ return pm .GetUntyped ().GetValue ()
364+ case dto .MetricType_SUMMARY :
365+ return pm .GetSummary ().GetSampleSum ()
366+ case dto .MetricType_HISTOGRAM :
367+ return pm .GetHistogram ().GetSampleSum ()
368+ default :
369+ return 0
370+ }
371+ }
372+
373+ // ---------- Filtering ----------
374+
356375func (m model ) passNameFilters (metricName string ) bool {
357376 if len (m .includes ) > 0 {
358377 matchedAny := false
0 commit comments