generated from kyma-project/template-repository
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathmain.go
147 lines (115 loc) · 3.58 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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package main
import (
"context"
"errors"
"flag"
"fmt"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/kyma-project/directory-size-exporter/internal/exporter"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
const (
defaultLogFormat = "json"
defaultLogLevel = "info"
defaultMetricCollectionInterval = 30 * time.Second
readHeaderTimeout = 1 * time.Second
shutdownTimeout = 10 * time.Second
)
var (
logger = createLogger(defaultLogFormat, defaultLogLevel)
storagePath string
metricName string
logFormat string
logLevel string
port string
interval time.Duration
)
func main() {
if err := run(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
}
func run() error {
flag.StringVar(&logFormat, "log-format", defaultLogFormat, "Log format (json or text)")
flag.StringVar(&logLevel, "log-level", defaultLogLevel, "Log level (debug, info, warn, error)")
flag.StringVar(&storagePath, "storage-path", "", "Path to the observed data folder")
flag.StringVar(&metricName, "metric-name", "", "Metric name used for exporting the folder size")
flag.StringVar(&port, "port", "2021", "Port for exposing the metrics")
flag.DurationVar(&interval, "interval", defaultMetricCollectionInterval, "Interval to calculate the metric ")
flag.Parse()
if err := validateFlags(); err != nil {
return fmt.Errorf("invalid flags: %w", err)
}
logger = createLogger(logFormat, logLevel)
exp := exporter.NewExporter(storagePath, metricName, logger)
exp.RecordMetrics(interval)
logger.Info("Started recording metrics")
http.Handle("/metrics", promhttp.Handler())
server := &http.Server{
Addr: ":" + port,
ReadHeaderTimeout: readHeaderTimeout,
}
go func() {
logger.Info("Listening on port '" + port + "'")
// When Shutdown is called, ListenAndServe will return http.ErrServerClosed, do not log it as an error
if err := server.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
logger.Error("HTTP server error: %v", slog.Any("err", err))
}
logger.Info("Stopped serving new connections.")
}()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
shutdownCtx, shutdownRelease := context.WithTimeout(context.Background(), shutdownTimeout)
defer shutdownRelease()
if err := server.Shutdown(shutdownCtx); err != nil {
logger.Error("HTTP shutdown error: %v", slog.Any("err", err))
return err
}
logger.Info("Graceful shutdown complete.")
return nil
}
func validateFlags() error {
if storagePath == "" {
return errors.New("--storage-path flag is required")
}
if metricName == "" {
return errors.New("--metric-name flag is required")
}
if logFormat != "json" && logFormat != "text" {
return errors.New("--log-format flag should be either 'json' or 'text'")
}
if logLevel != "debug" && logLevel != "info" && logLevel != "warn" && logLevel != "error" {
return errors.New("--log-level flag should be either 'debug', 'info', 'warn' or 'error'")
}
return nil
}
func createLogger(logFormat, logLevel string) *slog.Logger {
level := slog.LevelInfo
switch logLevel {
case "debug":
level = slog.LevelDebug
case "info":
level = slog.LevelInfo
case "warn":
level = slog.LevelWarn
case "error":
level = slog.LevelError
}
var handler slog.Handler
handlerOpts := slog.HandlerOptions{
Level: level,
}
if logFormat == "json" {
handler = slog.NewJSONHandler(os.Stdout, &handlerOpts)
} else {
handler = slog.NewTextHandler(os.Stdout, &handlerOpts)
}
return slog.New(handler)
}