-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Carlos Alexandro Becker <[email protected]>
- Loading branch information
0 parents
commit 683b3e6
Showing
9 changed files
with
721 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
github: [caarlos0] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
bin/ | ||
dist/ | ||
coverage.out |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
before: | ||
hooks: | ||
- go mod tidy | ||
gomod: | ||
proxy: true | ||
build: | ||
goarch: | ||
- amd64 | ||
- arm64 | ||
env: | ||
- CGO_ENABLED=0 | ||
nfpms: | ||
- vendor: Becker Software LTDA | ||
homepage: https://carlosbecker.com | ||
maintainer: Carlos Becker <[email protected]> | ||
description: Exports Speedtest results to the Prometheus format | ||
formats: | ||
- deb | ||
- apk | ||
- rpm | ||
dependencies: | ||
- speedtest-cli | ||
brews: | ||
- tap: | ||
owner: caarlos0 | ||
name: homebrew-tap | ||
folder: Formula | ||
description: Exports Speedtest results to the Prometheus format | ||
checksum: | ||
name_template: '{{ .ProjectName }}_checksums.txt' | ||
archives: | ||
- name_template: '{{ .Binary }}_{{ .Os }}_{{ .Arch }}' | ||
dockers: | ||
- image_templates: | ||
- 'ghcr.io/caarlos0/speedtest-exporter:{{ .Tag }}-amd64' | ||
- 'caarlos0/speedtest-exporter:{{ .Tag }}-amd64' | ||
dockerfile: Dockerfile | ||
use_buildx: true | ||
build_flag_templates: | ||
- "--pull" | ||
- "--label=org.opencontainers.image.created={{.Date}}" | ||
- "--label=org.opencontainers.image.name={{.ProjectName}}" | ||
- "--label=org.opencontainers.image.revision={{.FullCommit}}" | ||
- "--label=org.opencontainers.image.version={{.Version}}" | ||
- "--label=org.opencontainers.image.source=https://github.com/caarlos0/speedtest-exporter" | ||
- "--platform=linux/amd64" | ||
- image_templates: | ||
- 'ghcr.io/caarlos0/speedtest-exporter:{{ .Tag }}-arm64' | ||
- 'caarlos0/speedtest-exporter:{{ .Tag }}-arm64' | ||
dockerfile: Dockerfile | ||
use_buildx: true | ||
build_flag_templates: | ||
- "--pull" | ||
- "--label=org.opencontainers.image.created={{.Date}}" | ||
- "--label=org.opencontainers.image.name={{.ProjectName}}" | ||
- "--label=org.opencontainers.image.revision={{.FullCommit}}" | ||
- "--label=org.opencontainers.image.version={{.Version}}" | ||
- "--label=org.opencontainers.image.source=https://github.com/caarlos0/speedtest-exporter" | ||
- "--platform=linux/arm64" | ||
goarch: arm64 | ||
docker_manifests: | ||
- name_template: 'ghcr.io/caarlos0/speedtest-exporter:{{ .Tag }}' | ||
image_templates: | ||
- 'ghcr.io/caarlos0/speedtest-exporter:{{ .Tag }}-amd64' | ||
- 'ghcr.io/caarlos0/speedtest-exporter:{{ .Tag }}-arm64' | ||
- name_template: 'ghcr.io/caarlos0/speedtest-exporter:latest' | ||
image_templates: | ||
- 'ghcr.io/caarlos0/speedtest-exporter:{{ .Tag }}-amd64' | ||
- 'ghcr.io/caarlos0/speedtest-exporter:{{ .Tag }}-arm64' | ||
- name_template: 'caarlos0/speedtest-exporter:{{ .Tag }}' | ||
image_templates: | ||
- 'caarlos0/speedtest-exporter:{{ .Tag }}-amd64' | ||
- 'caarlos0/speedtest-exporter:{{ .Tag }}-arm64' | ||
- name_template: 'caarlos0/speedtest-exporter:latest' | ||
image_templates: | ||
- 'caarlos0/speedtest-exporter:{{ .Tag }}-amd64' | ||
- 'caarlos0/speedtest-exporter:{{ .Tag }}-arm64' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
FROM alpine | ||
EXPOSE 9876 | ||
WORKDIR / | ||
COPY speedtest-exporter*.apk /tmp | ||
RUN apk add --allow-untrusted /tmp/speedtest-exporter*.apk | ||
ENTRYPOINT ["/usr/local/bin/speedtest-exporter"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# speedtest-exporter | ||
|
||
Exports speedtest-cli metrics in the prometheus format. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
package collector | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"os/exec" | ||
"sync" | ||
"time" | ||
|
||
"github.com/patrickmn/go-cache" | ||
"github.com/prometheus/client_golang/prometheus" | ||
"github.com/prometheus/common/log" | ||
) | ||
|
||
type speedtestCollector struct { | ||
mutex sync.Mutex | ||
cache *cache.Cache | ||
|
||
up *prometheus.Desc | ||
scrapeDuration *prometheus.Desc | ||
pingSeconds *prometheus.Desc | ||
downloadSpeedBytes *prometheus.Desc | ||
uploadSpeedBytes *prometheus.Desc | ||
downloadedBytes *prometheus.Desc | ||
uploadedBytes *prometheus.Desc | ||
} | ||
|
||
// NewSpeedtestCollector returns a releases collector | ||
func NewSpeedtestCollector(cache *cache.Cache) prometheus.Collector { | ||
const namespace = "speedtest" | ||
const subsystem = "" | ||
return &speedtestCollector{ | ||
cache: cache, | ||
up: prometheus.NewDesc( | ||
prometheus.BuildFQName(namespace, subsystem, "up"), | ||
"Exporter is being able to talk with GitHub API", | ||
nil, | ||
nil, | ||
), | ||
scrapeDuration: prometheus.NewDesc( | ||
prometheus.BuildFQName(namespace, subsystem, "scrape_duration_seconds"), | ||
"Returns how long the probe took to complete in seconds", | ||
nil, | ||
nil, | ||
), | ||
pingSeconds: prometheus.NewDesc( | ||
prometheus.BuildFQName(namespace, subsystem, "ping_seconds"), | ||
"Latency", | ||
nil, | ||
nil, | ||
), | ||
downloadSpeedBytes: prometheus.NewDesc( | ||
prometheus.BuildFQName(namespace, subsystem, "download_speed_bytes"), | ||
"Download speed", | ||
nil, | ||
nil, | ||
), | ||
uploadSpeedBytes: prometheus.NewDesc( | ||
prometheus.BuildFQName(namespace, subsystem, "upload_speed_bytes"), | ||
"Upload speed", | ||
nil, | ||
nil, | ||
), | ||
downloadedBytes: prometheus.NewDesc( | ||
prometheus.BuildFQName(namespace, subsystem, "downloaded_bytes"), | ||
"Downloaded bytes", | ||
nil, | ||
nil, | ||
), | ||
uploadedBytes: prometheus.NewDesc( | ||
prometheus.BuildFQName(namespace, subsystem, "uploaded_bytes"), | ||
"Uploaded bytes", | ||
nil, | ||
nil, | ||
), | ||
} | ||
} | ||
|
||
// Describe all metrics | ||
func (c *speedtestCollector) Describe(ch chan<- *prometheus.Desc) { | ||
ch <- c.up | ||
ch <- c.scrapeDuration | ||
ch <- c.pingSeconds | ||
ch <- c.downloadSpeedBytes | ||
ch <- c.uploadSpeedBytes | ||
ch <- c.downloadedBytes | ||
ch <- c.uploadedBytes | ||
} | ||
|
||
// Collect all metrics | ||
func (c *speedtestCollector) Collect(ch chan<- prometheus.Metric) { | ||
c.mutex.Lock() | ||
defer c.mutex.Unlock() | ||
|
||
start := time.Now() | ||
success := 1 | ||
defer func() { | ||
ch <- prometheus.MustNewConstMetric(c.scrapeDuration, prometheus.GaugeValue, time.Since(start).Seconds()) | ||
ch <- prometheus.MustNewConstMetric(c.up, prometheus.GaugeValue, float64(success)) | ||
}() | ||
|
||
result, err := c.cachedOrCollect() | ||
if err != nil { | ||
success = 0 | ||
log.Errorf("failed to collect: %s", err.Error()) | ||
} | ||
|
||
ch <- prometheus.MustNewConstMetric(c.downloadSpeedBytes, prometheus.GaugeValue, result.Download) | ||
ch <- prometheus.MustNewConstMetric(c.uploadSpeedBytes, prometheus.GaugeValue, result.Upload) | ||
ch <- prometheus.MustNewConstMetric(c.pingSeconds, prometheus.GaugeValue, result.Ping/1000) | ||
ch <- prometheus.MustNewConstMetric(c.uploadedBytes, prometheus.GaugeValue, result.BytesSent) | ||
ch <- prometheus.MustNewConstMetric(c.downloadedBytes, prometheus.GaugeValue, result.BytesReceived) | ||
} | ||
|
||
func (c *speedtestCollector) cachedOrCollect() (SpeedtestResult, error) { | ||
cold, ok := c.cache.Get("result") | ||
if ok { | ||
log.Debug("returning results from cache") | ||
return cold.(SpeedtestResult), nil | ||
} | ||
|
||
hot, err := c.collect() | ||
if err != nil { | ||
return hot, err | ||
} | ||
c.cache.Set("result", hot, cache.DefaultExpiration) | ||
return hot, nil | ||
} | ||
|
||
func (c *speedtestCollector) collect() (SpeedtestResult, error) { | ||
log.Debug("running speedtest-cli") | ||
var out bytes.Buffer | ||
cmd := exec.Command("speedtest-cli", "--json") | ||
cmd.Stdout = &out | ||
if err := cmd.Run(); err != nil { | ||
return SpeedtestResult{}, fmt.Errorf("speedtest-cli failed: %w", err) | ||
} | ||
log.Debug("speedtest-cli result: " + out.String()) | ||
var result SpeedtestResult | ||
if err := json.Unmarshal(out.Bytes(), &result); err != nil { | ||
return SpeedtestResult{}, fmt.Errorf("failed to decode speedtest-cli output: %w", err) | ||
} | ||
return result, nil | ||
} | ||
|
||
type SpeedtestResult struct { | ||
Download float64 `json:"download"` | ||
Upload float64 `json:"upload"` | ||
Ping float64 `json:"ping"` | ||
BytesSent float64 `json:"bytes_sent"` | ||
BytesReceived float64 `json:"bytes_received"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module github.com/caarlos0/speedtest-exporter | ||
|
||
require ( | ||
github.com/alecthomas/kingpin v2.2.6+incompatible | ||
github.com/patrickmn/go-cache v2.1.0+incompatible | ||
github.com/prometheus/client_golang v1.8.0 | ||
github.com/prometheus/common v0.15.0 | ||
) | ||
|
||
go 1.16 |
Oops, something went wrong.