Merge pull request #5 from peschmae/feature/merge-kully
Feature/merge kully
This commit is contained in:
commit
64d17d5c25
11 changed files with 534 additions and 184 deletions
10
.github/workflows/go.yml
vendored
10
.github/workflows/go.yml
vendored
|
@ -12,13 +12,19 @@ jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: 1.17
|
go-version: 1.17
|
||||||
|
|
||||||
|
- name: install stringer
|
||||||
|
run: go install golang.org/x/tools/cmd/stringer@latest
|
||||||
|
|
||||||
|
- name: Generate
|
||||||
|
run: go generate ./...
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: go build -v ./...
|
run: go build -v ./...
|
||||||
|
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,5 +1,6 @@
|
||||||
mystrom-exporter
|
mystrom-exporter
|
||||||
output/*
|
output/*
|
||||||
|
*_string.go
|
||||||
|
|
||||||
# Created by https://www.toptal.com/developers/gitignore/api/osx,intellij+all,windows
|
# Created by https://www.toptal.com/developers/gitignore/api/osx,intellij+all,windows
|
||||||
# Edit at https://www.toptal.com/developers/gitignore?templates=osx,intellij+all,windows
|
# Edit at https://www.toptal.com/developers/gitignore?templates=osx,intellij+all,windows
|
||||||
|
@ -148,4 +149,4 @@ $RECYCLE.BIN/
|
||||||
# Windows shortcuts
|
# Windows shortcuts
|
||||||
*.lnk
|
*.lnk
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/osx,intellij+all,windows
|
# End of https://www.toptal.com/developers/gitignore/api/osx,intellij+all,windows
|
||||||
|
|
|
@ -2,7 +2,7 @@ FROM golang:alpine as build
|
||||||
|
|
||||||
WORKDIR /root
|
WORKDIR /root
|
||||||
COPY . /root
|
COPY . /root
|
||||||
RUN go build .
|
RUN go install golang.org/x/tools/cmd/stringer@latest && go generate ./... && go build .
|
||||||
|
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
|
|
63
Makefile
63
Makefile
|
@ -1,13 +1,56 @@
|
||||||
.PHONY: clean run
|
##
|
||||||
|
#
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
|
.PHONY: generate go-tools
|
||||||
|
|
||||||
linux:
|
version := $(shell git describe --tags --always)
|
||||||
GOOS=linux GOARCH=amd64 go build -o output/mystrom-exporter_linux-amd64
|
revision := $(shell git rev-parse HEAD)
|
||||||
mac:
|
branch := $(shell git rev-parse --abbrev-ref HEAD)
|
||||||
GOOS=darwin GOARCH=amd64 go build -o output/mystrom-exporter_mac-amd64
|
builduser := $(shell whoami)
|
||||||
arm64:
|
builddate := $(shell date '+%FT%T_%Z')
|
||||||
GOOS=linux GOARCH=arm64 go build -o output/mystrom-exporter_linux-arm64
|
|
||||||
arm:
|
versionPkgPrefix := mystrom-exporter/pkg/version
|
||||||
GOOS=linux GOARCH=arm go build -o output/mystrom-exporter_linux-arm
|
|
||||||
|
BINDIR := $(CURDIR)/output
|
||||||
|
GO ?= go
|
||||||
|
GOPATH ?= $(shell $(GO) env GOPATH)
|
||||||
|
LDFLAGS := -w -s \
|
||||||
|
-X $(versionPkgPrefix).Version=${version} \
|
||||||
|
-X $(versionPkgPrefix).Revision=${revision} \
|
||||||
|
-X $(versionPkgPrefix).Branch=${branch} \
|
||||||
|
-X $(versionPkgPrefix).BuildUser=${builduser} \
|
||||||
|
-X $(versionPkgPrefix).BuildDate=${builddate}
|
||||||
|
GOFLAGS := -v
|
||||||
|
GOX_FLAGS := -mod=vendor
|
||||||
|
GO_BUILD_FLAGS := -v
|
||||||
|
export GO111MODULE := on
|
||||||
|
|
||||||
|
build: go-tools generate ## builds the all platform binaries of the exporter
|
||||||
|
$(GOPATH)/bin/gox \
|
||||||
|
-os="darwin linux" \
|
||||||
|
-arch="amd64 arm arm64" \
|
||||||
|
-osarch="!darwin/arm" \
|
||||||
|
-output "${BINDIR}/{{.Dir}}-{{.OS}}-{{.Arch}}" \
|
||||||
|
-gcflags "$(GO_BUILD_FLAGS)" \
|
||||||
|
-ldflags '$(LDFLAGS)' \
|
||||||
|
-tags '$(TAGS)' \
|
||||||
|
./...
|
||||||
|
|
||||||
|
run:
|
||||||
|
${BINDIR}/mystrom-exporter-$(shell $(GO) env GOOS)-$(shell $(GO) env GOARCH)
|
||||||
|
|
||||||
|
|
||||||
all: linux mac arm64 arm
|
generate: go-tools
|
||||||
|
$(GO) generate ./...
|
||||||
|
|
||||||
|
go-tools: $(GOPATH)/bin/stringer $(GOPATH)/bin/gox
|
||||||
|
|
||||||
|
# -- see more info on https://pkg.go.dev/golang.org/x/tools/cmd/stringer
|
||||||
|
$(GOPATH)/bin/stringer:
|
||||||
|
$(GO) install golang.org/x/tools/cmd/stringer@latest
|
||||||
|
|
||||||
|
$(GOPATH)/bin/gox:
|
||||||
|
$(GO) install github.com/mitchellh/gox@latest
|
||||||
|
# --
|
||||||
|
help:
|
||||||
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||||
|
|
27
README.md
27
README.md
|
@ -28,9 +28,31 @@ $ ./mystrom-exporter --help
|
||||||
```
|
```
|
||||||
| Flag | Description | Default |
|
| Flag | Description | Default |
|
||||||
| ---- | ----------- | ------- |
|
| ---- | ----------- | ------- |
|
||||||
| switch.ip-address | IP address of the switch you try to monitor | `` |
|
|
||||||
| web.listen-address | Address to listen on | `:9452` |
|
| web.listen-address | Address to listen on | `:9452` |
|
||||||
| web.metrics-path | Path under which to expose metrics | `/metrics` |
|
| web.metrics-path | Path under which to expose exporters own metrics | `/metrics` |
|
||||||
|
| web.device-path | Path under which the metrics of the devices are fetched | `/device` |
|
||||||
|
|
||||||
|
## Prometheus configuration
|
||||||
|
A enhancement has been made to have only one exporter which can scrape multiple devices. This is configured in
|
||||||
|
Prometheus as follows assuming we have 4 mystrom devices and the exporter is running locally on the smae machine as
|
||||||
|
the Prometheus.
|
||||||
|
```yaml
|
||||||
|
- job_name: mystrom
|
||||||
|
scrape_interval: 30s
|
||||||
|
metrics_path: /device
|
||||||
|
honor_labels: true
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
- '192.168.105.11'
|
||||||
|
- '192.168.105.12'
|
||||||
|
- '192.168.105.13'
|
||||||
|
- '192.168.105.14'
|
||||||
|
relabel_configs:
|
||||||
|
- source_labels: [__address__]
|
||||||
|
target_label: __param_target
|
||||||
|
- target_label: __address__
|
||||||
|
replacement: 127.0.0.1:9452
|
||||||
|
```
|
||||||
|
|
||||||
## Supported architectures
|
## Supported architectures
|
||||||
Using the make file, you can easily build for the following architectures, those can also be considered the tested ones:
|
Using the make file, you can easily build for the following architectures, those can also be considered the tested ones:
|
||||||
|
@ -40,6 +62,7 @@ Using the make file, you can easily build for the following architectures, those
|
||||||
| Linux | arm64 |
|
| Linux | arm64 |
|
||||||
| Linux | arm |
|
| Linux | arm |
|
||||||
| Mac | amd64 |
|
| Mac | amd64 |
|
||||||
|
| Mac | arm64 |
|
||||||
|
|
||||||
Since go is cross compatible with windows, and mac arm as well, you should be able to build the binary for those as well, but they aren't tested.
|
Since go is cross compatible with windows, and mac arm as well, you should be able to build the binary for those as well, but they aren't tested.
|
||||||
The docker image is only built & tested for amd64.
|
The docker image is only built & tested for amd64.
|
||||||
|
|
8
go.mod
8
go.mod
|
@ -2,4 +2,10 @@ module mystrom-exporter
|
||||||
|
|
||||||
go 1.15
|
go 1.15
|
||||||
|
|
||||||
require github.com/prometheus/client_golang v1.10.0
|
require (
|
||||||
|
github.com/gorilla/mux v1.7.3
|
||||||
|
github.com/prometheus/client_golang v1.10.0
|
||||||
|
github.com/prometheus/common v0.18.0
|
||||||
|
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 // indirect
|
||||||
|
golang.org/x/tools v0.1.12
|
||||||
|
)
|
||||||
|
|
36
go.sum
36
go.sum
|
@ -7,9 +7,11 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMx
|
||||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
|
||||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||||
|
@ -40,6 +42,7 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
|
@ -89,6 +92,7 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
|
@ -96,6 +100,7 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
||||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
|
@ -138,10 +143,13 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||||
|
@ -198,6 +206,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
@ -237,6 +246,7 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
|
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
|
@ -251,11 +261,13 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||||
|
@ -275,6 +287,7 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
@ -283,6 +296,8 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
@ -300,6 +315,8 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -309,6 +326,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
@ -328,11 +346,20 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY=
|
|
||||||
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM=
|
||||||
|
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
@ -347,9 +374,13 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
|
||||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
@ -376,9 +407,11 @@ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miE
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
@ -392,6 +425,7 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
288
main.go
288
main.go
|
@ -1,199 +1,155 @@
|
||||||
|
//go:generate stringer -type MystromReqStatus main.go
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
"github.com/prometheus/common/log"
|
||||||
|
|
||||||
|
"mystrom-exporter/pkg/mystrom"
|
||||||
|
"mystrom-exporter/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
type switchReport struct {
|
// -- MystromRequestStatusType represents the request to MyStrom device status
|
||||||
Power float64 `json:"power"`
|
type MystromReqStatus uint32
|
||||||
WattPerSec float64 `json:"Ws"`
|
|
||||||
Relay bool `json:relay`
|
|
||||||
Temperature float64 `json:"temperature`
|
|
||||||
}
|
|
||||||
|
|
||||||
const namespace = "mystrom"
|
const (
|
||||||
|
OK MystromReqStatus = iota
|
||||||
|
ERROR_SOCKET
|
||||||
|
ERROR_TIMEOUT
|
||||||
|
ERROR_PARSING_VALUE
|
||||||
|
)
|
||||||
|
|
||||||
|
const namespace = "mystrom_exporter"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
listenAddress = flag.String("web.listen-address", ":9452",
|
listenAddress = flag.String("web.listen-address", ":9452",
|
||||||
"Address to listen on")
|
"Address to listen on")
|
||||||
metricsPath = flag.String("web.metrics-path", "/metrics",
|
metricsPath = flag.String("web.metrics-path", "/metrics",
|
||||||
"Path under which to expose metrics")
|
"Path under which to expose exporters own metrics")
|
||||||
switchIP = flag.String("switch.ip-address", "",
|
devicePath = flag.String("web.device-path", "/device",
|
||||||
"IP address of the switch you try to monitor")
|
"Path under which the metrics of the devices are fetched")
|
||||||
|
showVersion = flag.Bool("version", false,
|
||||||
up = prometheus.NewDesc(
|
"Show version information.")
|
||||||
prometheus.BuildFQName(namespace, "", "up"),
|
|
||||||
"Was the last myStrom query successful.",
|
|
||||||
nil, nil,
|
|
||||||
)
|
|
||||||
myStromPower = prometheus.NewDesc(
|
|
||||||
prometheus.BuildFQName(namespace, "", "report_power"),
|
|
||||||
"The current power consumed by devices attached to the switch",
|
|
||||||
nil, nil,
|
|
||||||
)
|
|
||||||
|
|
||||||
myStromRelay = prometheus.NewDesc(
|
|
||||||
prometheus.BuildFQName(namespace, "", "report_relay"),
|
|
||||||
"The current state of the relay (wether or not the relay is currently turned on)",
|
|
||||||
nil, nil,
|
|
||||||
)
|
|
||||||
|
|
||||||
myStromTemperature = prometheus.NewDesc(
|
|
||||||
prometheus.BuildFQName(namespace, "", "report_temperatur"),
|
|
||||||
"The currently measured temperature by the switch. (Might initially be wrong, but will automatically correct itself over the span of a few hours)",
|
|
||||||
nil, nil,
|
|
||||||
)
|
|
||||||
|
|
||||||
myStromWattPerSec = prometheus.NewDesc(
|
|
||||||
prometheus.BuildFQName(namespace, "", "report_watt_per_sec"),
|
|
||||||
"The average of energy consumed per second from last call this request",
|
|
||||||
nil, nil,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
var (
|
||||||
type Exporter struct {
|
mystromDurationCounterVec *prometheus.CounterVec
|
||||||
myStromSwitchIp string
|
mystromRequestsCounterVec *prometheus.CounterVec
|
||||||
}
|
)
|
||||||
|
var landingPage = []byte(`<html>
|
||||||
func NewExporter(myStromSwitchIp string) *Exporter {
|
<head><title>myStrom switch report Exporter</title></head>
|
||||||
return &Exporter{
|
<body>
|
||||||
myStromSwitchIp: myStromSwitchIp,
|
<h1>myStrom Exporter</h1>
|
||||||
}
|
<p><a href='` + *metricsPath + `'>Metrics</a></p>
|
||||||
}
|
</body>
|
||||||
|
</html>`)
|
||||||
func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
|
|
||||||
ch <- up
|
|
||||||
ch <- myStromPower
|
|
||||||
ch <- myStromRelay
|
|
||||||
ch <- myStromTemperature
|
|
||||||
ch <- myStromWattPerSec
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
|
||||||
up, prometheus.GaugeValue, 1,
|
|
||||||
)
|
|
||||||
|
|
||||||
e.FetchSwitchMetrics(e.myStromSwitchIp, ch)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Exporter) FetchSwitchMetrics(switchIP string, ch chan<- prometheus.Metric) {
|
|
||||||
|
|
||||||
report, err := FetchReport(switchIP)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error occured, while fetching metrics: %s", err)
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
|
||||||
up, prometheus.GaugeValue, 0,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
|
||||||
myStromPower, prometheus.GaugeValue, report.Power,
|
|
||||||
)
|
|
||||||
|
|
||||||
if report.Relay {
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
|
||||||
myStromRelay, prometheus.GaugeValue, 1,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
|
||||||
myStromRelay, prometheus.GaugeValue, 0,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
|
||||||
myStromWattPerSec, prometheus.GaugeValue, report.WattPerSec,
|
|
||||||
)
|
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(
|
|
||||||
myStromTemperature, prometheus.GaugeValue, report.Temperature,
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func FetchReport(switchIP string) (*switchReport, error) {
|
|
||||||
log.Printf("Trying to connect to switch at: %s\n", switchIP)
|
|
||||||
url := "http://" + switchIP + "/report"
|
|
||||||
|
|
||||||
switchClient := http.Client{
|
|
||||||
Timeout: time.Second * 5, // 3 second timeout, might need to be increased
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("User-Agent", "myStrom-exporter")
|
|
||||||
|
|
||||||
res, getErr := switchClient.Do(req)
|
|
||||||
if getErr != nil {
|
|
||||||
log.Printf("Error while trying to connect to switch: %s\n", getErr)
|
|
||||||
return nil, getErr
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.Body != nil {
|
|
||||||
defer res.Body.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
body, readErr := ioutil.ReadAll(res.Body)
|
|
||||||
if readErr != nil {
|
|
||||||
log.Printf("Error while reading body: %s\n", readErr)
|
|
||||||
return nil, readErr
|
|
||||||
}
|
|
||||||
|
|
||||||
report := switchReport{}
|
|
||||||
err = json.Unmarshal(body, &report)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Error while unmarshaling report: %s\n", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &report, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if *switchIP == "" {
|
// -- show version information
|
||||||
flag.Usage()
|
if *showVersion {
|
||||||
fmt.Println("\nNo switch.ip-address provided")
|
v, err := version.Print("mystrom_exporter")
|
||||||
os.Exit(1)
|
if err != nil {
|
||||||
|
log.Fatalf("Failed to print version information: %#v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(os.Stdout, v)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
exporter := NewExporter(*switchIP)
|
// -- create a new registry for the exporter telemetry
|
||||||
prometheus.MustRegister(exporter)
|
telemetryRegistry := setupMetrics()
|
||||||
|
|
||||||
http.Handle(*metricsPath, promhttp.Handler())
|
router := mux.NewRouter()
|
||||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
router.Handle(*metricsPath, promhttp.HandlerFor(telemetryRegistry, promhttp.HandlerOpts{}))
|
||||||
w.Write([]byte(`<html>
|
router.HandleFunc(*devicePath, scrapeHandler)
|
||||||
<head><title>myStrom switch report Exporter</title></head>
|
router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
<body>
|
w.Write(landingPage)
|
||||||
<h1>myStrom Exporter</h1>
|
|
||||||
<p><a href='` + *metricsPath + `'>Metrics</a></p>
|
|
||||||
</body>
|
|
||||||
</html>`))
|
|
||||||
})
|
})
|
||||||
|
log.Infoln("Listening on address " + *listenAddress)
|
||||||
|
log.Fatal(http.ListenAndServe(*listenAddress, router))
|
||||||
|
}
|
||||||
|
|
||||||
_, err := FetchReport(*switchIP)
|
func scrapeHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
if err != nil {
|
target := r.URL.Query().Get("target")
|
||||||
log.Fatalf("Switch at address %s couldn't be reached. Ensure it is reachable before starting the exporter", *switchIP)
|
if target == "" {
|
||||||
|
http.Error(w, "'target' parameter must be specified", http.StatusBadRequest)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Starting listener on %s\n", *listenAddress)
|
log.Infof("got scrape request for target '%v'", target)
|
||||||
log.Fatal(http.ListenAndServe(*listenAddress, nil))
|
exporter := mystrom.NewExporter(target)
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
gatherer, err := exporter.Scrape()
|
||||||
|
duration := time.Since(start).Seconds()
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(fmt.Sprintf("%v", err), "unable to connect with target") {
|
||||||
|
mystromRequestsCounterVec.WithLabelValues(target, ERROR_SOCKET.String()).Inc()
|
||||||
|
} else if strings.Contains(fmt.Sprintf("%v", err), "i/o timeout") {
|
||||||
|
mystromRequestsCounterVec.WithLabelValues(target, ERROR_TIMEOUT.String()).Inc()
|
||||||
|
} else {
|
||||||
|
mystromRequestsCounterVec.WithLabelValues(target, ERROR_PARSING_VALUE.String()).Inc()
|
||||||
|
}
|
||||||
|
http.Error(
|
||||||
|
w,
|
||||||
|
fmt.Sprintf("failed to scrape target '%v': %v", target, err),
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
)
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mystromDurationCounterVec.WithLabelValues(target).Add(duration)
|
||||||
|
mystromRequestsCounterVec.WithLabelValues(target, OK.String()).Inc()
|
||||||
|
|
||||||
|
promhttp.HandlerFor(gatherer, promhttp.HandlerOpts{}).ServeHTTP(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- setupMetrics creates a new registry for the exporter telemetry
|
||||||
|
func setupMetrics() *prometheus.Registry {
|
||||||
|
registry := prometheus.NewRegistry()
|
||||||
|
registry.MustRegister(prometheus.NewGoCollector())
|
||||||
|
registry.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}))
|
||||||
|
|
||||||
|
mystromDurationCounterVec = prometheus.NewCounterVec(
|
||||||
|
prometheus.CounterOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Name: "request_duration_seconds_total",
|
||||||
|
Help: "Total duration of mystrom successful requests by target in seconds",
|
||||||
|
},
|
||||||
|
[]string{"target"})
|
||||||
|
registry.MustRegister(mystromDurationCounterVec)
|
||||||
|
|
||||||
|
mystromRequestsCounterVec = prometheus.NewCounterVec(
|
||||||
|
prometheus.CounterOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Name: "requests_total",
|
||||||
|
Help: "Number of mystrom request by status and target",
|
||||||
|
},
|
||||||
|
[]string{"target", "status"})
|
||||||
|
registry.MustRegister(mystromRequestsCounterVec)
|
||||||
|
|
||||||
|
// -- make the build information is available through a metric
|
||||||
|
buildInfo := prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Name: "build_info",
|
||||||
|
Help: "A metric with a constant '1' value labeled by build information.",
|
||||||
|
},
|
||||||
|
[]string{"version", "revision", "branch", "goversion", "builddate", "builduser"},
|
||||||
|
)
|
||||||
|
buildInfo.WithLabelValues(version.Version, version.Revision, version.Branch, version.GoVersion, version.BuildDate, version.BuildUser).Set(1)
|
||||||
|
registry.MustRegister(buildInfo)
|
||||||
|
|
||||||
|
return registry
|
||||||
}
|
}
|
||||||
|
|
214
pkg/mystrom/mystrom.go
Normal file
214
pkg/mystrom/mystrom.go
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
package mystrom
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/prometheus/common/log"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
|
)
|
||||||
|
|
||||||
|
const namespace = "mystrom"
|
||||||
|
|
||||||
|
// 5 second timeout, might need to be increased
|
||||||
|
const reqTimeout = time.Second * 5
|
||||||
|
|
||||||
|
type switchReport struct {
|
||||||
|
Power float64 `json:"power"`
|
||||||
|
WattPerSec float64 `json:"Ws"`
|
||||||
|
Relay bool `json:"relay"`
|
||||||
|
Temperature float64 `json:"temperature"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type switchInfo struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
SwType float64 `json:"type"`
|
||||||
|
SSID string `json:"ssid"`
|
||||||
|
Static bool `json:"static"`
|
||||||
|
Connected bool `json:"connected"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exporter --
|
||||||
|
type Exporter struct {
|
||||||
|
myStromSwitchIp string
|
||||||
|
switchType float64
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewExporter --
|
||||||
|
func NewExporter(switchIP string) *Exporter {
|
||||||
|
return &Exporter{
|
||||||
|
myStromSwitchIp: switchIP,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scrape --
|
||||||
|
func (e *Exporter) Scrape() (prometheus.Gatherer, error) {
|
||||||
|
reg := prometheus.NewRegistry()
|
||||||
|
|
||||||
|
// --
|
||||||
|
bodyInfo, err := e.fetchData("/api/v1/info")
|
||||||
|
if err != nil {
|
||||||
|
}
|
||||||
|
|
||||||
|
info := switchInfo{}
|
||||||
|
err = json.Unmarshal(bodyInfo, &info)
|
||||||
|
if err != nil {
|
||||||
|
// fmt.Println(err)
|
||||||
|
// ch <- prometheus.MustNewConstMetric(
|
||||||
|
// up, prometheus.GaugeValue, 0,
|
||||||
|
// )
|
||||||
|
return reg, fmt.Errorf("unable to decode switchReport: %v", err.Error())
|
||||||
|
}
|
||||||
|
log.Debugf("info: %#v", info)
|
||||||
|
e.switchType = info.SwType
|
||||||
|
|
||||||
|
if err := registerInfoMetrics(reg, info, e.myStromSwitchIp); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to register metrics : %v", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// --
|
||||||
|
bodyData, err := e.fetchData("/report")
|
||||||
|
if err != nil {
|
||||||
|
}
|
||||||
|
|
||||||
|
report := switchReport{}
|
||||||
|
err = json.Unmarshal(bodyData, &report)
|
||||||
|
if err != nil {
|
||||||
|
// fmt.Println(err)
|
||||||
|
// ch <- prometheus.MustNewConstMetric(
|
||||||
|
// up, prometheus.GaugeValue, 0,
|
||||||
|
// )
|
||||||
|
return reg, fmt.Errorf("unable to decode switchReport: %v", err.Error())
|
||||||
|
}
|
||||||
|
log.Debugf("report: %#v", report)
|
||||||
|
|
||||||
|
if err := registerMetrics(reg, report, e.myStromSwitchIp, e.switchType); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to register metrics : %v", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return reg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetchData -- get the data from the switch under the given path
|
||||||
|
func (e *Exporter) fetchData(urlpath string) ([]byte, error) {
|
||||||
|
url := "http://" + e.myStromSwitchIp + urlpath
|
||||||
|
|
||||||
|
switchClient := http.Client{
|
||||||
|
Timeout: reqTimeout,
|
||||||
|
Transport: &http.Transport{
|
||||||
|
DisableCompression: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||||
|
if err != nil {
|
||||||
|
// ch <- prometheus.MustNewConstMetric(
|
||||||
|
// up, prometheus.GaugeValue, 0,
|
||||||
|
// )
|
||||||
|
}
|
||||||
|
req.Header.Set("User-Agent", "myStrom-exporter")
|
||||||
|
|
||||||
|
res, getErr := switchClient.Do(req)
|
||||||
|
if getErr != nil {
|
||||||
|
// ch <- prometheus.MustNewConstMetric(
|
||||||
|
// up, prometheus.GaugeValue, 0,
|
||||||
|
// )
|
||||||
|
}
|
||||||
|
if res.Body != nil {
|
||||||
|
defer res.Body.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
body, readErr := ioutil.ReadAll(res.Body)
|
||||||
|
if readErr != nil {
|
||||||
|
// ch <- prometheus.MustNewConstMetric(
|
||||||
|
// up, prometheus.GaugeValue, 0,
|
||||||
|
// )
|
||||||
|
return []byte{}, fmt.Errorf("unable to read body: %v", readErr.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return body, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// registerMetrics --
|
||||||
|
func registerMetrics(reg prometheus.Registerer, data switchReport, target string, st float64) error {
|
||||||
|
|
||||||
|
// --
|
||||||
|
collectorRelay := prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Name: "relay",
|
||||||
|
Help: "The current state of the relay (wether or not the relay is currently turned on)",
|
||||||
|
},
|
||||||
|
[]string{"instance"})
|
||||||
|
|
||||||
|
if err := reg.Register(collectorRelay); err != nil {
|
||||||
|
return fmt.Errorf("failed to register metric %v: %v", "relay", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.Relay {
|
||||||
|
collectorRelay.WithLabelValues(target).Set(1)
|
||||||
|
} else {
|
||||||
|
collectorRelay.WithLabelValues(target).Set(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if st != 114 {
|
||||||
|
// --
|
||||||
|
collectorPower := prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Name: "power",
|
||||||
|
Help: "The current power consumed by devices attached to the switch",
|
||||||
|
},
|
||||||
|
[]string{"instance"})
|
||||||
|
|
||||||
|
if err := reg.Register(collectorPower); err != nil {
|
||||||
|
return fmt.Errorf("failed to register metric %v: %v", "power", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
collectorPower.WithLabelValues(target).Set(data.Power)
|
||||||
|
|
||||||
|
// --
|
||||||
|
collectorTemperature := prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Name: "temperature",
|
||||||
|
Help: "The currently measured temperature by the switch. (Might initially be wrong, but will automatically correct itself over the span of a few hours)",
|
||||||
|
},
|
||||||
|
[]string{"instance"})
|
||||||
|
|
||||||
|
if err := reg.Register(collectorTemperature); err != nil {
|
||||||
|
return fmt.Errorf("failed to register metric %v: %v", "temperature", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
collectorTemperature.WithLabelValues(target).Set(data.Temperature)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// registerMetrics --
|
||||||
|
func registerInfoMetrics(reg prometheus.Registerer, data switchInfo, target string) error {
|
||||||
|
|
||||||
|
// --
|
||||||
|
collectorInfo := prometheus.NewGaugeVec(
|
||||||
|
prometheus.GaugeOpts{
|
||||||
|
Namespace: namespace,
|
||||||
|
Name: "info",
|
||||||
|
Help: "general information about the device",
|
||||||
|
},
|
||||||
|
[]string{"instance", "version", "mac", "type", "ssid"})
|
||||||
|
|
||||||
|
if err := reg.Register(collectorInfo); err != nil {
|
||||||
|
return fmt.Errorf("failed to register metric %v: %v", "info", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
collectorInfo.WithLabelValues(target, data.Version, data.Mac, fmt.Sprintf("%v", data.SwType), data.SSID).Set(1)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
60
pkg/version/version.go
Normal file
60
pkg/version/version.go
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
package version
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Build information. Populated at build-time.
|
||||||
|
var (
|
||||||
|
Version string
|
||||||
|
Revision string
|
||||||
|
Branch string
|
||||||
|
BuildUser string
|
||||||
|
BuildDate string
|
||||||
|
GoVersion = runtime.Version()
|
||||||
|
)
|
||||||
|
|
||||||
|
// versionInfoTmpl contains the template used by Print.
|
||||||
|
var versionInfoTmpl = `
|
||||||
|
{{.program}}, version {{.version}} (branch: {{.branch}}, revision: {{.revision}})
|
||||||
|
build user: {{.buildUser}}
|
||||||
|
build date: {{.buildDate}}
|
||||||
|
go version: {{.goVersion}}
|
||||||
|
`
|
||||||
|
|
||||||
|
// Print returns version information.
|
||||||
|
func Print(program string) (string, error) {
|
||||||
|
m := map[string]string{
|
||||||
|
"program": program,
|
||||||
|
"version": Version,
|
||||||
|
"revision": Revision,
|
||||||
|
"branch": Branch,
|
||||||
|
"buildUser": BuildUser,
|
||||||
|
"buildDate": BuildDate,
|
||||||
|
"goVersion": GoVersion,
|
||||||
|
}
|
||||||
|
t, err := template.New("version").Parse(versionInfoTmpl)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := t.ExecuteTemplate(&buf, "version", m); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(buf.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Info returns version, branch and revision information.
|
||||||
|
func Info() string {
|
||||||
|
return fmt.Sprintf("(version=%s, branch=%s, revision=%s)", Version, Branch, Revision)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildContext returns goVersion, buildUser and buildDate information.
|
||||||
|
func BuildContext() string {
|
||||||
|
return fmt.Sprintf("(go=%s, user=%s, date=%s)", GoVersion, BuildUser, BuildDate)
|
||||||
|
}
|
7
tools.go
Normal file
7
tools.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
// +build tools
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "golang.org/x/tools/cmd/stringer"
|
||||||
|
)
|
Loading…
Reference in a new issue