Skip to content

Commit 8755407

Browse files
committed
Make details a slice instead of map
1 parent 04991e5 commit 8755407

10 files changed

Lines changed: 50 additions & 87 deletions

File tree

internal/evaluator/cache.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func EvaluateCacheHit(rule rules.Rule, metrics parser.MetricsData, loadLevel rul
1313
result := rules.EvaluationResult{
1414
RuleName: rule.DisplayName,
1515
Status: rules.StatusGreen,
16-
Details: make(map[string]interface{}),
16+
Details: []string{},
1717
Timestamp: time.Now(),
1818
}
1919

internal/evaluator/composite.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ func EvaluateComposite(rule rules.Rule, metrics parser.MetricsData, loadLevel ru
1414
result := rules.EvaluationResult{
1515
RuleName: rule.DisplayName,
1616
Status: rules.StatusGreen,
17-
Details: make(map[string]interface{}),
17+
Details: []string{},
1818
Timestamp: time.Now(),
1919
}
2020

@@ -33,7 +33,7 @@ func EvaluateComposite(rule rules.Rule, metrics parser.MetricsData, loadLevel ru
3333
}
3434
value, _ := metric.GetSingleValue()
3535
metricValues[metricDef.Name] = value
36-
result.Details[metricDef.Name] = value
36+
result.Details = append(result.Details, fmt.Sprintf("%s: %.3f", metricDef.Name, value))
3737
}
3838

3939
// Evaluate checks in order

internal/evaluator/gauge.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ func EvaluateGauge(rule rules.Rule, metrics parser.MetricsData, loadLevel rules.
1515
result := rules.EvaluationResult{
1616
RuleName: rule.MetricName,
1717
Status: rules.StatusGreen,
18-
Details: make(map[string]interface{}),
18+
Details: []string{},
1919
Timestamp: time.Now(),
2020
}
2121

internal/evaluator/histogram.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func EvaluateHistogram(rule rules.Rule, metrics parser.MetricsData, loadLevel ru
1616
result := rules.EvaluationResult{
1717
RuleName: rule.MetricName,
1818
Status: rules.StatusGreen,
19-
Details: make(map[string]interface{}),
19+
Details: []string{},
2020
Timestamp: time.Now(),
2121
}
2222

@@ -65,9 +65,11 @@ func EvaluateHistogram(rule rules.Rule, metrics parser.MetricsData, loadLevel ru
6565
}
6666

6767
result.Value = p95
68-
result.Details["p95"] = p95
69-
result.Details["p99"] = p99
70-
result.Details["count"] = totalCount
68+
result.Details = append(result.Details,
69+
fmt.Sprintf("p95: %.3f", p95),
70+
fmt.Sprintf("p99: %.3f", p99),
71+
fmt.Sprintf("count: %.0f", totalCount),
72+
)
7173

7274
// Select thresholds based on load level
7375
thresholds := selectThresholds(rule, loadLevel)
@@ -120,7 +122,7 @@ func evaluateSingleHistogramInfOverflow(baseName string, metrics parser.MetricsD
120122
result := &rules.EvaluationResult{
121123
RuleName: baseName + " (+Inf overflow check)",
122124
Status: rules.StatusGreen,
123-
Details: make(map[string]interface{}),
125+
Details: []string{},
124126
Timestamp: time.Now(),
125127
}
126128

@@ -211,10 +213,17 @@ func evaluateSingleHistogramInfOverflow(baseName string, metrics parser.MetricsD
211213
}
212214

213215
result.Status = worstStatus
214-
result.Details["Total Number of Observations"] = formatHumanNumber(worstTotalCount)
215-
result.Details["Observations in +Inf bucket"] = formatHumanNumber(worstInfObservations)
216-
result.Details["Percentage of observations in +Inf bucket"] = formatHumanNumber(worstInfPercentage) + " %"
217-
result.Details["Highest non-infinity bucket"] = formatHumanNumber(worstHighestFiniteLe) + " units"
216+
if baseMetric, ok := metrics.GetMetric(baseName); ok && baseMetric.Help != "" {
217+
result.Details = append(result.Details, "Metric Description: "+baseMetric.Help)
218+
} else if bucketMetric, ok := metrics.GetMetric(baseName + "_bucket"); ok && bucketMetric.Help != "" {
219+
result.Details = append(result.Details, "Metric Description: "+bucketMetric.Help)
220+
}
221+
result.Details = append(result.Details,
222+
"Total Number of Observations: "+formatHumanNumber(worstTotalCount)+" unit",
223+
"Observations in +Inf bucket: "+formatHumanNumber(worstInfObservations)+" unit",
224+
"Percentage of observations in +Inf bucket: "+formatHumanNumber(worstInfPercentage)+" %",
225+
"Highest non-infinity bucket: "+formatHumanNumber(worstHighestFiniteLe)+" unit",
226+
)
218227

219228
// Build message based on worst case
220229
result.Message = fmt.Sprintf("%s%% of observations in +Inf bucket (acceptable). Highest non-infinity bucket: %s",
@@ -247,7 +256,7 @@ func getSeriesKey(labels map[string]string) string {
247256
}
248257

249258
func formatHumanNumber(value float64) string {
250-
raw := strconv.FormatFloat(value, 'f', -1, 64)
259+
raw := strconv.FormatFloat(value, 'f', 2, 64)
251260
sign := ""
252261
if strings.HasPrefix(raw, "-") {
253262
sign = "-"

internal/evaluator/percentage.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func EvaluatePercentage(rule rules.Rule, metrics parser.MetricsData, loadLevel r
1313
result := rules.EvaluationResult{
1414
RuleName: rule.DisplayName,
1515
Status: rules.StatusGreen,
16-
Details: make(map[string]interface{}),
16+
Details: []string{},
1717
Timestamp: time.Now(),
1818
}
1919

internal/evaluator/queue.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ func EvaluateQueue(rule rules.Rule, metrics parser.MetricsData, loadLevel rules.
1313
result := rules.EvaluationResult{
1414
RuleName: rule.MetricName,
1515
Status: rules.StatusGreen,
16-
Details: make(map[string]interface{}),
16+
Details: []string{},
1717
Timestamp: time.Now(),
1818
}
1919

internal/reporter/console.go

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bytes"
55
"fmt"
66
"os"
7-
"slices"
87
"strings"
98

109
"github.com/fatih/color"
@@ -67,21 +66,20 @@ func GenerateConsole(report rules.AnalysisReport) string {
6766
result.WriteString(color.RedString(" Status: RED\n"))
6867
result.WriteString(fmt.Sprintf(" Message: %s\n", r.Message))
6968
if len(r.Details) > 0 {
70-
result.WriteString(" Details:\n")
71-
keys := make([]string, 0, len(r.Details))
72-
for k := range r.Details {
73-
keys = append(keys, k)
74-
}
75-
slices.Sort(keys)
76-
for _, k := range keys {
77-
result.WriteString(fmt.Sprintf(" %s: %v\n", k, r.Details[k]))
69+
result.WriteString(color.New(color.FgYellow).Sprint(" Details:\n"))
70+
for _, detail := range r.Details {
71+
result.WriteString(fmt.Sprintf(" %s\n", detail))
7872
}
7973
}
8074
if r.PotentialActionUser != "" {
81-
result.WriteString(color.New(color.FgYellow).Sprintf(" Potential action: %s\n", r.PotentialActionUser))
75+
result.WriteString(fmt.Sprintf(" %s %s\n",
76+
color.New(color.FgYellow).Sprint("Potential action:"),
77+
r.PotentialActionUser))
8278
}
8379
if r.PotentialActionDeveloper != "" {
84-
result.WriteString(color.New(color.FgYellow).Sprintf(" Potential action (developer): %s\n", r.PotentialActionDeveloper))
80+
result.WriteString(fmt.Sprintf(" %s %s\n",
81+
color.New(color.FgYellow).Sprint("Potential action (developer):"),
82+
r.PotentialActionDeveloper))
8583
}
8684
result.WriteString("\n")
8785
}
@@ -96,21 +94,20 @@ func GenerateConsole(report rules.AnalysisReport) string {
9694
result.WriteString(color.YellowString(" Status: YELLOW\n"))
9795
result.WriteString(fmt.Sprintf(" Message: %s\n", r.Message))
9896
if len(r.Details) > 0 {
99-
result.WriteString(" Details:\n")
100-
keys := make([]string, 0, len(r.Details))
101-
for k := range r.Details {
102-
keys = append(keys, k)
103-
}
104-
slices.Sort(keys)
105-
for _, k := range keys {
106-
result.WriteString(fmt.Sprintf(" %s: %v\n", k, r.Details[k]))
97+
result.WriteString(color.New(color.FgYellow).Sprint(" Details:\n"))
98+
for _, detail := range r.Details {
99+
result.WriteString(fmt.Sprintf(" %s\n", detail))
107100
}
108101
}
109102
if r.PotentialActionUser != "" {
110-
result.WriteString(color.New(color.FgYellow).Sprintf(" Potential action: %s\n", r.PotentialActionUser))
103+
result.WriteString(fmt.Sprintf(" %s %s\n",
104+
color.New(color.FgYellow).Sprint("Potential action:"),
105+
r.PotentialActionUser))
111106
}
112107
if r.PotentialActionDeveloper != "" {
113-
result.WriteString(color.New(color.FgYellow).Sprintf(" Potential action (developer): %s\n", r.PotentialActionDeveloper))
108+
result.WriteString(fmt.Sprintf(" %s %s\n",
109+
color.New(color.FgYellow).Sprint("Potential action (developer):"),
110+
r.PotentialActionDeveloper))
114111
}
115112
result.WriteString("\n")
116113
}

internal/reporter/markdown.go

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,8 @@ func generateMarkdownDefault(report rules.AnalysisReport) string {
4949
result += "**Message:** " + r.Message + "\n"
5050
if len(r.Details) > 0 {
5151
result += "**Details:**\n"
52-
keys := make([]string, 0, len(r.Details))
53-
for k := range r.Details {
54-
keys = append(keys, k)
55-
}
56-
sort.Strings(keys)
57-
for _, k := range keys {
58-
result += "- " + k + ": " + fmt.Sprintf("%v", r.Details[k]) + "\n"
52+
for _, detail := range r.Details {
53+
result += "- " + detail + "\n"
5954
}
6055
}
6156
if r.PotentialActionUser != "" {
@@ -78,13 +73,8 @@ func generateMarkdownDefault(report rules.AnalysisReport) string {
7873
result += "**Message:** " + r.Message + "\n"
7974
if len(r.Details) > 0 {
8075
result += "**Details:**\n"
81-
keys := make([]string, 0, len(r.Details))
82-
for k := range r.Details {
83-
keys = append(keys, k)
84-
}
85-
sort.Strings(keys)
86-
for _, k := range keys {
87-
result += "- " + k + ": " + fmt.Sprintf("%v", r.Details[k]) + "\n"
76+
for _, detail := range r.Details {
77+
result += "- " + detail + "\n"
8878
}
8979
}
9080
if r.PotentialActionUser != "" {

internal/rules/types.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ type EvaluationResult struct {
193193
Status Status
194194
Message string
195195
Value float64
196-
Details map[string]interface{}
196+
Details []string
197197
Remediation string // Legacy field (use PotentialActionUser/Developer)
198198
PotentialActionUser string
199199
PotentialActionDeveloper string

internal/tui/view.go

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package tui
22

33
import (
44
"fmt"
5-
"sort"
65
"strings"
76

87
"github.com/charmbracelet/lipgloss"
@@ -239,41 +238,9 @@ func (m Model) viewDetail() string {
239238
detail.WriteString(detailLabelStyle.Render("Details:"))
240239
detail.WriteString("\n")
241240

242-
// Sort keys for consistent ordering
243-
keys := make([]string, 0, len(result.Details))
244-
for k := range result.Details {
245-
keys = append(keys, k)
246-
}
247-
sort.Strings(keys)
248-
249241
// Display details in plain text format (no ANSI codes) for easy selection/copying
250-
for _, k := range keys {
251-
v := result.Details[k]
252-
// Format the value nicely
253-
var formattedValue string
254-
switch val := v.(type) {
255-
case float64:
256-
// Format floats with appropriate precision
257-
if val >= 1000000 {
258-
formattedValue = fmt.Sprintf("%.0f", val)
259-
} else if val >= 1000 {
260-
formattedValue = fmt.Sprintf("%.0f", val)
261-
} else if val >= 1 {
262-
formattedValue = fmt.Sprintf("%.2f", val)
263-
} else {
264-
formattedValue = fmt.Sprintf("%.4f", val)
265-
}
266-
case int:
267-
formattedValue = fmt.Sprintf("%d", val)
268-
case int64:
269-
formattedValue = fmt.Sprintf("%d", val)
270-
default:
271-
// For other types, convert to string as-is (no truncation)
272-
formattedValue = fmt.Sprintf("%v", v)
273-
}
274-
275-
// Plain text format: key: value (completely plain text for easy copying)
276-
detail.WriteString(fmt.Sprintf(" %s: %s\n", k, formattedValue))
242+
for _, detailLine := range result.Details {
243+
detail.WriteString(fmt.Sprintf(" %s\n", detailLine))
277244
}
278245
detail.WriteString("\n")
279246
}

0 commit comments

Comments
 (0)