-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathexporter.go
137 lines (122 loc) · 3.66 KB
/
exporter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package main
import (
"crypto/tls"
"encoding/json"
"fmt"
"github.com/echocat/site24x7_exporter/utils"
"github.com/prometheus/client_golang/prometheus"
"log"
"net"
"net/http"
"net/url"
"sync"
"time"
"io"
"io/ioutil"
)
var (
currentStatusApiUri, _ = url.Parse("https://www.site24x7.com/api/current_status")
)
type Site24x7Exporter struct {
uri string
accessToken string
mutex sync.RWMutex
up prometheus.Gauge
status prometheus.Gauge
client *http.Client
}
func NewSite24x7Exporter(accessToken string, timeout time.Duration) *Site24x7Exporter {
return &Site24x7Exporter{
accessToken: accessToken,
up: prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: namespace,
Name: "up",
Help: "Was the Site24x7 instance query successful?",
}),
status: prometheus.NewGauge(prometheus.GaugeOpts{
Namespace: namespace,
Name: "status",
Help: "What is the status of the target monitor?",
}),
client: &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: utils.LoadInternalCaBundle(),
},
Dial: func(netw, addr string) (net.Conn, error) {
c, err := net.DialTimeout(netw, addr, timeout)
if err != nil {
return nil, err
}
if err := c.SetDeadline(time.Now().Add(timeout)); err != nil {
return nil, err
}
return c, nil
},
},
},
}
}
func (instance *Site24x7Exporter) createRequestFor(url *url.URL) *http.Request {
return &http.Request{
Method: "GET",
URL: url,
Proto: "HTTP/1.1",
ProtoMajor: 1,
ProtoMinor: 1,
Header: http.Header{
"Authorization": []string{fmt.Sprintf("Zoho-authtoken %s", instance.accessToken)},
},
Host: url.Host,
}
}
func (instance *Site24x7Exporter) executeAndEvaluate(request *http.Request, target interface{}) error {
response, err := instance.client.Do(request)
if err != nil {
return fmt.Errorf("Could not execute request %v. Got: %v", request.URL, err)
}
if response.StatusCode < 200 || response.StatusCode >= 400 {
return fmt.Errorf("Could not execute request %v. Got: %v - %v", request.URL, response.StatusCode, response.Status)
}
defer func() {
io.Copy(ioutil.Discard, response.Body)
response.Body.Close()
}()
decoder := json.NewDecoder(response.Body)
err = decoder.Decode(target)
if err != nil {
return fmt.Errorf("Could not execute request %v. Could not decode response. Got: %v", request.URL, err)
}
return nil
}
func (instance *Site24x7Exporter) retrieveCurrentStatus() (*CurrentStatus, error) {
request := instance.createRequestFor(currentStatusApiUri)
restObject := CurrentStatus{}
err := instance.executeAndEvaluate(request, &restObject)
if err != nil {
return nil, err
}
if restObject.ErrorCode != 0 {
return nil, fmt.Errorf("Could not execute request %v. Could not decode response. Got: #%d - %s", request.URL, restObject.ErrorCode, restObject.Message)
}
return &restObject, nil
}
// Describe describes all the metrics ever exported by the
// exporter. It implements prometheus.Collector.
func (instance *Site24x7Exporter) Describe(ch chan<- *prometheus.Desc) {
ch <- instance.up.Desc()
ch <- instance.status.Desc()
}
// Collect fetches the stats from configured site24x7 and
// delivers them as Prometheus metrics. It implements prometheus.Collector.
func (instance *Site24x7Exporter) Collect(ch chan<- prometheus.Metric) {
instance.mutex.Lock() // To protect metrics from concurrent collects.
defer instance.mutex.Unlock()
currentStatus, err := instance.retrieveCurrentStatus()
if err != nil {
log.Printf("Failed to retreive current status. Cause: %v", err)
return
}
NewStatusFor(currentStatus).Collect(ch)
NewAttributesFor(currentStatus).Collect(ch)
}