Parse more value types

* Parse bools as 0 for false and 1 for true
* Allow mapping between string and float values
This commit is contained in:
Mansour Behabadi
2020-05-03 18:11:09 +10:00
parent 39a6e392d5
commit 13c47b498d
3 changed files with 76 additions and 23 deletions

View File

@@ -11,7 +11,7 @@ mqtt:
qos: 0
cache:
# Timeout. Each received metric will be presented for this time if no update is send via MQTT
timeout: 2min
timeout: 2m
# This is a list of valid metrics. Only metrics listed here will be exported
metrics:
# The name of the metric in prometheus
@@ -46,4 +46,23 @@ metrics:
type: gauge
# A map of string to string for constant labels. This labels will be attached to every prometheus metric
const_labels:
sensor_type: dht22
sensor_type: dht22
- prom_name: state
# The name of the metric in a MQTT JSON message
mqtt_name: state
# The prometheus help text for this metric
help: Light state
# The prometheus type for this metric. Valid values are: "gauge" and "counter"
type: gauge
# A map of string to string for constant labels. This labels will be attached to every prometheus metric
const_labels:
sensor_type: ikea
# When specified, enables mapping between string values to metric values.
string_value_mapping:
# A map of string to metric value.
map:
off: 0
low: 0
# Metric value to use if a match cannot be found in the map above.
# If not specified, parsing error will occur.
error_value: 1

View File

@@ -1,8 +1,9 @@
package config
import (
"time"
"io/ioutil"
"time"
"github.com/prometheus/client_golang/prometheus"
"gopkg.in/yaml.v2"
)
@@ -40,11 +41,19 @@ type MQTTConfig struct {
// Metrics Config is a mapping between a metric send on mqtt to a prometheus metric
type MetricConfig struct {
PrometheusName string `yaml:"prom_name"`
MQTTName string `yaml:"mqtt_name"`
Help string `yaml:"help"`
ValueType string `yaml:"type"`
ConstantLabels map[string]string `yaml:"const_labels"`
PrometheusName string `yaml:"prom_name"`
MQTTName string `yaml:"mqtt_name"`
Help string `yaml:"help"`
ValueType string `yaml:"type"`
ConstantLabels map[string]string `yaml:"const_labels"`
StringValueMapping *StringValueMappingConfig `yaml:"string_value_mapping"`
}
// StringValueMappingConfig defines the mapping between from string to float
type StringValueMappingConfig struct {
// ErrorValue is used when no mapping is found in Map
ErrorValue *float64 `yaml:"error_value"`
Map map[string]float64 `yaml:"map"`
}
func (mc *MetricConfig) PrometheusDescription() *prometheus.Desc {

View File

@@ -45,30 +45,55 @@ func (i *Ingest) store(deviceID string, rawMetrics MQTTPayload) error {
var mc MetricCollection
for metricName, value := range rawMetrics {
if cfg, found := i.validMetrics[metricName]; found {
var floatValue float64
var isFloat bool
var err error
floatValue, isFloat = value.(float64)
if !isFloat {
stringValue, isString := value.(string)
cfg, cfgFound := i.validMetrics[metricName]
if !cfgFound {
continue
}
if !isString || ! validNumber.MatchString(stringValue) {
return fmt.Errorf("got data with unexpectd type: %T ('%s')", value, value)
var metricValue float64
if boolValue, ok := value.(bool); ok {
if boolValue {
metricValue = 1
} else {
metricValue = 0
}
} else if strValue, ok := value.(string); ok {
// If string value mapping is defined, use that
if cfg.StringValueMapping != nil {
floatValue, ok := cfg.StringValueMapping.Map[strValue]
if ok {
metricValue = floatValue
} else if cfg.StringValueMapping.ErrorValue != nil {
metricValue = *cfg.StringValueMapping.ErrorValue
} else {
return fmt.Errorf("got unexpected string data '%s'", strValue)
}
floatValue, err = strconv.ParseFloat(stringValue, 64)
} else {
// otherwise try to parse float
floatValue, err := strconv.ParseFloat(strValue, 64)
if err != nil {
return fmt.Errorf("got data with unexpectd type: %T ('%s') and failed to parse to float", value, value)
}
metricValue = floatValue
}
mc = append(mc, Metric{
Description: cfg.PrometheusDescription(),
Value: floatValue,
ValueType: cfg.PrometheusValueType(),
})
} else if floatValue, ok := value.(float64); ok {
metricValue = floatValue
} else {
return fmt.Errorf("got data with unexpectd type: %T ('%s')", value, value)
}
mc = append(mc, Metric{
Description: cfg.PrometheusDescription(),
Value: metricValue,
ValueType: cfg.PrometheusValueType(),
})
}
i.collector.Observe(deviceID, mc)
return nil