This repository was archived by the owner on Feb 20, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
138 lines (121 loc) · 3.91 KB
/
Copy pathmain.go
File metadata and controls
138 lines (121 loc) · 3.91 KB
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
138
package main
import (
"context"
"flag"
"fmt"
"net/http"
"net/http/httputil"
"net/url"
"os"
"os/signal"
"sync"
"syscall"
"time"
"rrinterceptor/cacher"
"github.com/hekmon/hllogger"
systemd "github.com/iguanesolutions/go-systemd"
)
var (
cache *cacher.Controller
influxURL *url.URL
httpServer *http.Server
httpProxy *httputil.ReverseProxy
log *hllogger.HlLogger
mainCtx context.Context
mainCancel context.CancelFunc
mainLock sync.Mutex
)
func main() {
// cli flags
var (
bindAddr = flag.String("bind-addr", ":9404", "The HTTP server bind address.")
influxTarget = flag.String("influx-url", "http://127.0.0.1:8086", "The influxdb target url.")
checkFrequency = flag.Int("check-frequency", 60, "The cache check frequency in minutes.")
expirationLimit = flag.Int("expiration-limit", 1440, "The cache expiration limit.")
logLevel = flag.Int("log-level", 1, "Set the loglevel: Fatal(0) Error(1) Warning(2) Info(3) Debug(4).")
)
flag.Parse()
var err error
if influxURL, err = url.Parse(*influxTarget); err != nil {
log.Fatalf(1, "[Main] Can't parse influxdb url: %v", err)
}
// Init logger
var logLevelTyped hllogger.LogLevel
if hllogger.LogLevel(*logLevel) > hllogger.Debug || hllogger.LogLevel(*logLevel) < hllogger.Fatal {
fmt.Fprint(os.Stderr, "WARNING: log level is invalid, defaulting to Info(1)\n")
logLevelTyped = hllogger.Info
} else {
logLevelTyped = hllogger.LogLevel(*logLevel)
}
log = hllogger.New(os.Stdout, &hllogger.Config{
LogLevel: logLevelTyped,
SystemdJournaldCompat: systemd.IsNotifyEnabled(),
})
// Now that we have a logger, notify about sysd
if systemd.IsNotifyEnabled() {
log.Info("[Main] Systemd notifications supported and enabled")
} else {
log.Warning("[Main] Systemd notifications not supported")
}
// Create the app main context & lock
mainCtx, mainCancel = context.WithCancel(context.Background())
defer mainCancel() // make linter happy
mainLock.Lock()
// Create the cache & start the cleaner
if cache, err = cacher.New(mainCtx, cacher.Config{
CheckFrequency: time.Duration(*checkFrequency) * time.Minute,
ExpirationLimit: time.Duration(*expirationLimit) * time.Minute,
Logger: log,
}); err != nil {
log.Fatal(1, "[Main] Can't spawn cacher: is there a logger ?")
}
// Init the stats metrics
if err = initMetrics(); err != nil {
log.Fatalf(1, "[Main] Can't init stats metrics: %v", err)
}
// Init signal handler
term := make(chan os.Signal, 1)
signal.Notify(term, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-term
exit()
}()
// Launch the web server
httpServer = &http.Server{
Addr: *bindAddr,
}
http.HandleFunc("/smartread", wrapHandlerWithLogging(readHandler))
http.Handle("/metrics", promHandler())
log.Infof("[Main] Starting HTTP server on %s", *bindAddr)
// Ready, start the server
if err = systemd.NotifyReady(); err != nil {
log.Errorf("[Main] Can't send systemd ready notification: %v", err)
}
if err = httpServer.ListenAndServe(); err != nil && err.Error() != "http: Server closed" {
log.Errorf("[Main] HTTP Server: %v", err)
}
// Wait till the end...
mainLock.Lock()
log.Debug("[Main] Exiting main goroutine")
}
func exit() {
log.Info("[Main] Exit triggered: gracefully stopping controllers")
var err error
if err = systemd.NotifyStopping(); err != nil {
log.Errorf("[Main] Exit: can't send stopping notification to systemd: %v", err)
}
// First gracefully stop the http server
timeout := 30 * time.Second
log.Debugf("[Main] Stopping HTTP server gracefully (%v timeout)", timeout)
stopContext, stopContextCancel := context.WithTimeout(mainCtx, timeout)
defer stopContextCancel()
if err = httpServer.Shutdown(stopContext); err != nil {
log.Errorf("[Main] HTTP Server shutdown: %v", err)
}
// Then properly the other workers
mainCancel()
log.Debug("[Main] Stopping the cacher")
cache.WaitFullStop()
// Release the main gorouting to exit
mainLock.Unlock()
}