Files
Christoph Petrausch be4af9ff5e Refactor metric extraction from MQTT
This commit allows to extract the metric name from the topic path. Now
it can be configured if all metrics are in a object in a certain topic
or if every topic contains exactly one metric. However, currently these
modes can not be mixed.

This should solve !26

TODO:
* Update documentation
* Add unit tests
2020-11-08 22:01:36 +01:00

51 lines
1.4 KiB
Go

package metrics
import (
"errors"
"fmt"
"github.com/hikhvar/mqtt2prometheus/pkg/config"
gojsonq "github.com/thedevsaddam/gojsonq/v2"
)
type Extractor func(topic string, payload []byte, deviceID string) (MetricCollection, error)
func NewJSONObjectExtractor(p Parser) Extractor {
return func(topic string, payload []byte, deviceID string) (MetricCollection, error) {
var mc MetricCollection
parsed := gojsonq.New().FromString(string(payload))
for path := range p.config() {
rawValue := parsed.Find(path)
parsed.Reset()
if rawValue == nil {
continue
}
m, err := p.parseMetric(path, deviceID, rawValue)
if err != nil {
return nil, fmt.Errorf("failed to parse valid metric value: %w", err)
}
m.Topic = topic
mc = append(mc, m)
}
return mc, nil
}
}
func NewMetricPerTopicExtractor(p Parser, metricName *config.Regexp) Extractor {
return func(topic string, payload []byte, deviceID string) (MetricCollection, error) {
mName := metricName.GroupValue(topic, config.MetricNameRegexGroup)
if mName == "" {
return nil, fmt.Errorf("failed to find valid metric in topic path")
}
m, err := p.parseMetric(mName, deviceID, string(payload))
if err != nil {
if errors.Is(err, metricNotConfigured) {
return nil, nil
}
return nil, fmt.Errorf("failed to parse metric: %w", err)
}
m.Topic = topic
return MetricCollection{m}, nil
}
}