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
|
package logger
import (
"fmt"
"io"
"log/syslog"
"os"
"time"
"gitlab.com/gitlab-org/labkit/log"
"gitlab.com/gitlab-org/gitlab-shell/v14/internal/config"
)
func logFmt(inFmt string) string {
// Hide the "combined" format, since that makes no sense in gitlab-shell.
// The default is JSON when unspecified.
if inFmt == "" || inFmt == "combined" {
return "json"
}
return inFmt
}
func logLevel(inLevel string) string {
if inLevel == "" {
return "info"
}
return inLevel
}
func logFile(inFile string) string {
if inFile == "" {
return "stderr"
}
return inFile
}
func buildOpts(cfg *config.Config) []log.LoggerOption {
return []log.LoggerOption{
log.WithFormatter(logFmt(cfg.LogFormat)),
log.WithOutputName(logFile(cfg.LogFile)),
log.WithTimezone(time.UTC),
log.WithLogLevel(logLevel(cfg.LogLevel)),
}
}
// Configure configures the logging singleton for operation inside a remote TTY (like SSH). In this
// mode an empty LogFile is not accepted and syslog is used as a fallback when LogFile could not be
// opened for writing.
func Configure(cfg *config.Config) io.Closer {
var closer io.Closer = io.NopCloser(nil)
err := fmt.Errorf("No logfile specified")
if cfg.LogFile != "" {
closer, err = log.Initialize(buildOpts(cfg)...)
}
if err != nil {
progName, _ := os.Executable()
syslogLogger, syslogLoggerErr := syslog.NewLogger(syslog.LOG_ERR|syslog.LOG_USER, 0)
if syslogLoggerErr == nil {
msg := fmt.Sprintf("%s: Unable to configure logging: %v\n", progName, err.Error())
syslogLogger.Print(msg)
} else {
msg := fmt.Sprintf("%s: Unable to configure logging: %v, %v\n", progName, err.Error(), syslogLoggerErr.Error())
fmt.Fprintf(os.Stderr, msg)
}
cfg.LogFile = "/dev/null"
closer, err = log.Initialize(buildOpts(cfg)...)
if err != nil {
log.WithError(err).Warn("Unable to configure logging to /dev/null, leaving unconfigured")
}
}
return closer
}
// ConfigureStandalone configures the logging singleton for standalone operation. In this mode an
// empty LogFile is treated as logging to stderr, and standard output is used as a fallback
// when LogFile could not be opened for writing.
func ConfigureStandalone(cfg *config.Config) io.Closer {
closer, err1 := log.Initialize(buildOpts(cfg)...)
if err1 != nil {
var err2 error
cfg.LogFile = "stdout"
closer, err2 = log.Initialize(buildOpts(cfg)...)
// Output this after the logger has been configured!
log.WithError(err1).WithField("log_file", cfg.LogFile).Warn("Unable to configure logging, falling back to STDOUT")
// LabKit v1.7.0 doesn't have any conditions where logging to "stdout" will fail
if err2 != nil {
log.WithError(err2).Warn("Unable to configure logging to STDOUT, leaving unconfigured")
}
}
return closer
}
|