Skip to content

Commit de7c4c7

Browse files
Parsaparsa97
Parsa
authored andcommitted
feature: count json objects with same value
if we want to count json objects with same values we can use countbylabel type in the metric configuration Signed-off-by: Parsa <[email protected]> Signed-off-by: Parsa <[email protected]>
1 parent 7ab7efc commit de7c4c7

File tree

7 files changed

+88
-2
lines changed

7 files changed

+88
-2
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ Serving HTTP on :: port 8000 (http://[::]:8000/) ...
2121
## TEST with 'default' module
2222

2323
$ curl "http://localhost:7979/probe?module=default&target=http://localhost:8000/examples/data.json"
24+
# HELP example_count Example of count object from a json
25+
# TYPE example_count untyped
26+
example_count{environment="beta",state="ACTIVE"} 2
27+
example_count{environment="beta",state="INACTIVE"} 1
2428
# HELP example_global_value Example of a top-level global value scrape in the json
2529
# TYPE example_global_value untyped
2630
example_global_value{environment="beta",location="planet-mars"} 1234

config/config.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,15 @@ type Metric struct {
3030
EpochTimestamp string
3131
Help string
3232
Values map[string]string
33+
Mincount int
3334
}
3435

3536
type ScrapeType string
3637

3738
const (
3839
ValueScrape ScrapeType = "value" // default
3940
ObjectScrape ScrapeType = "object"
41+
CountScrape ScrapeType = "countbylabel"
4042
)
4143

4244
type ValueType string
@@ -89,8 +91,10 @@ func LoadConfig(configPath string) (Config, error) {
8991
if module.Metrics[i].ValueType == "" {
9092
module.Metrics[i].ValueType = ValueTypeUntyped
9193
}
94+
if !(module.Metrics[i].Mincount > 0) {
95+
module.Metrics[i].Mincount = 1
96+
}
9297
}
9398
}
94-
9599
return config, nil
96100
}

examples/config.yml

+8-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ modules:
3030
active: 1 # static value
3131
count: '{.count}' # dynamic value
3232
boolean: '{.some_boolean}'
33+
- name: example_count
34+
type: countbylabel
35+
help: Example of count json labels
36+
path: '{.values[*].state}'
37+
labels:
38+
environment: beta # static label
39+
state: '{}' # dynamic label
40+
mincount: 1
3341

3442
animals:
3543
metrics:
@@ -66,4 +74,3 @@ modules:
6674
# content: |
6775
# {"time_diff": "{{ duration `95` }}","anotherVar": "{{ .myVal | first }}"}
6876
# templatize: true
69-

exporter/collector.go

+37
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type JSONMetric struct {
3939
LabelsJSONPaths []string
4040
ValueType prometheus.ValueType
4141
EpochTimestampJSONPath string
42+
Mincount int
4243
}
4344

4445
func (mc JSONMetricCollector) Describe(ch chan<- *prometheus.Desc) {
@@ -70,6 +71,42 @@ func (mc JSONMetricCollector) Collect(ch chan<- prometheus.Metric) {
7071
continue
7172
}
7273

74+
case config.CountScrape:
75+
values, err := extractValue(mc.Logger, mc.Data, m.KeyJSONPath, true)
76+
if err != nil {
77+
level.Error(mc.Logger).Log("msg", "Failed to extract json objects for metric", "err", err, "metric", m.Desc)
78+
continue
79+
}
80+
81+
var jsonData []interface{}
82+
counts := make(map[interface{}]int)
83+
84+
if err := json.Unmarshal([]byte(values), &jsonData); err == nil {
85+
for _, data := range jsonData {
86+
counts[data]++
87+
}
88+
for data, count := range counts {
89+
if count >= m.Mincount {
90+
jdata, err := json.Marshal(data)
91+
if err != nil {
92+
level.Error(mc.Logger).Log("msg", "Failed to marshal data to json", "path", m.ValueJSONPath, "err", err, "metric", m.Desc, "data", data)
93+
continue
94+
}
95+
if err != nil {
96+
level.Error(mc.Logger).Log("msg", "Failed to extract value for metric", "path", m.ValueJSONPath, "err", err, "metric", m.Desc)
97+
continue
98+
}
99+
100+
ch <- prometheus.MustNewConstMetric(
101+
m.Desc,
102+
prometheus.UntypedValue,
103+
float64(count),
104+
extractLabels(mc.Logger, jdata, m.LabelsJSONPaths)...,
105+
)
106+
}
107+
}
108+
}
109+
73110
case config.ObjectScrape:
74111
values, err := extractValue(mc.Logger, mc.Data, m.KeyJSONPath, true)
75112
if err != nil {

exporter/util.go

+22
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,28 @@ func CreateMetricsList(c config.Module) ([]JSONMetric, error) {
133133
}
134134
metrics = append(metrics, jsonMetric)
135135
}
136+
case config.CountScrape:
137+
var variableLabels, variableLabelsValues []string
138+
for k, v := range metric.Labels {
139+
variableLabels = append(variableLabels, k)
140+
variableLabelsValues = append(variableLabelsValues, v)
141+
}
142+
jsonMetric := JSONMetric{
143+
Type: config.CountScrape,
144+
Desc: prometheus.NewDesc(
145+
metric.Name,
146+
metric.Help,
147+
variableLabels,
148+
nil,
149+
),
150+
KeyJSONPath: metric.Path,
151+
Mincount: metric.Mincount,
152+
LabelsJSONPaths: variableLabelsValues,
153+
ValueType: valueType,
154+
EpochTimestampJSONPath: metric.EpochTimestamp,
155+
}
156+
fmt.Println(jsonMetric)
157+
metrics = append(metrics, jsonMetric)
136158
default:
137159
return nil, fmt.Errorf("Unknown metric type: '%s', for metric: '%s'", metric.Type, metric.Name)
138160
}

test/config/good.yml

+8
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,11 @@ modules:
2222
active: 1 # static value
2323
count: '{.count}' # dynamic value
2424
boolean: '{.some_boolean}'
25+
26+
- name: example_count
27+
type: countbylabel
28+
help: Example of count object from a json
29+
path: '{.values[*].state}'
30+
labels:
31+
environment: beta # static label
32+
state: '{}' # dynamic label

test/response/good.txt

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# HELP example_count Example of count object from a json
2+
# TYPE example_count untyped
3+
example_count{environment="beta",state="ACTIVE"} 2
4+
example_count{environment="beta",state="INACTIVE"} 1
15
# HELP example_global_value Example of a top-level global value scrape in the json
26
# TYPE example_global_value gauge
37
example_global_value{environment="beta",location="planet-mars"} 1234

0 commit comments

Comments
 (0)