refact "cscli metrics" part 2 (#2806)
This commit is contained in:
parent
5ff8a03195
commit
81acad0d66
2 changed files with 155 additions and 148 deletions
|
@ -19,6 +19,27 @@ import (
|
|||
"github.com/crowdsecurity/go-cs-lib/trace"
|
||||
)
|
||||
|
||||
type (
|
||||
statAcquis map[string]map[string]int
|
||||
statParser map[string]map[string]int
|
||||
statBucket map[string]map[string]int
|
||||
statLapi map[string]map[string]int
|
||||
statLapiMachine map[string]map[string]map[string]int
|
||||
statLapiBouncer map[string]map[string]map[string]int
|
||||
statLapiDecision map[string]struct {
|
||||
NonEmpty int
|
||||
Empty int
|
||||
}
|
||||
statDecision map[string]map[string]map[string]int
|
||||
statAppsecEngine map[string]map[string]int
|
||||
statAppsecRule map[string]map[string]map[string]int
|
||||
statAlert map[string]int
|
||||
statStash map[string]struct {
|
||||
Type string
|
||||
Count int
|
||||
}
|
||||
)
|
||||
|
||||
type cliMetrics struct {
|
||||
cfg configGetter
|
||||
}
|
||||
|
@ -29,7 +50,6 @@ func NewCLIMetrics(getconfig configGetter) *cliMetrics {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// FormatPrometheusMetrics is a complete rip from prom2json
|
||||
func FormatPrometheusMetrics(out io.Writer, url string, formatType string, noUnit bool) error {
|
||||
mfChan := make(chan *dto.MetricFamily, 1024)
|
||||
|
@ -63,24 +83,19 @@ func FormatPrometheusMetrics(out io.Writer, url string, formatType string, noUni
|
|||
|
||||
log.Debugf("Finished reading prometheus output, %d entries", len(result))
|
||||
/*walk*/
|
||||
lapi_decisions_stats := map[string]struct {
|
||||
NonEmpty int
|
||||
Empty int
|
||||
}{}
|
||||
acquis_stats := map[string]map[string]int{}
|
||||
parsers_stats := map[string]map[string]int{}
|
||||
buckets_stats := map[string]map[string]int{}
|
||||
lapi_stats := map[string]map[string]int{}
|
||||
lapi_machine_stats := map[string]map[string]map[string]int{}
|
||||
lapi_bouncer_stats := map[string]map[string]map[string]int{}
|
||||
decisions_stats := map[string]map[string]map[string]int{}
|
||||
appsec_engine_stats := map[string]map[string]int{}
|
||||
appsec_rule_stats := map[string]map[string]map[string]int{}
|
||||
alerts_stats := map[string]int{}
|
||||
stash_stats := map[string]struct {
|
||||
Type string
|
||||
Count int
|
||||
}{}
|
||||
|
||||
mAcquis := statAcquis{}
|
||||
mParser := statParser{}
|
||||
mBucket := statBucket{}
|
||||
mLapi := statLapi{}
|
||||
mLapiMachine := statLapiMachine{}
|
||||
mLapiBouncer := statLapiBouncer{}
|
||||
mLapiDecision := statLapiDecision{}
|
||||
mDecision := statDecision{}
|
||||
mAppsecEngine := statAppsecEngine{}
|
||||
mAppsecRule := statAppsecRule{}
|
||||
mAlert := statAlert{}
|
||||
mStash := statStash{}
|
||||
|
||||
for idx, fam := range result {
|
||||
if !strings.HasPrefix(fam.Name, "cs_") {
|
||||
|
@ -127,138 +142,138 @@ func FormatPrometheusMetrics(out io.Writer, url string, formatType string, noUni
|
|||
switch fam.Name {
|
||||
/*buckets*/
|
||||
case "cs_bucket_created_total":
|
||||
if _, ok := buckets_stats[name]; !ok {
|
||||
buckets_stats[name] = make(map[string]int)
|
||||
if _, ok := mBucket[name]; !ok {
|
||||
mBucket[name] = make(map[string]int)
|
||||
}
|
||||
buckets_stats[name]["instantiation"] += ival
|
||||
mBucket[name]["instantiation"] += ival
|
||||
case "cs_buckets":
|
||||
if _, ok := buckets_stats[name]; !ok {
|
||||
buckets_stats[name] = make(map[string]int)
|
||||
if _, ok := mBucket[name]; !ok {
|
||||
mBucket[name] = make(map[string]int)
|
||||
}
|
||||
buckets_stats[name]["curr_count"] += ival
|
||||
mBucket[name]["curr_count"] += ival
|
||||
case "cs_bucket_overflowed_total":
|
||||
if _, ok := buckets_stats[name]; !ok {
|
||||
buckets_stats[name] = make(map[string]int)
|
||||
if _, ok := mBucket[name]; !ok {
|
||||
mBucket[name] = make(map[string]int)
|
||||
}
|
||||
buckets_stats[name]["overflow"] += ival
|
||||
mBucket[name]["overflow"] += ival
|
||||
case "cs_bucket_poured_total":
|
||||
if _, ok := buckets_stats[name]; !ok {
|
||||
buckets_stats[name] = make(map[string]int)
|
||||
if _, ok := mBucket[name]; !ok {
|
||||
mBucket[name] = make(map[string]int)
|
||||
}
|
||||
if _, ok := acquis_stats[source]; !ok {
|
||||
acquis_stats[source] = make(map[string]int)
|
||||
if _, ok := mAcquis[source]; !ok {
|
||||
mAcquis[source] = make(map[string]int)
|
||||
}
|
||||
buckets_stats[name]["pour"] += ival
|
||||
acquis_stats[source]["pour"] += ival
|
||||
mBucket[name]["pour"] += ival
|
||||
mAcquis[source]["pour"] += ival
|
||||
case "cs_bucket_underflowed_total":
|
||||
if _, ok := buckets_stats[name]; !ok {
|
||||
buckets_stats[name] = make(map[string]int)
|
||||
if _, ok := mBucket[name]; !ok {
|
||||
mBucket[name] = make(map[string]int)
|
||||
}
|
||||
buckets_stats[name]["underflow"] += ival
|
||||
mBucket[name]["underflow"] += ival
|
||||
/*acquis*/
|
||||
case "cs_parser_hits_total":
|
||||
if _, ok := acquis_stats[source]; !ok {
|
||||
acquis_stats[source] = make(map[string]int)
|
||||
if _, ok := mAcquis[source]; !ok {
|
||||
mAcquis[source] = make(map[string]int)
|
||||
}
|
||||
acquis_stats[source]["reads"] += ival
|
||||
mAcquis[source]["reads"] += ival
|
||||
case "cs_parser_hits_ok_total":
|
||||
if _, ok := acquis_stats[source]; !ok {
|
||||
acquis_stats[source] = make(map[string]int)
|
||||
if _, ok := mAcquis[source]; !ok {
|
||||
mAcquis[source] = make(map[string]int)
|
||||
}
|
||||
acquis_stats[source]["parsed"] += ival
|
||||
mAcquis[source]["parsed"] += ival
|
||||
case "cs_parser_hits_ko_total":
|
||||
if _, ok := acquis_stats[source]; !ok {
|
||||
acquis_stats[source] = make(map[string]int)
|
||||
if _, ok := mAcquis[source]; !ok {
|
||||
mAcquis[source] = make(map[string]int)
|
||||
}
|
||||
acquis_stats[source]["unparsed"] += ival
|
||||
mAcquis[source]["unparsed"] += ival
|
||||
case "cs_node_hits_total":
|
||||
if _, ok := parsers_stats[name]; !ok {
|
||||
parsers_stats[name] = make(map[string]int)
|
||||
if _, ok := mParser[name]; !ok {
|
||||
mParser[name] = make(map[string]int)
|
||||
}
|
||||
parsers_stats[name]["hits"] += ival
|
||||
mParser[name]["hits"] += ival
|
||||
case "cs_node_hits_ok_total":
|
||||
if _, ok := parsers_stats[name]; !ok {
|
||||
parsers_stats[name] = make(map[string]int)
|
||||
if _, ok := mParser[name]; !ok {
|
||||
mParser[name] = make(map[string]int)
|
||||
}
|
||||
parsers_stats[name]["parsed"] += ival
|
||||
mParser[name]["parsed"] += ival
|
||||
case "cs_node_hits_ko_total":
|
||||
if _, ok := parsers_stats[name]; !ok {
|
||||
parsers_stats[name] = make(map[string]int)
|
||||
if _, ok := mParser[name]; !ok {
|
||||
mParser[name] = make(map[string]int)
|
||||
}
|
||||
parsers_stats[name]["unparsed"] += ival
|
||||
mParser[name]["unparsed"] += ival
|
||||
case "cs_lapi_route_requests_total":
|
||||
if _, ok := lapi_stats[route]; !ok {
|
||||
lapi_stats[route] = make(map[string]int)
|
||||
if _, ok := mLapi[route]; !ok {
|
||||
mLapi[route] = make(map[string]int)
|
||||
}
|
||||
lapi_stats[route][method] += ival
|
||||
mLapi[route][method] += ival
|
||||
case "cs_lapi_machine_requests_total":
|
||||
if _, ok := lapi_machine_stats[machine]; !ok {
|
||||
lapi_machine_stats[machine] = make(map[string]map[string]int)
|
||||
if _, ok := mLapiMachine[machine]; !ok {
|
||||
mLapiMachine[machine] = make(map[string]map[string]int)
|
||||
}
|
||||
if _, ok := lapi_machine_stats[machine][route]; !ok {
|
||||
lapi_machine_stats[machine][route] = make(map[string]int)
|
||||
if _, ok := mLapiMachine[machine][route]; !ok {
|
||||
mLapiMachine[machine][route] = make(map[string]int)
|
||||
}
|
||||
lapi_machine_stats[machine][route][method] += ival
|
||||
mLapiMachine[machine][route][method] += ival
|
||||
case "cs_lapi_bouncer_requests_total":
|
||||
if _, ok := lapi_bouncer_stats[bouncer]; !ok {
|
||||
lapi_bouncer_stats[bouncer] = make(map[string]map[string]int)
|
||||
if _, ok := mLapiBouncer[bouncer]; !ok {
|
||||
mLapiBouncer[bouncer] = make(map[string]map[string]int)
|
||||
}
|
||||
if _, ok := lapi_bouncer_stats[bouncer][route]; !ok {
|
||||
lapi_bouncer_stats[bouncer][route] = make(map[string]int)
|
||||
if _, ok := mLapiBouncer[bouncer][route]; !ok {
|
||||
mLapiBouncer[bouncer][route] = make(map[string]int)
|
||||
}
|
||||
lapi_bouncer_stats[bouncer][route][method] += ival
|
||||
mLapiBouncer[bouncer][route][method] += ival
|
||||
case "cs_lapi_decisions_ko_total", "cs_lapi_decisions_ok_total":
|
||||
if _, ok := lapi_decisions_stats[bouncer]; !ok {
|
||||
lapi_decisions_stats[bouncer] = struct {
|
||||
if _, ok := mLapiDecision[bouncer]; !ok {
|
||||
mLapiDecision[bouncer] = struct {
|
||||
NonEmpty int
|
||||
Empty int
|
||||
}{}
|
||||
}
|
||||
x := lapi_decisions_stats[bouncer]
|
||||
x := mLapiDecision[bouncer]
|
||||
if fam.Name == "cs_lapi_decisions_ko_total" {
|
||||
x.Empty += ival
|
||||
} else if fam.Name == "cs_lapi_decisions_ok_total" {
|
||||
x.NonEmpty += ival
|
||||
}
|
||||
lapi_decisions_stats[bouncer] = x
|
||||
mLapiDecision[bouncer] = x
|
||||
case "cs_active_decisions":
|
||||
if _, ok := decisions_stats[reason]; !ok {
|
||||
decisions_stats[reason] = make(map[string]map[string]int)
|
||||
if _, ok := mDecision[reason]; !ok {
|
||||
mDecision[reason] = make(map[string]map[string]int)
|
||||
}
|
||||
if _, ok := decisions_stats[reason][origin]; !ok {
|
||||
decisions_stats[reason][origin] = make(map[string]int)
|
||||
if _, ok := mDecision[reason][origin]; !ok {
|
||||
mDecision[reason][origin] = make(map[string]int)
|
||||
}
|
||||
decisions_stats[reason][origin][action] += ival
|
||||
mDecision[reason][origin][action] += ival
|
||||
case "cs_alerts":
|
||||
/*if _, ok := alerts_stats[scenario]; !ok {
|
||||
alerts_stats[scenario] = make(map[string]int)
|
||||
/*if _, ok := mAlert[scenario]; !ok {
|
||||
mAlert[scenario] = make(map[string]int)
|
||||
}*/
|
||||
alerts_stats[reason] += ival
|
||||
mAlert[reason] += ival
|
||||
case "cs_cache_size":
|
||||
stash_stats[name] = struct {
|
||||
mStash[name] = struct {
|
||||
Type string
|
||||
Count int
|
||||
}{Type: mtype, Count: ival}
|
||||
case "cs_appsec_reqs_total":
|
||||
if _, ok := appsec_engine_stats[metric.Labels["appsec_engine"]]; !ok {
|
||||
appsec_engine_stats[metric.Labels["appsec_engine"]] = make(map[string]int, 0)
|
||||
if _, ok := mAppsecEngine[metric.Labels["appsec_engine"]]; !ok {
|
||||
mAppsecEngine[metric.Labels["appsec_engine"]] = make(map[string]int, 0)
|
||||
}
|
||||
appsec_engine_stats[metric.Labels["appsec_engine"]]["processed"] = ival
|
||||
mAppsecEngine[metric.Labels["appsec_engine"]]["processed"] = ival
|
||||
case "cs_appsec_block_total":
|
||||
if _, ok := appsec_engine_stats[metric.Labels["appsec_engine"]]; !ok {
|
||||
appsec_engine_stats[metric.Labels["appsec_engine"]] = make(map[string]int, 0)
|
||||
if _, ok := mAppsecEngine[metric.Labels["appsec_engine"]]; !ok {
|
||||
mAppsecEngine[metric.Labels["appsec_engine"]] = make(map[string]int, 0)
|
||||
}
|
||||
appsec_engine_stats[metric.Labels["appsec_engine"]]["blocked"] = ival
|
||||
mAppsecEngine[metric.Labels["appsec_engine"]]["blocked"] = ival
|
||||
case "cs_appsec_rule_hits":
|
||||
appsecEngine := metric.Labels["appsec_engine"]
|
||||
ruleID := metric.Labels["rule_name"]
|
||||
if _, ok := appsec_rule_stats[appsecEngine]; !ok {
|
||||
appsec_rule_stats[appsecEngine] = make(map[string]map[string]int, 0)
|
||||
if _, ok := mAppsecRule[appsecEngine]; !ok {
|
||||
mAppsecRule[appsecEngine] = make(map[string]map[string]int, 0)
|
||||
}
|
||||
if _, ok := appsec_rule_stats[appsecEngine][ruleID]; !ok {
|
||||
appsec_rule_stats[appsecEngine][ruleID] = make(map[string]int, 0)
|
||||
if _, ok := mAppsecRule[appsecEngine][ruleID]; !ok {
|
||||
mAppsecRule[appsecEngine][ruleID] = make(map[string]int, 0)
|
||||
}
|
||||
appsec_rule_stats[appsecEngine][ruleID]["triggered"] = ival
|
||||
mAppsecRule[appsecEngine][ruleID]["triggered"] = ival
|
||||
default:
|
||||
log.Debugf("unknown: %+v", fam.Name)
|
||||
continue
|
||||
|
@ -267,33 +282,33 @@ func FormatPrometheusMetrics(out io.Writer, url string, formatType string, noUni
|
|||
}
|
||||
|
||||
if formatType == "human" {
|
||||
acquisStatsTable(out, acquis_stats, noUnit)
|
||||
bucketStatsTable(out, buckets_stats, noUnit)
|
||||
parserStatsTable(out, parsers_stats, noUnit)
|
||||
lapiStatsTable(out, lapi_stats)
|
||||
lapiMachineStatsTable(out, lapi_machine_stats)
|
||||
lapiBouncerStatsTable(out, lapi_bouncer_stats)
|
||||
lapiDecisionStatsTable(out, lapi_decisions_stats)
|
||||
decisionStatsTable(out, decisions_stats)
|
||||
alertStatsTable(out, alerts_stats)
|
||||
stashStatsTable(out, stash_stats)
|
||||
appsecMetricsToTable(out, appsec_engine_stats, noUnit)
|
||||
appsecRulesToTable(out, appsec_rule_stats, noUnit)
|
||||
mAcquis.table(out, noUnit)
|
||||
mBucket.table(out, noUnit)
|
||||
mParser.table(out, noUnit)
|
||||
mLapi.table(out)
|
||||
mLapiMachine.table(out)
|
||||
mLapiBouncer.table(out)
|
||||
mLapiDecision.table(out)
|
||||
mDecision.table(out)
|
||||
mAlert.table(out)
|
||||
mStash.table(out)
|
||||
mAppsecEngine.table(out, noUnit)
|
||||
mAppsecRule.table(out, noUnit)
|
||||
return nil
|
||||
}
|
||||
|
||||
stats := make(map[string]any)
|
||||
|
||||
stats["acquisition"] = acquis_stats
|
||||
stats["buckets"] = buckets_stats
|
||||
stats["parsers"] = parsers_stats
|
||||
stats["lapi"] = lapi_stats
|
||||
stats["lapi_machine"] = lapi_machine_stats
|
||||
stats["lapi_bouncer"] = lapi_bouncer_stats
|
||||
stats["lapi_decisions"] = lapi_decisions_stats
|
||||
stats["decisions"] = decisions_stats
|
||||
stats["alerts"] = alerts_stats
|
||||
stats["stash"] = stash_stats
|
||||
stats["acquisition"] = mAcquis
|
||||
stats["buckets"] = mBucket
|
||||
stats["parsers"] = mParser
|
||||
stats["lapi"] = mLapi
|
||||
stats["lapi_machine"] = mLapiMachine
|
||||
stats["lapi_bouncer"] = mLapiBouncer
|
||||
stats["lapi_decisions"] = mLapiDecision
|
||||
stats["decisions"] = mDecision
|
||||
stats["alerts"] = mAlert
|
||||
stats["stash"] = mStash
|
||||
|
||||
switch formatType {
|
||||
case "json":
|
||||
|
|
|
@ -81,7 +81,7 @@ func metricsToTable(t *table.Table, stats map[string]map[string]int, keys []stri
|
|||
return numRows, nil
|
||||
}
|
||||
|
||||
func bucketStatsTable(out io.Writer, stats map[string]map[string]int, noUnit bool) {
|
||||
func (s statBucket) table(out io.Writer, noUnit bool) {
|
||||
t := newTable(out)
|
||||
t.SetRowLines(false)
|
||||
t.SetHeaders("Bucket", "Current Count", "Overflows", "Instantiated", "Poured", "Expired")
|
||||
|
@ -89,7 +89,7 @@ func bucketStatsTable(out io.Writer, stats map[string]map[string]int, noUnit boo
|
|||
|
||||
keys := []string{"curr_count", "overflow", "instantiation", "pour", "underflow"}
|
||||
|
||||
if numRows, err := metricsToTable(t, stats, keys, noUnit); err != nil {
|
||||
if numRows, err := metricsToTable(t, s, keys, noUnit); err != nil {
|
||||
log.Warningf("while collecting bucket stats: %s", err)
|
||||
} else if numRows > 0 {
|
||||
renderTableTitle(out, "\nBucket Metrics:")
|
||||
|
@ -97,7 +97,7 @@ func bucketStatsTable(out io.Writer, stats map[string]map[string]int, noUnit boo
|
|||
}
|
||||
}
|
||||
|
||||
func acquisStatsTable(out io.Writer, stats map[string]map[string]int, noUnit bool) {
|
||||
func (s statAcquis) table(out io.Writer, noUnit bool) {
|
||||
t := newTable(out)
|
||||
t.SetRowLines(false)
|
||||
t.SetHeaders("Source", "Lines read", "Lines parsed", "Lines unparsed", "Lines poured to bucket")
|
||||
|
@ -105,7 +105,7 @@ func acquisStatsTable(out io.Writer, stats map[string]map[string]int, noUnit boo
|
|||
|
||||
keys := []string{"reads", "parsed", "unparsed", "pour"}
|
||||
|
||||
if numRows, err := metricsToTable(t, stats, keys, noUnit); err != nil {
|
||||
if numRows, err := metricsToTable(t, s, keys, noUnit); err != nil {
|
||||
log.Warningf("while collecting acquis stats: %s", err)
|
||||
} else if numRows > 0 {
|
||||
renderTableTitle(out, "\nAcquisition Metrics:")
|
||||
|
@ -113,13 +113,13 @@ func acquisStatsTable(out io.Writer, stats map[string]map[string]int, noUnit boo
|
|||
}
|
||||
}
|
||||
|
||||
func appsecMetricsToTable(out io.Writer, metrics map[string]map[string]int, noUnit bool) {
|
||||
func (s statAppsecEngine) table(out io.Writer, noUnit bool) {
|
||||
t := newTable(out)
|
||||
t.SetRowLines(false)
|
||||
t.SetHeaders("Appsec Engine", "Processed", "Blocked")
|
||||
t.SetAlignment(table.AlignLeft, table.AlignLeft)
|
||||
keys := []string{"processed", "blocked"}
|
||||
if numRows, err := metricsToTable(t, metrics, keys, noUnit); err != nil {
|
||||
if numRows, err := metricsToTable(t, s, keys, noUnit); err != nil {
|
||||
log.Warningf("while collecting appsec stats: %s", err)
|
||||
} else if numRows > 0 {
|
||||
renderTableTitle(out, "\nAppsec Metrics:")
|
||||
|
@ -127,8 +127,8 @@ func appsecMetricsToTable(out io.Writer, metrics map[string]map[string]int, noUn
|
|||
}
|
||||
}
|
||||
|
||||
func appsecRulesToTable(out io.Writer, metrics map[string]map[string]map[string]int, noUnit bool) {
|
||||
for appsecEngine, appsecEngineRulesStats := range metrics {
|
||||
func (s statAppsecRule) table(out io.Writer, noUnit bool) {
|
||||
for appsecEngine, appsecEngineRulesStats := range s {
|
||||
t := newTable(out)
|
||||
t.SetRowLines(false)
|
||||
t.SetHeaders("Rule ID", "Triggered")
|
||||
|
@ -144,7 +144,7 @@ func appsecRulesToTable(out io.Writer, metrics map[string]map[string]map[string]
|
|||
|
||||
}
|
||||
|
||||
func parserStatsTable(out io.Writer, stats map[string]map[string]int, noUnit bool) {
|
||||
func (s statParser) table(out io.Writer, noUnit bool) {
|
||||
t := newTable(out)
|
||||
t.SetRowLines(false)
|
||||
t.SetHeaders("Parsers", "Hits", "Parsed", "Unparsed")
|
||||
|
@ -152,7 +152,7 @@ func parserStatsTable(out io.Writer, stats map[string]map[string]int, noUnit boo
|
|||
|
||||
keys := []string{"hits", "parsed", "unparsed"}
|
||||
|
||||
if numRows, err := metricsToTable(t, stats, keys, noUnit); err != nil {
|
||||
if numRows, err := metricsToTable(t, s, keys, noUnit); err != nil {
|
||||
log.Warningf("while collecting parsers stats: %s", err)
|
||||
} else if numRows > 0 {
|
||||
renderTableTitle(out, "\nParser Metrics:")
|
||||
|
@ -160,11 +160,7 @@ func parserStatsTable(out io.Writer, stats map[string]map[string]int, noUnit boo
|
|||
}
|
||||
}
|
||||
|
||||
func stashStatsTable(out io.Writer, stats map[string]struct {
|
||||
Type string
|
||||
Count int
|
||||
}) {
|
||||
|
||||
func (s statStash) table(out io.Writer) {
|
||||
t := newTable(out)
|
||||
t.SetRowLines(false)
|
||||
t.SetHeaders("Name", "Type", "Items")
|
||||
|
@ -172,14 +168,14 @@ func stashStatsTable(out io.Writer, stats map[string]struct {
|
|||
|
||||
// unfortunately, we can't reuse metricsToTable as the structure is too different :/
|
||||
sortedKeys := []string{}
|
||||
for k := range stats {
|
||||
for k := range s {
|
||||
sortedKeys = append(sortedKeys, k)
|
||||
}
|
||||
sort.Strings(sortedKeys)
|
||||
|
||||
numRows := 0
|
||||
for _, alabel := range sortedKeys {
|
||||
astats := stats[alabel]
|
||||
astats := s[alabel]
|
||||
|
||||
row := []string{
|
||||
alabel,
|
||||
|
@ -195,7 +191,7 @@ func stashStatsTable(out io.Writer, stats map[string]struct {
|
|||
}
|
||||
}
|
||||
|
||||
func lapiStatsTable(out io.Writer, stats map[string]map[string]int) {
|
||||
func (s statLapi) table(out io.Writer) {
|
||||
t := newTable(out)
|
||||
t.SetRowLines(false)
|
||||
t.SetHeaders("Route", "Method", "Hits")
|
||||
|
@ -203,14 +199,14 @@ func lapiStatsTable(out io.Writer, stats map[string]map[string]int) {
|
|||
|
||||
// unfortunately, we can't reuse metricsToTable as the structure is too different :/
|
||||
sortedKeys := []string{}
|
||||
for k := range stats {
|
||||
for k := range s {
|
||||
sortedKeys = append(sortedKeys, k)
|
||||
}
|
||||
sort.Strings(sortedKeys)
|
||||
|
||||
numRows := 0
|
||||
for _, alabel := range sortedKeys {
|
||||
astats := stats[alabel]
|
||||
astats := s[alabel]
|
||||
|
||||
subKeys := []string{}
|
||||
for skey := range astats {
|
||||
|
@ -235,13 +231,13 @@ func lapiStatsTable(out io.Writer, stats map[string]map[string]int) {
|
|||
}
|
||||
}
|
||||
|
||||
func lapiMachineStatsTable(out io.Writer, stats map[string]map[string]map[string]int) {
|
||||
func (s statLapiMachine) table(out io.Writer) {
|
||||
t := newTable(out)
|
||||
t.SetRowLines(false)
|
||||
t.SetHeaders("Machine", "Route", "Method", "Hits")
|
||||
t.SetAlignment(table.AlignLeft, table.AlignLeft, table.AlignLeft, table.AlignLeft)
|
||||
|
||||
numRows := lapiMetricsToTable(t, stats)
|
||||
numRows := lapiMetricsToTable(t, s)
|
||||
|
||||
if numRows > 0 {
|
||||
renderTableTitle(out, "\nLocal API Machines Metrics:")
|
||||
|
@ -249,13 +245,13 @@ func lapiMachineStatsTable(out io.Writer, stats map[string]map[string]map[string
|
|||
}
|
||||
}
|
||||
|
||||
func lapiBouncerStatsTable(out io.Writer, stats map[string]map[string]map[string]int) {
|
||||
func (s statLapiBouncer) table(out io.Writer) {
|
||||
t := newTable(out)
|
||||
t.SetRowLines(false)
|
||||
t.SetHeaders("Bouncer", "Route", "Method", "Hits")
|
||||
t.SetAlignment(table.AlignLeft, table.AlignLeft, table.AlignLeft, table.AlignLeft)
|
||||
|
||||
numRows := lapiMetricsToTable(t, stats)
|
||||
numRows := lapiMetricsToTable(t, s)
|
||||
|
||||
if numRows > 0 {
|
||||
renderTableTitle(out, "\nLocal API Bouncers Metrics:")
|
||||
|
@ -263,18 +259,14 @@ func lapiBouncerStatsTable(out io.Writer, stats map[string]map[string]map[string
|
|||
}
|
||||
}
|
||||
|
||||
func lapiDecisionStatsTable(out io.Writer, stats map[string]struct {
|
||||
NonEmpty int
|
||||
Empty int
|
||||
},
|
||||
) {
|
||||
func (s statLapiDecision) table(out io.Writer) {
|
||||
t := newTable(out)
|
||||
t.SetRowLines(false)
|
||||
t.SetHeaders("Bouncer", "Empty answers", "Non-empty answers")
|
||||
t.SetAlignment(table.AlignLeft, table.AlignLeft, table.AlignLeft)
|
||||
|
||||
numRows := 0
|
||||
for bouncer, hits := range stats {
|
||||
for bouncer, hits := range s {
|
||||
t.AddRow(
|
||||
bouncer,
|
||||
fmt.Sprintf("%d", hits.Empty),
|
||||
|
@ -289,14 +281,14 @@ func lapiDecisionStatsTable(out io.Writer, stats map[string]struct {
|
|||
}
|
||||
}
|
||||
|
||||
func decisionStatsTable(out io.Writer, stats map[string]map[string]map[string]int) {
|
||||
func (s statDecision) table(out io.Writer) {
|
||||
t := newTable(out)
|
||||
t.SetRowLines(false)
|
||||
t.SetHeaders("Reason", "Origin", "Action", "Count")
|
||||
t.SetAlignment(table.AlignLeft, table.AlignLeft, table.AlignLeft, table.AlignLeft)
|
||||
|
||||
numRows := 0
|
||||
for reason, origins := range stats {
|
||||
for reason, origins := range s {
|
||||
for origin, actions := range origins {
|
||||
for action, hits := range actions {
|
||||
t.AddRow(
|
||||
|
@ -316,14 +308,14 @@ func decisionStatsTable(out io.Writer, stats map[string]map[string]map[string]in
|
|||
}
|
||||
}
|
||||
|
||||
func alertStatsTable(out io.Writer, stats map[string]int) {
|
||||
func (s statAlert) table(out io.Writer) {
|
||||
t := newTable(out)
|
||||
t.SetRowLines(false)
|
||||
t.SetHeaders("Reason", "Count")
|
||||
t.SetAlignment(table.AlignLeft, table.AlignLeft)
|
||||
|
||||
numRows := 0
|
||||
for scenario, hits := range stats {
|
||||
for scenario, hits := range s {
|
||||
t.AddRow(
|
||||
scenario,
|
||||
fmt.Sprintf("%d", hits),
|
||||
|
|
Loading…
Reference in a new issue