collect option
This commit is contained in:
parent
7c629a62f7
commit
050d40cf27
5 changed files with 238 additions and 157 deletions
|
@ -17,20 +17,18 @@ type Collector struct {
|
|||
}
|
||||
|
||||
// NewHueCollector initialization
|
||||
func NewHueCollector(URL string, username string) (*Collector, error) {
|
||||
func NewHueCollector(URL string, username string, metricsFile *metric.MetricsFile) (*Collector, error) {
|
||||
|
||||
hueExporter := hue.Exporter{
|
||||
BaseURL: URL,
|
||||
Username: username,
|
||||
}
|
||||
|
||||
return &Collector{&hueExporter, nil}, nil
|
||||
return &Collector{&hueExporter, metricsFile.Metrics}, nil
|
||||
}
|
||||
|
||||
// Describe for prometheus
|
||||
func (collector *Collector) Describe(ch chan<- *prometheus.Desc) {
|
||||
|
||||
collector.metrics = collector.exporter.InitMetrics()
|
||||
collector.initDescAndType()
|
||||
}
|
||||
|
||||
|
@ -52,7 +50,6 @@ func (collector *Collector) Collect(ch chan<- prometheus.Metric) {
|
|||
//Test collector metrics
|
||||
func (collector *Collector) Test() {
|
||||
|
||||
collector.metrics = collector.exporter.InitMetrics()
|
||||
collector.initDescAndType()
|
||||
|
||||
err := collector.collect()
|
||||
|
@ -194,10 +191,6 @@ func getLabelValues(labelNames []string, result map[string]interface{}) ([]strin
|
|||
case "false":
|
||||
labelValueString = "0"
|
||||
}
|
||||
|
||||
if labelname != "name" {
|
||||
labelValue = strings.ToLower(labelValueString)
|
||||
}
|
||||
labelValues = append(labelValues, labelValueString)
|
||||
}
|
||||
return labelValues, nil
|
||||
|
|
240
hue/hue.go
240
hue/hue.go
|
@ -21,116 +21,47 @@ type collectEntry struct {
|
|||
}
|
||||
|
||||
const (
|
||||
TypeLight = "light"
|
||||
TypeSensor = "sensor"
|
||||
typeLight = "light"
|
||||
typeSensor = "sensor"
|
||||
|
||||
LabelName = "name"
|
||||
LabelType = "type"
|
||||
LabelID = "id"
|
||||
LabelModelID = "model_id"
|
||||
LabelManufacturerName = "manufacturer_name"
|
||||
LabelSwVersion = "sw_version"
|
||||
LabelSwConfigID = "sw_config_id"
|
||||
LabelUniqueID = "unique_id"
|
||||
labelName = "name"
|
||||
labelType = "type"
|
||||
labelID = "id"
|
||||
labelModelID = "model_id"
|
||||
labelManufacturerName = "manufacturer_name"
|
||||
labelSwVersion = "sw_version"
|
||||
labelSwConfigID = "sw_config_id"
|
||||
labelUniqueID = "unique_id"
|
||||
|
||||
LabelStateOn = "state_on"
|
||||
LabelStateAlert = "state_alert"
|
||||
LabelStateBri = "state_bri"
|
||||
LabelStateColorMode = "state_color_mode"
|
||||
LabelStateCT = "state_ct"
|
||||
LabelStateReachable = "state_reachable"
|
||||
LabelStateSaturation = "state_saturation"
|
||||
LabelStateButtonEvent = "state_buttonevent"
|
||||
LabelStateDaylight = "state_daylight"
|
||||
LabelStateLastUpdated = "state_lastupdated"
|
||||
LabelStateTemperature = "state_temperature"
|
||||
LabelStateLightLevel = "state_lightlevel"
|
||||
labelStateOn = "state_on"
|
||||
labelStateAlert = "state_alert"
|
||||
labelStateBri = "state_bri"
|
||||
labelStateColorMode = "state_color_mode"
|
||||
labelStateCT = "state_ct"
|
||||
labelStateReachable = "state_reachable"
|
||||
labelStateSaturation = "state_saturation"
|
||||
labelStateButtonEvent = "state_buttonevent"
|
||||
labelStateDaylight = "state_daylight"
|
||||
labelStateLastUpdated = "state_lastupdated"
|
||||
labelStateTemperature = "state_temperature"
|
||||
labelStateLightLevel = "state_lightlevel"
|
||||
|
||||
LabelConfigBattery = "config_battery"
|
||||
LabelConfigOn = "config_on"
|
||||
LabelConfigReachable = "config_reachable"
|
||||
labelConfigBattery = "config_battery"
|
||||
labelConfigOn = "config_on"
|
||||
labelConfigReachable = "config_reachable"
|
||||
|
||||
labelAPIVersion = "api_version"
|
||||
labelBridgeID = "bridge_id"
|
||||
labelIPAddress = "ip_address"
|
||||
labelInternetServiceInternet = "internetservice_internet"
|
||||
labelInternetServiceRemoteAccess = "internetservice_remoteaccess"
|
||||
labelInternetServiceSwUpdate = "internetservice_swupdate"
|
||||
labelInternetServiceTime = "internetservice_time"
|
||||
labelLocalTime = "local_time"
|
||||
labelSwUpdate2LastChange = "sw_update_last_change"
|
||||
labelZigbeeChannel = "zigbee_channel"
|
||||
)
|
||||
|
||||
// InitMetrics func
|
||||
func (exporter *Exporter) InitMetrics() (metrics []*metric.Metric) {
|
||||
|
||||
metrics = append(metrics, &metric.Metric{
|
||||
HueType: TypeLight,
|
||||
FqName: "hue_light_info",
|
||||
Help: "Non-numeric data, value is always 1",
|
||||
Labels: []string{
|
||||
LabelName,
|
||||
LabelID,
|
||||
LabelType,
|
||||
LabelModelID,
|
||||
LabelManufacturerName,
|
||||
LabelSwVersion,
|
||||
LabelSwConfigID,
|
||||
LabelUniqueID,
|
||||
LabelStateOn,
|
||||
LabelStateAlert,
|
||||
LabelStateBri,
|
||||
LabelStateCT,
|
||||
LabelStateReachable,
|
||||
LabelStateSaturation,
|
||||
},
|
||||
})
|
||||
|
||||
metrics = append(metrics, &metric.Metric{
|
||||
HueType: TypeLight,
|
||||
FqName: "hue_light_state",
|
||||
Help: "light status (1=ON, 0=OFF)",
|
||||
Labels: []string{
|
||||
LabelName,
|
||||
},
|
||||
ResultKey: LabelStateOn,
|
||||
})
|
||||
|
||||
metrics = append(metrics, &metric.Metric{
|
||||
HueType: TypeSensor,
|
||||
FqName: "hue_sensor_info",
|
||||
Help: "Non-numeric data, value is always 1",
|
||||
Labels: []string{
|
||||
LabelName,
|
||||
LabelID,
|
||||
LabelType,
|
||||
LabelModelID,
|
||||
LabelManufacturerName,
|
||||
LabelSwVersion,
|
||||
LabelUniqueID,
|
||||
LabelStateButtonEvent,
|
||||
LabelStateDaylight,
|
||||
LabelStateLastUpdated,
|
||||
LabelStateTemperature,
|
||||
LabelConfigBattery,
|
||||
LabelConfigOn,
|
||||
LabelConfigReachable,
|
||||
},
|
||||
})
|
||||
|
||||
metrics = append(metrics, &metric.Metric{
|
||||
HueType: TypeSensor,
|
||||
FqName: "hue_sensor_temperature",
|
||||
Help: "temperature level celsius degree",
|
||||
Labels: []string{
|
||||
LabelName,
|
||||
},
|
||||
ResultKey: LabelStateTemperature,
|
||||
})
|
||||
|
||||
metrics = append(metrics, &metric.Metric{
|
||||
HueType: TypeSensor,
|
||||
FqName: "hue_sensor_lightlevel",
|
||||
Help: "light level",
|
||||
Labels: []string{
|
||||
LabelName,
|
||||
},
|
||||
ResultKey: LabelStateLightLevel,
|
||||
})
|
||||
|
||||
return metrics
|
||||
}
|
||||
|
||||
// CollectAll available hue metrics
|
||||
func CollectAll(url string, username string, fileName string) {
|
||||
|
||||
|
@ -150,17 +81,20 @@ func CollectAll(url string, username string, fileName string) {
|
|||
return
|
||||
}
|
||||
|
||||
bridgeData, err := collectBridgeInfo(bridge)
|
||||
if err != nil {
|
||||
fmt.Sprintln(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, sensor := range sensorData {
|
||||
jsonContent = append(jsonContent, collectEntry{
|
||||
Type: "sensor",
|
||||
Result: sensor,
|
||||
})
|
||||
jsonContent = append(jsonContent, collectEntry{Type: "sensor", Result: sensor})
|
||||
}
|
||||
for _, light := range lightData {
|
||||
jsonContent = append(jsonContent, collectEntry{
|
||||
Type: "light",
|
||||
Result: light,
|
||||
})
|
||||
jsonContent = append(jsonContent, collectEntry{Type: "light", Result: light})
|
||||
}
|
||||
for _, bridge := range bridgeData {
|
||||
jsonContent = append(jsonContent, collectEntry{Type: "bridge", Result: bridge})
|
||||
}
|
||||
|
||||
jsonString, err := json.MarshalIndent(jsonContent, "", "\t")
|
||||
|
@ -195,11 +129,14 @@ func (exporter *Exporter) Collect(metrics []*metric.Metric) (err error) {
|
|||
|
||||
for _, metric := range metrics {
|
||||
switch metric.HueType {
|
||||
case TypeLight:
|
||||
case typeLight:
|
||||
metric.MetricResult = lightData
|
||||
case TypeSensor:
|
||||
case typeSensor:
|
||||
metric.MetricResult = sensorData
|
||||
default:
|
||||
return fmt.Errorf("Type '%v' currently not supported", metric.HueType)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -209,17 +146,17 @@ func collectSensors(bridge *hueAPI.Bridge) (sensorData []map[string]interface{},
|
|||
|
||||
sensors, err := bridge.GetSensors()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[error GetAllSensors()] '%v'", err)
|
||||
return nil, fmt.Errorf("[GetAllSensors()] '%v'", err)
|
||||
}
|
||||
for _, sensor := range sensors {
|
||||
result := make(map[string]interface{})
|
||||
result[LabelName] = sensor.Name
|
||||
result[LabelID] = sensor.ID
|
||||
result[LabelType] = sensor.Type
|
||||
result[LabelModelID] = sensor.ModelID
|
||||
result[LabelManufacturerName] = sensor.ManufacturerName
|
||||
result[LabelSwVersion] = sensor.SwVersion
|
||||
result[LabelUniqueID] = sensor.UniqueID
|
||||
result[labelName] = sensor.Name
|
||||
result[labelID] = sensor.ID
|
||||
result[labelType] = sensor.Type
|
||||
result[labelModelID] = sensor.ModelID
|
||||
result[labelManufacturerName] = sensor.ManufacturerName
|
||||
result[labelSwVersion] = sensor.SwVersion
|
||||
result[labelUniqueID] = sensor.UniqueID
|
||||
|
||||
//State
|
||||
for stateKey, stateValue := range sensor.State {
|
||||
|
@ -240,31 +177,56 @@ func collectLights(bridge *hueAPI.Bridge) (lightData []map[string]interface{}, e
|
|||
|
||||
lights, err := bridge.GetLights()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[error GetAllLights()] '%v'", err)
|
||||
return nil, fmt.Errorf("[GetAllLights()] '%v'", err)
|
||||
}
|
||||
|
||||
for _, light := range lights {
|
||||
|
||||
result := make(map[string]interface{})
|
||||
result[LabelName] = light.Name
|
||||
result[LabelID] = light.ID
|
||||
result[LabelType] = light.Type
|
||||
result[LabelModelID] = light.ModelID
|
||||
result[LabelManufacturerName] = light.ManufacturerName
|
||||
result[LabelSwVersion] = light.SwVersion
|
||||
result[LabelSwConfigID] = light.SwConfigID
|
||||
result[LabelUniqueID] = light.UniqueID
|
||||
result[labelName] = light.Name
|
||||
result[labelID] = light.ID
|
||||
result[labelType] = light.Type
|
||||
result[labelModelID] = light.ModelID
|
||||
result[labelManufacturerName] = light.ManufacturerName
|
||||
result[labelSwVersion] = light.SwVersion
|
||||
result[labelSwConfigID] = light.SwConfigID
|
||||
result[labelUniqueID] = light.UniqueID
|
||||
|
||||
// State
|
||||
result[LabelStateOn] = light.State.On
|
||||
result[LabelStateAlert] = light.State.Alert
|
||||
result[LabelStateBri] = light.State.Bri
|
||||
result[LabelStateColorMode] = light.State.ColorMode
|
||||
result[LabelStateCT] = light.State.Ct
|
||||
result[LabelStateReachable] = light.State.Reachable
|
||||
result[LabelStateSaturation] = light.State.Sat
|
||||
result[labelStateOn] = light.State.On
|
||||
result[labelStateAlert] = light.State.Alert
|
||||
result[labelStateBri] = light.State.Bri
|
||||
result[labelStateColorMode] = light.State.ColorMode
|
||||
result[labelStateCT] = light.State.Ct
|
||||
result[labelStateReachable] = light.State.Reachable
|
||||
result[labelStateSaturation] = light.State.Sat
|
||||
|
||||
lightData = append(lightData, result)
|
||||
}
|
||||
return lightData, nil
|
||||
}
|
||||
|
||||
func collectBridgeInfo(bridge *hueAPI.Bridge) (bridgeData []map[string]interface{}, err error) {
|
||||
|
||||
config, err := bridge.GetConfig()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[GetConfig] '%v'", err)
|
||||
}
|
||||
result := make(map[string]interface{})
|
||||
result[labelName] = config.Name
|
||||
result[labelAPIVersion] = config.APIVersion
|
||||
result[labelBridgeID] = config.BridgeID
|
||||
result[labelIPAddress] = config.IPAddress
|
||||
result[labelInternetServiceInternet] = config.InternetService.Internet
|
||||
result[labelInternetServiceRemoteAccess] = config.InternetService.RemoteAccess
|
||||
result[labelInternetServiceSwUpdate] = config.InternetService.SwUpdate
|
||||
result[labelInternetServiceTime] = config.InternetService.Time
|
||||
result[labelLocalTime] = config.LocalTime
|
||||
result[labelModelID] = config.ModelID
|
||||
result[labelSwVersion] = config.SwVersion
|
||||
result[labelSwUpdate2LastChange] = config.SwUpdate2.LastChange
|
||||
result[labelZigbeeChannel] = config.ZigbeeChannel
|
||||
|
||||
bridgeData = append(bridgeData, result)
|
||||
return bridgeData, nil
|
||||
}
|
||||
|
|
27
main.go
27
main.go
|
@ -1,7 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
|
@ -11,12 +13,14 @@ import (
|
|||
|
||||
"github.com/aexel90/hue_exporter/collector"
|
||||
"github.com/aexel90/hue_exporter/hue"
|
||||
"github.com/aexel90/hue_exporter/metric"
|
||||
)
|
||||
|
||||
var (
|
||||
flagBridgeURL = flag.String("hue-url", "", "The URL of the bridge")
|
||||
flagUsername = flag.String("username", "", "The username token having bridge access")
|
||||
flagAddress = flag.String("listen-address", "127.0.0.1:9773", "The address to listen on for HTTP requests.")
|
||||
flagMetricsFile = flag.String("metrics-file", "metrics.json", "The JSON file with the metric definitions.")
|
||||
|
||||
flagTest = flag.Bool("test", false, "test configured metrics")
|
||||
flagCollect = flag.Bool("collect", false, "test configured metrics")
|
||||
|
@ -27,13 +31,21 @@ func main() {
|
|||
|
||||
flag.Parse()
|
||||
|
||||
var metricsFile *metric.MetricsFile
|
||||
|
||||
// collect mode
|
||||
if *flagCollect {
|
||||
hue.CollectAll(*flagBridgeURL, *flagUsername, *flagCollectFile)
|
||||
return
|
||||
}
|
||||
|
||||
hueCollector, err := collector.NewHueCollector(*flagBridgeURL, *flagUsername)
|
||||
err := readAndParseFile(*flagMetricsFile, &metricsFile)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
hueCollector, err := collector.NewHueCollector(*flagBridgeURL, *flagUsername, metricsFile)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
|
@ -48,3 +60,16 @@ func main() {
|
|||
log.Fatal(http.ListenAndServe(*flagAddress, nil))
|
||||
}
|
||||
}
|
||||
|
||||
func readAndParseFile(file string, v interface{}) error {
|
||||
jsonData, err := ioutil.ReadFile(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading metric file: %v", err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(jsonData, v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing JSON: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -14,14 +14,20 @@ type PrometheusResult struct {
|
|||
|
||||
// Metric struct
|
||||
type Metric struct {
|
||||
HueType string
|
||||
Labels []string
|
||||
HueType string `json:"type"`
|
||||
ResultKey string `json:"resultKey"`
|
||||
FqName string `json:"fqName"`
|
||||
Help string `json:"help"`
|
||||
Labels []string `json:"labels"`
|
||||
|
||||
MetricResult []map[string]interface{}
|
||||
ResultKey string
|
||||
FqName string
|
||||
Help string
|
||||
|
||||
PromType prometheus.ValueType
|
||||
PromDesc *prometheus.Desc
|
||||
PromResult []*PrometheusResult
|
||||
}
|
||||
|
||||
// MetricsFile struct
|
||||
type MetricsFile struct {
|
||||
Metrics []*Metric `json:"metrics"`
|
||||
}
|
||||
|
|
95
metrics.json
Normal file
95
metrics.json
Normal file
|
@ -0,0 +1,95 @@
|
|||
{
|
||||
"metrics": [
|
||||
{
|
||||
"type": "light",
|
||||
"fqname": "hue_light_info",
|
||||
"help": "Non-numeric data, value is always 1",
|
||||
"labels": [
|
||||
"id",
|
||||
"manufacturer_name",
|
||||
"model_id",
|
||||
"name",
|
||||
"state_alert",
|
||||
"state_bri",
|
||||
"state_color_mode",
|
||||
"state_ct",
|
||||
"state_on",
|
||||
"state_reachable",
|
||||
"state_saturation",
|
||||
"sw_config_id",
|
||||
"sw_version",
|
||||
"type",
|
||||
"unique_id"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "light",
|
||||
"fqname": "hue_light_state",
|
||||
"help": "light status (1=ON, 0=OFF)",
|
||||
"resultKey": "state_on",
|
||||
"labels": [
|
||||
"name"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "sesnsor",
|
||||
"fqname": "hue_sensor_info",
|
||||
"help": "Non-numeric data, value is always 1",
|
||||
"labels": [
|
||||
"config_battery",
|
||||
"config_on",
|
||||
"config_reachable",
|
||||
"id",
|
||||
"manufacturer_name",
|
||||
"model_id",
|
||||
"name",
|
||||
"state_buttonevent",
|
||||
"state_daylight",
|
||||
"state_lastupdated",
|
||||
"state_lightlevel",
|
||||
"state_temperature",
|
||||
"sw_version",
|
||||
"type",
|
||||
"unique_id"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "sensor",
|
||||
"fqname": "hue_sensor_temperature",
|
||||
"help": "temperature level celsius degree",
|
||||
"resultKey": "state_temperature",
|
||||
"labels": [
|
||||
"name"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "sensor",
|
||||
"fqname": "hue_sensor_lightlevel",
|
||||
"help": "light level",
|
||||
"resultKey": "state_lightlevel",
|
||||
"labels": [
|
||||
"name"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "bridge",
|
||||
"fqname": "hue_brdige_info",
|
||||
"help": "Non-numeric data, value is always 1",
|
||||
"labels": [
|
||||
"api_version",
|
||||
"bridge_id",
|
||||
"internetservice_internet",
|
||||
"internetservice_remoteaccess",
|
||||
"internetservice_swupdate",
|
||||
"internetservice_time",
|
||||
"ip_address",
|
||||
"local_time",
|
||||
"model_id",
|
||||
"name",
|
||||
"sw_update_last_change",
|
||||
"sw_version",
|
||||
"zigbee_channel"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue