Skip to content
This repository was archived by the owner on Jun 30, 2021. It is now read-only.

Commit c9a4ef1

Browse files
committed
Added basic exporter features
1 parent 7eb1e53 commit c9a4ef1

File tree

9 files changed

+448
-0
lines changed

9 files changed

+448
-0
lines changed

.gitignore

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,65 @@
1010

1111
# Output of the go coverage tool, specifically when used with LiteIDE
1212
*.out
13+
### JetBrains template
14+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
15+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
16+
17+
# User-specific stuff
18+
.idea/**/workspace.xml
19+
.idea/**/tasks.xml
20+
.idea/**/usage.statistics.xml
21+
.idea/**/dictionaries
22+
.idea/**/shelf
23+
24+
# Sensitive or high-churn files
25+
.idea/**/dataSources/
26+
.idea/**/dataSources.ids
27+
.idea/**/dataSources.local.xml
28+
.idea/**/sqlDataSources.xml
29+
.idea/**/dynamic.xml
30+
.idea/**/uiDesigner.xml
31+
.idea/**/dbnavigator.xml
32+
33+
# Gradle
34+
.idea/**/gradle.xml
35+
.idea/**/libraries
36+
37+
# Gradle and Maven with auto-import
38+
# When using Gradle or Maven with auto-import, you should exclude module files,
39+
# since they will be recreated, and may cause churn. Uncomment if using
40+
# auto-import.
41+
# .idea/modules.xml
42+
# .idea/*.iml
43+
# .idea/modules
44+
45+
# CMake
46+
cmake-build-*/
47+
48+
# Mongo Explorer plugin
49+
.idea/**/mongoSettings.xml
50+
51+
# File-based project format
52+
*.iws
53+
54+
# IntelliJ
55+
out/
56+
57+
# mpeltonen/sbt-idea plugin
58+
.idea_modules/
59+
60+
# JIRA plugin
61+
atlassian-ide-plugin.xml
62+
63+
# Cursive Clojure plugin
64+
.idea/replstate.xml
65+
66+
# Crashlytics plugin (for Android Studio and IntelliJ)
67+
com_crashlytics_export_strings.xml
68+
crashlytics.properties
69+
crashlytics-build.properties
70+
fabric.properties
71+
72+
# Editor-based Rest Client
73+
.idea/httpRequests
74+

app.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package main
2+
3+
import (
4+
"./exporter"
5+
"./utils"
6+
"flag"
7+
"github.com/prometheus/client_golang/prometheus"
8+
"github.com/prometheus/client_golang/prometheus/promhttp"
9+
"log"
10+
"net/http"
11+
)
12+
13+
func main() {
14+
flag.Parse()
15+
utils.ParseConfig()
16+
17+
exp := exporter.New()
18+
19+
prometheus.MustRegister(exp)
20+
21+
listenAddress := utils.Config().Listen.Address
22+
23+
http.Handle(utils.Config().Listen.MetricsPath, promhttp.Handler())
24+
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
25+
http.Redirect(w, r, utils.Config().Listen.MetricsPath, http.StatusMovedPermanently)
26+
})
27+
28+
log.Printf("Starting Raspberry PI exporter on %q", listenAddress)
29+
30+
if err := http.ListenAndServe(listenAddress, nil); err != nil {
31+
log.Fatalf("Cannot start Raspberry PI exporter: %s", err)
32+
} else {
33+
log.Printf("Started Raspberry PI exporter on %q", listenAddress)
34+
}
35+
}

collector/clock.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package collector
2+
3+
import (
4+
"../utils"
5+
"github.com/prometheus/client_golang/prometheus"
6+
"regexp"
7+
"strconv"
8+
)
9+
10+
const (
11+
CoreClock string = "core"
12+
EmmcClock string = "emmc"
13+
ArmClock string = "arm"
14+
)
15+
16+
func getClock(desc *prometheus.Desc, device string) prometheus.Metric {
17+
clock, err := utils.ExecuteVcGen("measure_clock", device)
18+
19+
if err != nil {
20+
return prometheus.NewInvalidMetric(desc, err)
21+
}
22+
23+
clock = regexp.MustCompile(`frequency\(\d*\)=|(\n)|(\r)`).ReplaceAllString(clock, "")
24+
25+
clockFloat, err := strconv.ParseFloat(clock, 64)
26+
27+
if err != nil {
28+
return prometheus.NewInvalidMetric(desc, err)
29+
}
30+
31+
return prometheus.MustNewConstMetric(
32+
desc,
33+
prometheus.GaugeValue,
34+
clockFloat,
35+
)
36+
}

