Files
mqtt2prometheus/pkg/metrics/extractor_test.go
Christian Schneider 9f92116fe3 Support multiple configs per input metric.
When generating metric values using expression evaluation, there are new
use-cases for more than one configuration for each sensor value.
Expressions are more flexible than aggregation rules in Prometheus, so
it makes sense to derive multiple metrics from the same sensor input.
2024-03-25 10:15:05 +01:00

159 lines
3.7 KiB
Go

package metrics
import (
"reflect"
"testing"
"github.com/hikhvar/mqtt2prometheus/pkg/config"
"github.com/prometheus/client_golang/prometheus"
)
func TestNewJSONObjectExtractor_parseMetric(t *testing.T) {
now = testNow
type fields struct {
metricConfigs map[string][]*config.MetricConfig
}
type args struct {
metricPath string
deviceID string
value string
}
tests := []struct {
name string
separator string
fields fields
args args
want Metric
wantErr bool
noValue bool
}{
{
name: "string value",
separator: "->",
fields: fields{
map[string][]*config.MetricConfig{
"SDS0X1->PM2->5": {
{
PrometheusName: "temperature",
MQTTName: "SDS0X1.PM2.5",
ValueType: "gauge",
},
},
},
},
args: args{
metricPath: "topic",
deviceID: "dht22",
value: "{\"SDS0X1\":{\"PM2\":{\"5\":4.9}}}",
},
want: Metric{
Description: prometheus.NewDesc("temperature", "", []string{"sensor", "topic"}, nil),
ValueType: prometheus.GaugeValue,
Value: 4.9,
IngestTime: testNow(),
Topic: "topic",
},
}, {
name: "string value with dots in path",
separator: "->",
fields: fields{
map[string][]*config.MetricConfig{
"SDS0X1->PM2.5": {
{
PrometheusName: "temperature",
MQTTName: "SDS0X1->PM2.5",
ValueType: "gauge",
},
},
},
},
args: args{
metricPath: "topic",
deviceID: "dht22",
value: "{\"SDS0X1\":{\"PM2.5\":4.9,\"PM10\":8.5}}",
},
want: Metric{
Description: prometheus.NewDesc("temperature", "", []string{"sensor", "topic"}, nil),
ValueType: prometheus.GaugeValue,
Value: 4.9,
IngestTime: testNow(),
Topic: "topic",
},
}, {
name: "metric matching SensorNameFilter",
separator: ".",
fields: fields{
map[string][]*config.MetricConfig{
"temperature": {
{
PrometheusName: "temperature",
MQTTName: "temperature",
ValueType: "gauge",
SensorNameFilter: *config.MustNewRegexp(".*22$"),
},
},
},
},
args: args{
metricPath: "topic",
deviceID: "dht22",
value: "{\"temperature\": 8.5}",
},
want: Metric{
Description: prometheus.NewDesc("temperature", "", []string{"sensor", "topic"}, nil),
ValueType: prometheus.GaugeValue,
Value: 8.5,
IngestTime: testNow(),
Topic: "topic",
},
}, {
name: "metric not matching SensorNameFilter",
separator: ".",
fields: fields{
map[string][]*config.MetricConfig{
"temperature": {
{
PrometheusName: "temperature",
MQTTName: "temperature",
ValueType: "gauge",
SensorNameFilter: *config.MustNewRegexp(".*fail$"),
},
},
},
},
args: args{
metricPath: "topic",
deviceID: "dht22",
value: "{\"temperature\": 8.5}",
},
want: Metric{},
noValue: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := Parser{
separator: tt.separator,
metricConfigs: tt.fields.metricConfigs,
}
extractor := NewJSONObjectExtractor(p)
got, err := extractor(tt.args.metricPath, []byte(tt.args.value), tt.args.deviceID)
if (err != nil) != tt.wantErr {
t.Errorf("parseMetric() error = %v, wantErr %v", err, tt.wantErr)
return
}
if len(got) == 0 {
if !tt.noValue {
t.Errorf("parseMetric() got = %v, want %v", nil, tt.want)
}
} else if !reflect.DeepEqual(got[0], tt.want) {
t.Errorf("parseMetric() got = %v, want %v", got[0], tt.want)
} else if len(got) > 1 {
t.Errorf("unexpected result got = %v, want %v", got, tt.want)
}
})
}
}