Skip to content

Commit 053d1f1

Browse files
authored
Merge pull request #4 from eze-kiel/enable-json-logging
Enable json logging
2 parents f9e3278 + 3fe3d28 commit 053d1f1

File tree

5 files changed

+83
-26
lines changed

5 files changed

+83
-26
lines changed

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@ and then execute the binary at `./out/bin/uptimerobot-exporter`
2323
```
2424
Usage of uptimerobot-exporter:
2525
-api-key string
26-
Uptime Robot API key
26+
Uptime Robot API key
2727
-inteval int
28-
Uptime robot API scrape interval, in seconds (default 30)
28+
Uptime robot API scrape interval, in seconds (default 30)
2929
-ip string
30-
IP on which the Prometheus server will be binded (default "0.0.0.0")
30+
IP on which the Prometheus server will be binded (default "0.0.0.0")
31+
-log-level string
32+
Log level (default "info")
3133
-p string
32-
Port that will be used by the Prometheus server (default "9705")
34+
Port that will be used by the Prometheus server (default "9705")
3335
```
3436

3537
Basically, you just have to pass your Uptime Robot API key. Of course, to avoid typing it in the terminal, you can provide it via an environment variable called `UPTIMEROBOT_API_KEY`.

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ go 1.16
44

55
require (
66
github.com/prometheus/client_golang v1.11.0
7+
github.com/rs/zerolog v1.23.0
78
github.com/sirupsen/logrus v1.8.1
89
)

go.sum

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
1010
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
1111
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
1212
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
13+
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
1314
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1415
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
1516
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -20,6 +21,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
2021
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
2122
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
2223
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
24+
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
2325
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
2426
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
2527
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -82,6 +84,9 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
8284
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
8385
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
8486
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
87+
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
88+
github.com/rs/zerolog v1.23.0 h1:UskrK+saS9P9Y789yNNulYKdARjPZuS35B8gJF2x60g=
89+
github.com/rs/zerolog v1.23.0/go.mod h1:6c7hFfxPOy7TacJc4Fcdi24/J0NKYGzjG8FWRI916Qo=
8590
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
8691
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
8792
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
@@ -93,19 +98,26 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
9398
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
9499
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
95100
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
101+
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
96102
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
97103
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
104+
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
98105
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
106+
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
99107
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
100108
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
101109
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
102110
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
103111
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
112+
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
104113
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
114+
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
105115
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
106116
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
107117
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
118+
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
108119
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
120+
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
109121
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
110122
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
111123
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -117,14 +129,22 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w
117129
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
118130
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
119131
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
132+
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
133+
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
120134
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
121135
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q=
122136
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
123137
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
124138
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
139+
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
125140
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
126-
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
141+
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
142+
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
143+
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
144+
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
127145
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
146+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
147+
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
128148
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
129149
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
130150
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=

logger/logger.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package logger
2+
3+
import (
4+
"os"
5+
6+
"github.com/rs/zerolog"
7+
"github.com/rs/zerolog/log"
8+
)
9+
10+
// New creates a new zerolog logger
11+
func New(level string) zerolog.Logger {
12+
lvl, err := zerolog.ParseLevel(level)
13+
if err != nil {
14+
log.Error().Msgf("cannot parse level %s, using 'info'", level)
15+
lvl = zerolog.InfoLevel
16+
}
17+
zerolog.SetGlobalLevel(lvl)
18+
logger := zerolog.New(os.Stderr).With().Timestamp().Logger()
19+
return logger
20+
}

main.go

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ import (
1313

1414
"flag"
1515

16+
"github.com/eze-kiel/uptimerobot-exporter/logger"
1617
"github.com/prometheus/client_golang/prometheus"
1718
"github.com/prometheus/client_golang/prometheus/promauto"
1819
"github.com/prometheus/client_golang/prometheus/promhttp"
20+
"github.com/rs/zerolog"
1921
"github.com/sirupsen/logrus"
2022
)
2123

@@ -24,6 +26,8 @@ type app struct {
2426
address string
2527
port string
2628
scrapeInterval int
29+
logLevel string
30+
logger zerolog.Logger
2731
}
2832

