forked from Technofy/cloudwatch_exporter
/
main.go
127 lines (99 loc) · 3.24 KB
/
main.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
package main
import (
"flag"
"fmt"
"log"
"net/http"
"os"
"sync"
"github.com/NixM0nk3y/cloudwatch_exporter/config"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
var (
listenAddress = flag.String("web.listen-address", ":9042", "Address on which to expose metrics and web interface.")
metricsPath = flag.String("web.telemetry-path", "/metrics", "Path under which to expose exporter's metrics.")
scrapePath = flag.String("web.telemetry-scrape-path", "/scrape", "Path under which to expose CloudWatch metrics.")
configFile = flag.String("config.file", "config.yml", "Path to configuration file.")
globalRegistry *prometheus.Registry
settings *config.Settings
totalRequests prometheus.Counter
configMutex = &sync.Mutex{}
)
func loadConfigFile() error {
var err error
var tmpSettings *config.Settings
configMutex.Lock()
// Initial loading of the configuration file
tmpSettings, err = config.Load(*configFile)
if err != nil {
return err
}
generateTemplates(tmpSettings)
settings = tmpSettings
configMutex.Unlock()
return nil
}
// handleReload handles a full reload of the configuration file and regenerates the collector templates.
func handleReload(w http.ResponseWriter, req *http.Request) {
err := loadConfigFile()
if err != nil {
str := fmt.Sprintf("Can't read configuration file: %s", err.Error())
fmt.Fprintln(w, str)
fmt.Println(str)
}
fmt.Fprintln(w, "Reload complete")
}
// handleTarget handles scrape requests which make use of CloudWatch service
func handleTarget(w http.ResponseWriter, req *http.Request) {
urlQuery := req.URL.Query()
target := urlQuery.Get("target")
task := urlQuery.Get("task")
region := urlQuery.Get("region")
account := urlQuery.Get("account")
// Check if we have all the required parameters in the URL
if task == "" {
fmt.Fprintln(w, "Error: Missing task parameter")
return
}
configMutex.Lock()
registry := prometheus.NewRegistry()
collector, err := NewCwCollector(target, task, region, account)
if err != nil {
// Can't create the collector, display error
fmt.Fprintf(w, "Error: %s\n", err.Error())
configMutex.Unlock()
return
}
registry.MustRegister(collector)
handler := promhttp.HandlerFor(registry, promhttp.HandlerOpts{
DisableCompression: false,
})
// Serve the answer through the Collect method of the Collector
handler.ServeHTTP(w, req)
configMutex.Unlock()
}
func main() {
flag.Parse()
globalRegistry = prometheus.NewRegistry()
totalRequests = prometheus.NewCounter(prometheus.CounterOpts{
Name: "cloudwatch_requests_total",
Help: "API requests made to CloudWatch",
})
globalRegistry.MustRegister(totalRequests)
prometheus.DefaultGatherer = globalRegistry
err := loadConfigFile()
if err != nil {
fmt.Printf("Can't read configuration file: %s\n", err.Error())
os.Exit(-1)
}
fmt.Println("CloudWatch exporter started...")
// Expose the exporter's own metrics on /metrics
http.Handle(*metricsPath, promhttp.Handler())
// Expose CloudWatch through this endpoint
http.HandleFunc(*scrapePath, handleTarget)
// Allows manual reload of the configuration
http.HandleFunc("/reload", handleReload)
// Start serving for clients
log.Fatal(http.ListenAndServe(*listenAddress, nil))
}