Skip to content

Commit

Permalink
add optional total calculation for params
Browse files Browse the repository at this point in the history
Signed-off-by: Markus Blaschke <[email protected]>
  • Loading branch information
mblaschke committed Jan 7, 2024
1 parent eb78484 commit 7b49524
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 7 deletions.
1 change: 1 addition & 0 deletions config/opts.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type (

Device struct {
AllowedConnectionStates []string `long:"myuplink.device.allowed-connectionstates" env:"MYUPLINK_DEVICE_ALLOWED_CONNECTIONSTATES" env-delim:"," description:"Allowed device connection states" default:"Connected"`
CalcTotalParameters []string `long:"myuplink.device.calc-total-parameters" env:"MYUPLINK_DEVICE_CALC_TOTAL_PARAMETRS" env-delim:"," description:"Calculate total metrics for these parameters (eg. energey log parameters)"`
}
}

Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ func main() {
logger.Info(string(opts.GetJson()))

globalCache = cache.New(60*time.Minute, 1*time.Minute)
totalParamCache.Init()

logger.Infof("connecting to myUplink")
myuplinkClient = myuplink.NewClient(logger)
Expand Down
24 changes: 18 additions & 6 deletions metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@ import (

type (
MyUplinkMetrics struct {
system *prometheus.GaugeVec
systemDevice *prometheus.GaugeVec
systemDevicePoint *prometheus.GaugeVec
systemDevicePointEnum *prometheus.GaugeVec
system *prometheus.GaugeVec
systemDevice *prometheus.GaugeVec
systemDevicePoint *prometheus.GaugeVec
systemDevicePointEnum *prometheus.GaugeVec
systemDevicePointTotal *prometheus.GaugeVec
}
)

func NewMyUplinkMetrics(registry *prometheus.Registry) *MyUplinkMetrics {
metrics := &MyUplinkMetrics{}

pointLabels := []string{"systemID", "deviceID", "category", "parameterID", "parameterName", "parameterUnit"}

metrics.system = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "myuplink_system_info",
Expand All @@ -39,7 +42,7 @@ func NewMyUplinkMetrics(registry *prometheus.Registry) *MyUplinkMetrics {
Name: "myuplink_system_device_point",
Help: "myUplink device metric point",
},
[]string{"systemID", "deviceID", "category", "parameterID", "parameterName", "parameterUnit"},
pointLabels,
)
registry.MustRegister(metrics.systemDevicePoint)

Expand All @@ -48,9 +51,18 @@ func NewMyUplinkMetrics(registry *prometheus.Registry) *MyUplinkMetrics {
Name: "myuplink_system_device_point_enum",
Help: "myUplink device metric point enum value",
},
[]string{"systemID", "deviceID", "category", "parameterID", "parameterName", "parameterUnit", "valueText"},
append(pointLabels, "valueText"),
)
registry.MustRegister(metrics.systemDevicePointEnum)

metrics.systemDevicePointTotal = prometheus.NewGaugeVec(
prometheus.GaugeOpts{
Name: "myuplink_system_device_point_total",
Help: "myUplink device metric point total",
},
pointLabels,
)
registry.MustRegister(metrics.systemDevicePointTotal)

return metrics
}
4 changes: 3 additions & 1 deletion myuplink/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type (
DesiredFwVersion string `json:"desiredFwVersion"`
}

SystemDevicePoints []struct {
SystemDevicePoint struct {
Category string `json:"category"`
ParameterID string `json:"parameterId"`
ParameterName string `json:"parameterName"`
Expand All @@ -59,6 +59,8 @@ type (
ScaleValue string `json:"scaleValue"`
ZoneID string `json:"zoneId"`
}

SystemDevicePoints []SystemDevicePoint
)

func (d *SystemDevice) IsConnectionStateAllowed(allowedValues []string) bool {
Expand Down
15 changes: 15 additions & 0 deletions probe.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ func myuplinkProbe(w http.ResponseWriter, r *http.Request) {
"parameterUnit": clearText(devicePoint.ParameterUnit),
}).Set(*devicePoint.Value)

// enum translation
enumValue := fmt.Sprintf("%d", int64(*devicePoint.Value))
for _, enumVal := range devicePoint.EnumValues {
enumMetricVal := float64(0)
Expand All @@ -128,6 +129,20 @@ func myuplinkProbe(w http.ResponseWriter, r *http.Request) {
"valueText": clearText(enumVal.Text),
}).Set(enumMetricVal)
}

// total values (counters)
for _, totalParameterID := range opts.MyUplink.Device.CalcTotalParameters {
if strings.EqualFold(devicePoint.ParameterID, totalParameterID) {
metrics.systemDevicePointTotal.With(prometheus.Labels{
"systemID": system.SystemID,
"deviceID": device.ID,
"category": clearText(devicePoint.Category),
"parameterID": devicePoint.ParameterID,
"parameterName": clearText(devicePoint.ParameterName),
"parameterUnit": clearText(devicePoint.ParameterUnit),
}).Set(totalParamCache.getParameterValue(device.ID, devicePoint.ParameterID, devicePoint))
}
}
}
}
}
Expand Down
59 changes: 59 additions & 0 deletions totalparameters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package main

import (
"fmt"
"sync"
"time"

"github.com/webdevops/myuplink-exporter/myuplink"
)

type (
TotalParameterCache struct {
lock sync.RWMutex
deviceParamMap map[string]*TotalParameterMetric
}

TotalParameterMetric struct {
updated time.Time
value float64
}
)

var (
totalParamCache TotalParameterCache
)

func (c *TotalParameterCache) Init() {
c.deviceParamMap = map[string]*TotalParameterMetric{}
}

func (c *TotalParameterCache) getParameterValue(deviceID string, parameterID string, devicePoint myuplink.SystemDevicePoint) float64 {
key := fmt.Sprintf(
"%s:%s",
deviceID,
parameterID,
)

// exists check (eg. new parameter)
if _, exists := c.deviceParamMap[key]; !exists {
c.lock.Lock()
c.deviceParamMap[key] = &TotalParameterMetric{
updated: devicePoint.Timestamp,
value: *devicePoint.Value,
}
c.lock.Unlock()
}

// increase check
if c.deviceParamMap[key].updated != devicePoint.Timestamp {
c.lock.Lock()
c.deviceParamMap[key].updated = devicePoint.Timestamp
c.deviceParamMap[key].value += *devicePoint.Value
c.lock.Unlock()
}

c.lock.RLock()
defer c.lock.RUnlock()
return c.deviceParamMap[key].value
}

0 comments on commit 7b49524

Please sign in to comment.