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  }