collector/coretemp.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package collector
2+
3+
import (
4+
"../utils"
5+
"github.com/prometheus/client_golang/prometheus"
6+
"io/ioutil"
7+
"regexp"
8+
"strconv"
9+
"strings"
10+
)
11+
12+
func getCoreTemp(collector VcGenCmdCollector) prometheus.Metric {
13+
coreTempFromSys, err := ioutil.ReadFile("/sys/class/thermal/thermal_zone0/temp")
14+
var coreTemp string
15+
method := "file"
16+
17+
if err != nil {
18+
if coreTemp, err = utils.ExecuteVcGen("measure_temp"); err != nil {
19+
return prometheus.NewInvalidMetric(collector.CoreTemp, err)
20+
} else {
21+
coreTemp = regexp.MustCompile(`(temp=)|('C)|(\n)|(\r)`).ReplaceAllString(coreTemp, "")
22+
method = "vcgen"
23+
}
24+
} else {
25+
coreTemp = string(coreTempFromSys)
26+
}
27+
28+
coreTemp = strings.TrimSuffix(coreTemp, "\n")
29+
coreTempFloat, err := strconv.ParseFloat(coreTemp, 64)
30+
31+
if err != nil {
32+
return prometheus.NewInvalidMetric(collector.CoreTemp, err)
33+
}
34+
35+
if method == "file" {
36+
coreTempFloat /= 1000
37+
}
38+
39+
return prometheus.MustNewConstMetric(
40+
collector.CoreTemp,
41+
prometheus.GaugeValue,
42+
coreTempFloat,
43+
)
44+
}

collector/vcgencmcollector.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package collector
2+
3+
import (
4+
"github.com/prometheus/client_golang/prometheus"
5+
)
6+
7+
type VcGenCmdCollector struct {
8+
CoreTemp *prometheus.Desc
9+
CoreVoltage *prometheus.Desc
10+
SdramControllerVoltage *prometheus.Desc
11+
SdramInputOutputVoltage *prometheus.Desc
12+
SdramPhysicalVoltage *prometheus.Desc
13+
CoreClock *prometheus.Desc
14+
ArmClock *prometheus.Desc
15+
EmmcClock *prometheus.Desc
16+
}
17+
18+
func (VcGenCmdCollector) Describe(channel chan<- *prometheus.Desc) {
19+
var collector = NewVcGenCmdCollector()
20+
21+
channel <- collector.CoreTemp
22+
channel <- collector.CoreVoltage
23+
channel <- collector.SdramControllerVoltage
24+
channel <- collector.SdramInputOutputVoltage
25+
channel <- collector.SdramPhysicalVoltage
26+
channel <- collector.CoreClock
27+
channel <- collector.ArmClock
28+
channel <- collector.EmmcClock
29+
}
30+
31+
func (VcGenCmdCollector) Collect(channel chan<- prometheus.Metric) {
32+
var collector = NewVcGenCmdCollector()
33+
34+
channel <- getCoreTemp(*collector)
35+
channel <- getVoltage(collector.CoreVoltage, CoreVoltage)
36+
channel <- getVoltage(collector.SdramPhysicalVoltage, SdramPhysicalVoltage)
37+
channel <- getVoltage(collector.SdramInputOutputVoltage, SdramInputOutputVoltage)
38+
channel <- getVoltage(collector.SdramControllerVoltage, SdramControllerVoltage)
39+
channel <- getClock(collector.CoreClock, CoreClock)
40+
channel <- getClock(collector.ArmClock, ArmClock)
41+
channel <- getClock(collector.EmmcClock, EmmcClock)
42+
}
43+
44+
var _ prometheus.Collector = &VcGenCmdCollector{}
45+
46+
func NewVcGenCmdCollector() *VcGenCmdCollector {
47+
const (
48+
subsystem = "vcgencmd"
49+
namespace = "pi"
50+
)
51+
52+
return &VcGenCmdCollector{
53+
CoreTemp: prometheus.NewDesc(
54+
prometheus.BuildFQName(namespace, subsystem, "core_temp"),
55+
"Temperature of the SoC",
56+
nil,
57+
nil,
58+
),
59+
CoreVoltage: prometheus.NewDesc(
60+
prometheus.BuildFQName(namespace, subsystem, "core_voltage"),
61+
"Voltage of the CPU",
62+
nil,
63+
nil,
64+
),
65+
SdramControllerVoltage: prometheus.NewDesc(
66+
prometheus.BuildFQName(namespace, subsystem, "sdram_controller_voltage"),
67+
"Voltage of the SDRAM controller",
68+
nil,
69+
nil,
70+
),
71+
SdramInputOutputVoltage: prometheus.NewDesc(
72+
prometheus.BuildFQName(namespace, subsystem, "sdram_input_output_voltage"),
73+
"Voltage of the SDRAM IO",
74+
nil,
75+
nil,
76+
),
77+
SdramPhysicalVoltage: prometheus.NewDesc(
78+
prometheus.BuildFQName(namespace, subsystem, "sdram_physical_voltage"),
79+
"Voltage of the physical SDRAM",
80+
nil,
81+
nil,
82+
),
83+
CoreClock: prometheus.NewDesc(
84+
prometheus.BuildFQName(namespace, subsystem, "core_clock"),
85+
"Clock of the core in Hz",
86+
nil,
87+
nil,
88+
),
89+
ArmClock: prometheus.NewDesc(
90+
prometheus.BuildFQName(namespace, subsystem, "arm_clock"),
91+
"Clock of the ARM CPU in Hz",
92+
nil,
93+
nil,
94+
),
95+
EmmcClock: prometheus.NewDesc(
96+
prometheus.BuildFQName(namespace, subsystem, "emmc_clock"),
97+
"Clock of the external MMC in Hz",
98+
nil,
99+
nil,
100+
),
101+
}
102+
}

