Skip to content

Commit d7c8f06

Browse files
exporter: add global resource sink metrics
FRM exposes the amount of coupons and points via `/getResourceSink` and allows to monitor the total amount of points per minute with `rate`. Signed-off-by: Tan Siewert <tan@siewert.io>
1 parent e04bf3a commit d7c8f06

6 files changed

Lines changed: 103 additions & 28 deletions

File tree

Companion/exporter/exporter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func NewPrometheusExporter(frmApiHosts []string) *PrometheusExporter {
3838
vehicleStationCollector := NewVehicleStationCollector("/getTruckStation")
3939
trainCollector := NewTrainCollector("/getTrains")
4040
trainStationCollector := NewTrainStationCollector("/getTrainStation")
41-
resourceSinkCollector := NewResourceSinkCollector("/getResourceSinkBuilding")
41+
resourceSinkCollector := NewResourceSinkCollector("/getResourceSinkBuilding", "/getResourceSink")
4242
pumpCollector := NewPumpCollector("/getPump")
4343
extractorCollector := NewExtractorCollector("/getExtractor")
4444
portalCollector := NewPortalCollector("/getPortal")

Companion/exporter/frm_server_fake_test.go

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,23 @@ import (
99
)
1010

1111
type FRMServerFake struct {
12-
server *httptest.Server
13-
productionData []exporter.ProductionDetails
14-
powerData []exporter.PowerDetails
15-
factoryBuildings []exporter.BuildingDetail
16-
vehicleData []exporter.VehicleDetails
17-
trainData []exporter.TrainDetails
18-
droneData []exporter.DroneStationDetails
19-
vehicleStationData []exporter.VehicleStationDetails
20-
trainStationData []exporter.TrainStationDetails
21-
resourceSinkData []exporter.ResourceSinkDetails
22-
sessionInfoData exporter.SessionInfo
23-
pumpData []exporter.PumpDetails
24-
extractorData []exporter.ExtractorDetails
25-
portalData []exporter.PortalDetails
26-
hypertubeData []exporter.HypertubeDetails
27-
frackingData []exporter.FrackingDetails
12+
server *httptest.Server
13+
productionData []exporter.ProductionDetails
14+
powerData []exporter.PowerDetails
15+
factoryBuildings []exporter.BuildingDetail
16+
vehicleData []exporter.VehicleDetails
17+
trainData []exporter.TrainDetails
18+
droneData []exporter.DroneStationDetails
19+
vehicleStationData []exporter.VehicleStationDetails
20+
trainStationData []exporter.TrainStationDetails
21+
resourceSinkData []exporter.ResourceSinkDetails
22+
gloalResourceSinkData []exporter.ResourceSinkGlobalDetails
23+
sessionInfoData exporter.SessionInfo
24+
pumpData []exporter.PumpDetails
25+
extractorData []exporter.ExtractorDetails
26+
portalData []exporter.PortalDetails
27+
hypertubeData []exporter.HypertubeDetails
28+
frackingData []exporter.FrackingDetails
2829
}
2930

3031
func NewFRMServerFake() *FRMServerFake {
@@ -43,6 +44,7 @@ func NewFRMServerFake() *FRMServerFake {
4344
mux.Handle("/getVehicles", http.HandlerFunc(getStatsHandler(&fake.vehicleData)))
4445
mux.Handle("/getTruckStation", http.HandlerFunc(getStatsHandler(&fake.vehicleStationData)))
4546
mux.Handle("/getTrainStation", http.HandlerFunc(getStatsHandler(&fake.trainStationData)))
47+
mux.Handle("/getResourceSink", http.HandlerFunc(getStatsHandler(&fake.gloalResourceSinkData)))
4648
mux.Handle("/getResourceSinkBuilding", http.HandlerFunc(getStatsHandler(&fake.resourceSinkData)))
4749
mux.Handle("/getSessionInfo", http.HandlerFunc(getStatsHandler(&fake.sessionInfoData)))
4850
mux.Handle("/getPump", http.HandlerFunc(getStatsHandler(&fake.pumpData)))
@@ -104,6 +106,10 @@ func (e *FRMServerFake) ReturnsResourceSinkData(data []exporter.ResourceSinkDeta
104106
e.resourceSinkData = data
105107
}
106108

109+
func (e *FRMServerFake) ReturnsGlobalResourceSinkData(data []exporter.ResourceSinkGlobalDetails) {
110+
e.gloalResourceSinkData = data
111+
}
112+
107113
func (e *FRMServerFake) ReturnsPumpData(data []exporter.PumpDetails) {
108114
e.pumpData = data
109115
}

Companion/exporter/resource_sink_collector.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,52 @@ import (
66
)
77

88
type ResourceSinkCollector struct {
9-
endpoint string
9+
buildingEndpoint string
10+
globalEndpoint string
1011
}
1112

1213
type ResourceSinkDetails struct {
1314
Location Location `json:"location"`
1415
PowerInfo PowerInfo `json:"PowerInfo"`
1516
}
1617

17-
func NewResourceSinkCollector(endpoint string) *ResourceSinkCollector {
18+
type ResourceSinkGlobalDetails struct {
19+
NumCoupon int `json:"NumCoupon"`
20+
TotalPoints int `json:"TotalPoints"`
21+
PointsToCoupon int `json:"PointsToCoupon"`
22+
}
23+
24+
func NewResourceSinkCollector(buildingEndpoint, globalEndpoint string) *ResourceSinkCollector {
1825
return &ResourceSinkCollector{
19-
endpoint: endpoint,
26+
buildingEndpoint: buildingEndpoint,
27+
globalEndpoint: globalEndpoint,
2028
}
2129
}
2230

2331
func (c *ResourceSinkCollector) Collect(frmAddress string, sessionName string) {
24-
details := []ResourceSinkDetails{}
25-
err := retrieveData(frmAddress+c.endpoint, &details)
32+
buildingDetails := []ResourceSinkDetails{}
33+
err := retrieveData(frmAddress+c.buildingEndpoint, &buildingDetails)
34+
if err != nil {
35+
log.Printf("error reading resource sink details statistics from FRM: %s\n", err)
36+
return
37+
}
38+
39+
globalDetails := []ResourceSinkGlobalDetails{}
40+
err = retrieveData(frmAddress+c.globalEndpoint, &globalDetails)
2641
if err != nil {
27-
log.Printf("error reading vehicle station statistics from FRM: %s\n", err)
42+
log.Printf("error reading global resource sink statistics from FRM: %s\n", err)
2843
return
2944
}
3045

46+
for _, d := range globalDetails {
47+
ResourceSinkTotalPoints.WithLabelValues(frmAddress, sessionName).Set(float64(d.TotalPoints))
48+
ResourceSinkPointsToCoupon.WithLabelValues(frmAddress, sessionName).Set(float64(d.PointsToCoupon))
49+
ResourceSinkCollectedCoupons.WithLabelValues(frmAddress, sessionName).Set(float64(d.NumCoupon))
50+
}
51+
3152
powerInfo := map[float64]float64{}
3253
maxPowerInfo := map[float64]float64{}
33-
for _, d := range details {
54+
for _, d := range buildingDetails {
3455
val, ok := powerInfo[d.PowerInfo.CircuitGroupId]
3556
if ok {
3657
powerInfo[d.PowerInfo.CircuitGroupId] = val + d.PowerInfo.PowerConsumed

Companion/exporter/resource_sink_collector_test.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ var _ = Describe("ResourceSinkCollector", func() {
1414
BeforeEach(func() {
1515
FRMServer.Reset()
1616
url = FRMServer.server.URL
17-
collector = exporter.NewResourceSinkCollector("/getResourceSinkBuilding")
17+
collector = exporter.NewResourceSinkCollector("/getResourceSinkBuilding", "/getResourceSink")
1818

1919
FRMServer.ReturnsResourceSinkData([]exporter.ResourceSinkDetails{
2020
{
@@ -39,6 +39,14 @@ var _ = Describe("ResourceSinkCollector", func() {
3939
},
4040
},
4141
})
42+
43+
FRMServer.ReturnsGlobalResourceSinkData([]exporter.ResourceSinkGlobalDetails{
44+
{
45+
TotalPoints: 100,
46+
PointsToCoupon: 200,
47+
NumCoupon: 1,
48+
},
49+
})
4250
})
4351

4452
AfterEach(func() {
@@ -63,4 +71,31 @@ var _ = Describe("ResourceSinkCollector", func() {
6371
Expect(val).To(Equal(90.0))
6472
})
6573
})
74+
75+
Describe("Resource sink global metrics collection", func() {
76+
It("sets the 'resource_sink_total_points' metric with the right labels", func() {
77+
collector.Collect(url, sessionName)
78+
79+
val, err := gaugeValue(exporter.ResourceSinkTotalPoints, url, sessionName)
80+
81+
Expect(err).ToNot(HaveOccurred())
82+
Expect(val).To(Equal(100.0))
83+
})
84+
It("sets the 'resource_sink_points_to_coupon' metric with the right labels", func() {
85+
collector.Collect(url, sessionName)
86+
87+
val, err := gaugeValue(exporter.ResourceSinkPointsToCoupon, url, sessionName)
88+
89+
Expect(err).ToNot(HaveOccurred())
90+
Expect(val).To(Equal(200.0))
91+
})
92+
It("sets the 'resource_sink_collected_coupons' metric with the right labels", func() {
93+
collector.Collect(url, sessionName)
94+
95+
val, err := gaugeValue(exporter.ResourceSinkCollectedCoupons, url, sessionName)
96+
97+
Expect(err).ToNot(HaveOccurred())
98+
Expect(val).To(Equal(1.0))
99+
})
100+
})
66101
})

Companion/exporter/resource_sink_metrics.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,19 @@ var (
1818
}, []string{
1919
"circuit_id",
2020
})
21+
22+
ResourceSinkTotalPoints = RegisterNewGaugeVec(prometheus.GaugeOpts{
23+
Name: "resource_sink_total_points",
24+
Help: "AWESOME sink total points",
25+
}, []string{})
26+
27+
ResourceSinkPointsToCoupon = RegisterNewGaugeVec(prometheus.GaugeOpts{
28+
Name: "resource_sink_points_to_coupon",
29+
Help: "AWESOME sink points to next coupon",
30+
}, []string{})
31+
32+
ResourceSinkCollectedCoupons = RegisterNewGaugeVec(prometheus.GaugeOpts{
33+
Name: "resource_sink_collected_coupons",
34+
Help: "AWESOME sink collected coupons",
35+
}, []string{})
2136
)

Companion/go.mod

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
module github.com/AP-Hunt/FicsitRemoteMonitoringCompanion/Companion
22

3-
go 1.22.0
4-
5-
toolchain go1.23.0
3+
go 1.23.4
64

75
require (
86
github.com/coder/quartz v0.1.2

0 commit comments

Comments
 (0)