2933
type AccountDetails struct {
@@ -111,21 +115,23 @@ func main() {
111115
flag.StringVar(&a.address, "ip", "0.0.0.0", "IP on which the Prometheus server will be binded")
112116
flag.StringVar(&a.port, "p", "9705", "Port that will be used by the Prometheus server")
113117
flag.IntVar(&a.scrapeInterval, "inteval", 30, "Uptime robot API scrape interval, in seconds")
118+
flag.StringVar(&a.logLevel, "log-level", "info", "Log level")
114119
flag.Parse()
115120

121+
a.logger = logger.New(a.logLevel)
116122
if a.apiKey == "" {
117123
a.apiKey = os.Getenv("UPTIMEROBOT_API_KEY")
118124
if a.apiKey == "" {
119-
logrus.Fatal(errors.New("no API key provided in flags nor in env variables"))
125+
a.logger.Fatal().Err(errors.New("missing Uptime Robot API key")).Msg("use -api-key or UPTIMEROBOT_API_KEY env variable")
120126
}
121127
}
122-
logrus.Info("API key found")
128+
a.logger.Info().Msg("API key found")
129+
a.logger.Info().Msg("starting fetch routines")
123130

124-
logrus.Info("starting fetch routines")
125-
go fetchAccountDetails(a.apiKey, a.scrapeInterval)
126-
go fetchMonitors(a.apiKey, a.scrapeInterval)
131+
go a.fetchAccountDetails()
132+
go a.fetchMonitors()
127133

128-
logrus.Info("starting metrics server")
134+
a.logger.Info().Msg("starting metrics server")
129135
http.Handle("/metrics", promhttp.Handler())
130136
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
131137
w.WriteHeader(http.StatusOK)
@@ -134,32 +140,36 @@ func main() {
134140
http.ListenAndServe(a.address+":"+a.port, nil)
135141
}
136142

137-
func fetchAccountDetails(apiKey string, interval int) {
138-
ticker := time.NewTicker(time.Duration(interval) * time.Second)
143+
func (a app) fetchAccountDetails() {
144+
ticker := time.NewTicker(time.Duration(a.scrapeInterval) * time.Second)
139145
for {
140146
<-ticker.C
141-
logrus.Info("fetching account details")
147+
a.logger.Info().Msg("fetching account details")
142148
data := url.Values{
143-
"api_key": {apiKey},
149+
"api_key": {a.apiKey},
144150
"format": {"json"},
145151
}
146152

147153
resp, err := http.PostForm("https://api.uptimerobot.com/v2/getAccountDetails", data)
148154
if err != nil {
149-
logrus.Error(err)
155+
a.logger.Error().Err(err).Msg("failed to fetch account details")
156+
continue
150157
}
151158

152159
body, err := ioutil.ReadAll(resp.Body)
160+
resp.Body.Close()
153161
if err != nil {
154-
logrus.Fatalf("cannot parse response body: %s", err)
162+
a.logger.Error().Err(err).Msg("cannot parse response body")
163+
continue
155164
}
156-
resp.Body.Close()
157165

158166
var account AccountDetails
159167
if err := json.Unmarshal(body, &account); err != nil {
160-
logrus.Fatalf("cannot parse JSON: %s", err)
168+
a.logger.Error().Err(err).Msg("cannot parse JSON")
169+
continue
161170
}
162171

172+
a.logger.Debug().Msg("updating account details metrics")
163173
upMonitors.Set(float64(account.Account.UpMonitors))
164174
downMonitors.Set(float64(account.Account.DownMonitors))
165175
pausedMonitors.Set(float64(account.Account.PausedMonitors))
@@ -175,35 +185,39 @@ func fetchAccountDetails(apiKey string, interval int) {
175185
}
176186
}
177187

178-
func fetchMonitors(apiKey string, interval int) {
179-
ticker := time.NewTicker(time.Duration(interval) * time.Second)
188+
func (a app) fetchMonitors() {
189+
ticker := time.NewTicker(time.Duration(a.scrapeInterval) * time.Second)
180190
for {
181191
<-ticker.C
182192
logrus.Info("fetching monitors")
183193
data := url.Values{
184-
"api_key": {apiKey},
194+
"api_key": {a.apiKey},
185195
"format": {"json"},
186196
"response_times": {"1"},
187197
"response_times_limit": {"1"},
188198
}
189199

190200
resp, err := http.PostForm("https://api.uptimerobot.com/v2/getMonitors", data)
191201
if err != nil {
192-
logrus.Error(err)
202+
a.logger.Error().Err(err).Msg("failed to fetch monitors")
203+
continue
193204
}
194205

195206
body, err := ioutil.ReadAll(resp.Body)
207+
resp.Body.Close()
196208
if err != nil {
197-
logrus.Fatalf("cannot parse response body: %s", err)
209+
a.logger.Error().Err(err).Msg("cannot parse response body")
210+
continue
198211
}
199-
resp.Body.Close()
200212

201213
var monitors MonitorsData
202214
if err := json.Unmarshal(body, &monitors); err != nil {
203-
logrus.Fatalf("cannot parse JSON: %s", err)
215+
a.logger.Error().Err(err).Msg("cannot parse JSON")
216+
continue
204217
}
205218

206219
for _, m := range monitors.Monitors {
220+
a.logger.Debug().Msg("updating monitors metrics")
207221
monitorsStatus.WithLabelValues(m.URL, m.FriendlyName, strconv.Itoa(m.Interval)).Set(float64(m.Status))
208222
responseTime.WithLabelValues(m.URL, m.FriendlyName, strconv.Itoa(m.Type)).Set(float64(m.ResponseTimes[0].Value))
209223
}

0 commit comments

Comments
 (0)