collector/voltage.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package collector
2+
3+
import (
4+
"../utils"
5+
"github.com/prometheus/client_golang/prometheus"
6+
"regexp"
7+
"strconv"
8+
)
9+
10+
const (
11+
CoreVoltage string = "core"
12+
SdramControllerVoltage string = "sdram_c"
13+
SdramInputOutputVoltage string = "sdram_i"
14+
SdramPhysicalVoltage string = "sdram_p"
15+
)
16+
17+
func getVoltage(desc *prometheus.Desc, device string) prometheus.Metric {
18+
voltage, err := utils.ExecuteVcGen("measure_volts", device)
19+
20+
if err != nil {
21+
return prometheus.NewInvalidMetric(desc, err)
22+
}
23+
24+
voltage = regexp.MustCompile(`(volt=)|(V)|(\n)|(\r)`).ReplaceAllString(voltage, "")
25+
26+
voltageFloat, err := strconv.ParseFloat(voltage, 64)
27+
28+
if err != nil {
29+
return prometheus.NewInvalidMetric(desc, err)
30+
}
31+
32+
return prometheus.MustNewConstMetric(
33+
desc,
34+
prometheus.GaugeValue,
35+
voltageFloat,
36+
)
37+
}

exporter/raspberryexporter.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package exporter
2+
3+
import (
4+
"../collector"
5+
"github.com/prometheus/client_golang/prometheus"
6+
"sync"
7+
)
8+
9+
type Exporter struct {
10+
mutex sync.Mutex
11+
collectors []prometheus.Collector
12+
}
13+
14+
func New() Exporter {
15+
var exporter = Exporter{}
16+
exporter.collectors = []prometheus.Collector{
17+
collector.NewVcGenCmdCollector(),
18+
}
19+
20+
return exporter
21+
}
22+
23+
func (exporter Exporter) Describe(channel chan<- *prometheus.Desc) {
24+
for _, cc := range exporter.collectors {
25+
cc.Describe(channel)
26+
}
27+
}
28+
29+
func (exporter Exporter) Collect(channel chan<- prometheus.Metric) {
30+
for _, c := range exporter.collectors {
31+
c.Collect(channel)
32+
}
33+
}
34+
35+
var _ prometheus.Collector = &Exporter{}

0 commit comments

Comments
 (0)