-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
127 lines (106 loc) · 3.7 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"
"main/exporter"
"net/http"
"os"
"strings"
"time"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/collectors/version"
"github.com/prometheus/client_golang/prometheus/promhttp"
log "github.com/sirupsen/logrus"
)
var (
internalVersion, serviceEndpoint string
// internal settings
listenAddress = flag.String("listen-address", ":19100", "Address to listen on to be scraped.")
metricsPath = flag.String("telemetry-path", "/metrics", "Base path under which to expose metrics.")
debugLevel = flag.Bool("debug", false, "Enable debug mode.")
// remote service related flags
serviceName = flag.String("service-name", "", "Remote service name to reference.")
serviceProtocol = flag.String("service-protocol", "http", "HTTP Schema of the remote service (http or https).")
serviceUri = flag.String("service-uri", "", "Endpoint address of the remote service.")
servicePort = flag.String("service-port", "80", "HTTP Port of the remote service.")
serviceMetricsPath = flag.String("service-metrics-path", "metrics", "Service path to scrape metrics from.")
serviceVersionScrape = flag.Bool("service-version-scrape", false, "Enable whether the service will be internally scraped for fetching remote build version or not.")
)
func main() {
flag.Parse()
name := *serviceName
if strings.Trim(name, " ") == "" {
log.Fatalln("Service name not set! Specify by -service-name SERVICE")
}
// build service endpoint
// if not set try to fetch from env
serviceEndpoint = fmt.Sprintf("%s://%s:%s", *serviceProtocol, *serviceUri, *servicePort)
if *serviceUri == "" {
host, exists := os.LookupEnv("SERVICE_ENDPOINT")
if exists && host != "" {
serviceEndpoint = fmt.Sprintf("%s://%s:%s", *serviceProtocol, host, *servicePort)
} else {
log.Fatalln("Service URI is not set! Specify either a '-service-uri' flag OR an environment variable 'SERVICE_ENDPOINT'")
}
}
// enable debug mode if required
if *debugLevel {
log.SetLevel(log.DebugLevel)
}
log.Info("Check if target is reachable...")
if *serviceVersionScrape {
internalVersion = checkEndpoint(serviceEndpoint)
} else {
checkEndpoint(serviceEndpoint)
}
log.Info("Target endpoint is reachable")
registry := prometheus.NewRegistry()
// register current Exporter version metrics
versionMetric := version.NewCollector(name)
registry.MustRegister(versionMetric)
// register remote service metrics
exporter := exporter.NewCollector(name, fmt.Sprintf("%s/%s", serviceEndpoint, *serviceMetricsPath), internalVersion)
registry.MustRegister(exporter)
http.Handle(*metricsPath, promhttp.HandlerFor(
registry,
promhttp.HandlerOpts{
DisableCompression: false,
ErrorHandling: promhttp.ContinueOnError,
}),
)
log.Println("Starting server....")
srv := &http.Server{
Addr: *listenAddress,
ReadHeaderTimeout: 30 * time.Second,
}
if err := srv.ListenAndServe(); err != nil {
log.WithFields(log.Fields{
"err": err,
}).Errorf("http server quit with error: %v", err)
}
}
// check if service endpoint is reachable
// increases duration by 5secs for the next ticket if unavailable
func checkEndpoint(endpoint string) string {
var duration = 5
stopCh := make(chan bool)
t := time.NewTicker(time.Duration(duration) * time.Second)
stats := &exporter.HttpStats{}
discovery:
for {
select {
case <-t.C:
if stats = exporter.FetchStats(endpoint); stats != nil {
break discovery
}
log.Errorf("service endpoint not available, retrying in %ds", duration)
t = time.NewTicker(time.Duration(duration) * time.Second)
duration = duration + 5
continue
case <-stopCh:
os.Exit(0)
}
}
t.Stop()
return stats.Version
}