github.com/nilium/gitlab-runner@v12.5.0+incompatible/log/configuration.go (about) 1 package log 2 3 import ( 4 "fmt" 5 "os" 6 7 "github.com/sirupsen/logrus" 8 "github.com/urfave/cli" 9 ) 10 11 const ( 12 FormatRunner = "runner" 13 FormatText = "text" 14 FormatJSON = "json" 15 ) 16 17 var ( 18 configuration = NewConfig(logrus.StandardLogger()) 19 20 logFlags = []cli.Flag{ 21 cli.BoolFlag{ 22 Name: "debug", 23 Usage: "debug mode", 24 EnvVar: "DEBUG", 25 }, 26 cli.StringFlag{ 27 Name: "log-format", 28 Usage: "Choose log format (options: runner, text, json)", 29 EnvVar: "LOG_FORMAT", 30 }, 31 cli.StringFlag{ 32 Name: "log-level, l", 33 Usage: "Log level (options: debug, info, warn, error, fatal, panic)", 34 EnvVar: "LOG_LEVEL", 35 }, 36 } 37 38 formats = map[string]logrus.Formatter{ 39 FormatRunner: new(RunnerTextFormatter), 40 FormatText: new(logrus.TextFormatter), 41 FormatJSON: new(logrus.JSONFormatter), 42 } 43 ) 44 45 func formatNames() []string { 46 formatNames := make([]string, 0) 47 for name := range formats { 48 formatNames = append(formatNames, name) 49 } 50 51 return formatNames 52 } 53 54 type Config struct { 55 logger *logrus.Logger 56 level logrus.Level 57 format logrus.Formatter 58 59 levelSetWithCli bool 60 formatSetWithCli bool 61 62 goroutinesDumpStopCh chan bool 63 } 64 65 func (l *Config) IsLevelSetWithCli() bool { 66 return l.levelSetWithCli 67 } 68 69 func (l *Config) IsFormatSetWithCli() bool { 70 return l.formatSetWithCli 71 } 72 73 func (l *Config) handleCliCtx(cliCtx *cli.Context) error { 74 if cliCtx.IsSet("log-level") || cliCtx.IsSet("l") { 75 err := l.SetLevel(cliCtx.String("log-level")) 76 if err != nil { 77 return err 78 } 79 l.levelSetWithCli = true 80 } 81 82 if cliCtx.Bool("debug") { 83 l.level = logrus.DebugLevel 84 l.levelSetWithCli = true 85 } 86 87 if cliCtx.IsSet("log-format") { 88 err := l.SetFormat(cliCtx.String("log-format")) 89 if err != nil { 90 return err 91 } 92 93 l.formatSetWithCli = true 94 } 95 96 l.ReloadConfiguration() 97 98 return nil 99 } 100 101 func (l *Config) SetLevel(levelString string) error { 102 level, err := logrus.ParseLevel(levelString) 103 if err != nil { 104 return fmt.Errorf("failed to parse log level: %v", err) 105 } 106 107 l.level = level 108 109 return nil 110 } 111 112 func (l *Config) SetFormat(format string) error { 113 formatter, ok := formats[format] 114 if !ok { 115 return fmt.Errorf("unknown log format %q, expected one of: %v", l.format, formatNames()) 116 } 117 118 l.format = formatter 119 120 return nil 121 } 122 123 func (l *Config) ReloadConfiguration() { 124 l.logger.SetFormatter(l.format) 125 l.logger.SetLevel(l.level) 126 127 if l.level == logrus.DebugLevel { 128 l.enableGoroutinesDump() 129 } else { 130 l.disableGoroutinesDump() 131 } 132 } 133 134 func (l *Config) enableGoroutinesDump() { 135 if l.goroutinesDumpStopCh != nil { 136 return 137 } 138 139 l.goroutinesDumpStopCh = make(chan bool) 140 141 watchForGoroutinesDump(l.logger, l.goroutinesDumpStopCh) 142 } 143 144 func (l *Config) disableGoroutinesDump() { 145 if l.goroutinesDumpStopCh == nil { 146 return 147 } 148 149 close(l.goroutinesDumpStopCh) 150 l.goroutinesDumpStopCh = nil 151 } 152 153 func NewConfig(logger *logrus.Logger) *Config { 154 return &Config{ 155 logger: logger, 156 level: logrus.InfoLevel, 157 format: new(RunnerTextFormatter), 158 } 159 } 160 161 func Configuration() *Config { 162 return configuration 163 } 164 165 func ConfigureLogging(app *cli.App) { 166 app.Flags = append(app.Flags, logFlags...) 167 168 appBefore := app.Before 169 app.Before = func(cliCtx *cli.Context) error { 170 Configuration().logger.SetOutput(os.Stderr) 171 172 err := Configuration().handleCliCtx(cliCtx) 173 if err != nil { 174 logrus.WithError(err).Fatal("Error while setting up logging configuration") 175 } 176 177 if appBefore != nil { 178 return appBefore(cliCtx) 179 } 180 return nil 181 } 182 }