github.com/Axway/agent-sdk@v1.1.101/pkg/util/log/loggerconfig.go (about)

     1  package log
     2  
     3  import (
     4  	"flag"
     5  	"io"
     6  	"os"
     7  	"path"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/sirupsen/logrus"
    12  	"github.com/snowzach/rotatefilehook"
    13  )
    14  
    15  // GlobalLoggerConfig - is the default config of the logger
    16  var GlobalLoggerConfig LoggerConfig
    17  
    18  func init() {
    19  	GlobalLoggerConfig = LoggerConfig{
    20  		output: STDOUT,
    21  		path:   ".",
    22  		cfg: rotatefilehook.RotateFileConfig{
    23  			Level: logrus.InfoLevel,
    24  			Formatter: &logrus.JSONFormatter{
    25  				TimestampFormat: time.RFC3339,
    26  				FieldMap: logrus.FieldMap{
    27  					logrus.FieldKeyMsg: "message",
    28  				},
    29  			},
    30  		},
    31  		metricCfg: rotatefilehook.RotateFileConfig{
    32  			Level: logrus.InfoLevel,
    33  			Formatter: &logrus.JSONFormatter{
    34  				TimestampFormat: time.RFC3339,
    35  				FieldMap: logrus.FieldMap{
    36  					logrus.FieldKeyMsg: "message",
    37  				},
    38  			},
    39  		},
    40  		usageCfg: rotatefilehook.RotateFileConfig{
    41  			Level: logrus.InfoLevel,
    42  			Formatter: &logrus.JSONFormatter{
    43  				TimestampFormat: time.RFC3339,
    44  				FieldMap: logrus.FieldMap{
    45  					logrus.FieldKeyMsg: "message",
    46  				},
    47  			},
    48  		},
    49  		initialized: false,
    50  	}
    51  }
    52  
    53  // LoggerConfig - is a builder used to setup the logging for an agent
    54  type LoggerConfig struct {
    55  	err           error
    56  	output        LoggingOutput
    57  	path          string
    58  	cfg           rotatefilehook.RotateFileConfig
    59  	metricCfg     rotatefilehook.RotateFileConfig
    60  	usageCfg      rotatefilehook.RotateFileConfig
    61  	initialized   bool
    62  	metricEnabled bool
    63  	usageEnabled  bool
    64  }
    65  
    66  // Apply - applies the config changes to the logger
    67  func (b *LoggerConfig) Apply() error {
    68  	if b.err != nil {
    69  		return b.err
    70  	}
    71  
    72  	// validate metric fields, if enabled
    73  	if b.metricEnabled {
    74  		if err := b.validateSize("log.metricfile.rotateeverybytes", b.metricCfg.MaxSize); err != nil {
    75  			return err
    76  		}
    77  		if err := b.validate0orGreater("log.metricfile.keepfiles", b.metricCfg.MaxBackups); err != nil {
    78  			return err
    79  		}
    80  		if err := b.validate0orGreater("log.metricfile.cleanbackupsevery", b.metricCfg.MaxAge); err != nil {
    81  			return err
    82  		}
    83  		b.metricCfg.MaxSize = ConvertMaxSize(b.metricCfg.MaxSize)
    84  	}
    85  
    86  	if b.usageEnabled {
    87  		if err := b.validateSize("log.usagefile.rotateeverybytes", b.usageCfg.MaxSize); err != nil {
    88  			return err
    89  		}
    90  		if err := b.validate0orGreater("log.usagefile.keepfiles", b.usageCfg.MaxBackups); err != nil {
    91  			return err
    92  		}
    93  		if err := b.validate0orGreater("log.usagefile.cleanbackupsevery", b.usageCfg.MaxAge); err != nil {
    94  			return err
    95  		}
    96  		b.usageCfg.MaxSize = ConvertMaxSize(b.usageCfg.MaxSize)
    97  	}
    98  
    99  	// update the log logger
   100  	log.SetFormatter(b.cfg.Formatter)
   101  	log.SetLevel(b.cfg.Level)
   102  
   103  	// update the logrus logger
   104  	logrus.SetFormatter(b.cfg.Formatter)
   105  	logrus.SetLevel(b.cfg.Level)
   106  
   107  	// Set the stdout output for the log and logrus
   108  	if b.output == STDOUT || b.output == Both {
   109  		writer := io.Writer(os.Stdout)
   110  		log.SetOutput(writer)
   111  		logrus.SetOutput(writer)
   112  	}
   113  
   114  	if !b.initialized || isLogP {
   115  		// Add the rotate file hook for log and logrus
   116  		if b.output == File || b.output == Both {
   117  			if b.path != "" {
   118  				b.cfg.Filename = path.Join(b.path, b.cfg.Filename)
   119  			}
   120  			rotateFileHook, _ := rotatefilehook.NewRotateFileHook(b.cfg)
   121  			log.AddHook(rotateFileHook)
   122  			logrus.StandardLogger().AddHook(rotateFileHook)
   123  		}
   124  
   125  		isTest := flag.Lookup("test.v") != nil
   126  
   127  		// skip metric log setup in unit tests
   128  		if !isTest && b.metricEnabled {
   129  			b.metricCfg.Filename = path.Join(b.path, "audit", b.metricCfg.Filename)
   130  			rotateMetricHook, _ := rotatefilehook.NewRotateFileHook(b.metricCfg)
   131  			metric.AddHook(rotateMetricHook)
   132  			metric.SetOutput(io.Discard) // discard logging to stderr
   133  		}
   134  
   135  		if !isTest && b.usageEnabled {
   136  			b.usageCfg.Filename = path.Join(b.path, "audit", b.usageCfg.Filename)
   137  			rotateUsageHook, _ := rotatefilehook.NewRotateFileHook(b.usageCfg)
   138  			usage.AddHook(rotateUsageHook)
   139  			usage.SetOutput(io.Discard) // discard logging to stderr
   140  		}
   141  
   142  		// Set to initialized if this is not a test
   143  		b.initialized = !isTest
   144  	}
   145  
   146  	return nil
   147  }
   148  
   149  // Level - sets the logger level
   150  func (b *LoggerConfig) Level(level string) *LoggerConfig {
   151  	if b.err == nil {
   152  		lvl, err := logrus.ParseLevel(level)
   153  		if err != nil {
   154  			b.err = ErrInvalidLogConfig.FormatError("log.level", "trace, debug, info, warn, error")
   155  		}
   156  		b.cfg.Level = lvl
   157  	}
   158  	return b
   159  }
   160  
   161  // GetLevel - returns current log level
   162  func (b *LoggerConfig) GetLevel() string {
   163  	return b.cfg.Level.String()
   164  }
   165  
   166  // Format - sets the logger formatt
   167  func (b *LoggerConfig) Format(format string) *LoggerConfig {
   168  	if b.err == nil {
   169  		switch strings.ToLower(format) {
   170  		case loggingFormatStringMap[Line]:
   171  			b.cfg.Formatter = &logrus.TextFormatter{
   172  				TimestampFormat:  time.RFC3339,
   173  				FullTimestamp:    true,
   174  				PadLevelText:     true,
   175  				QuoteEmptyFields: true,
   176  				DisableColors:    true,
   177  				FieldMap: logrus.FieldMap{
   178  					logrus.FieldKeyMsg: "message",
   179  				},
   180  			}
   181  		case loggingFormatStringMap[JSON]:
   182  			b.cfg.Formatter = &logrus.JSONFormatter{
   183  				TimestampFormat: time.RFC3339,
   184  				FieldMap: logrus.FieldMap{
   185  					logrus.FieldKeyMsg: "message",
   186  				},
   187  			}
   188  		default:
   189  			b.err = ErrInvalidLogConfig.FormatError("log.format", "json, line")
   190  		}
   191  	}
   192  	return b
   193  }
   194  
   195  // Output - sets how the logs will be tracked
   196  func (b *LoggerConfig) Output(output string) *LoggerConfig {
   197  	if b.err == nil {
   198  		if _, ok := stringLoggingOutputMap[strings.ToLower(output)]; !ok {
   199  			b.err = ErrInvalidLogConfig.FormatError("log.output", "stdout, file, both")
   200  		}
   201  		b.output = stringLoggingOutputMap[output]
   202  	}
   203  	return b
   204  }
   205  
   206  // Filename -
   207  func (b *LoggerConfig) Filename(filename string) *LoggerConfig {
   208  	if b.err == nil {
   209  		b.cfg.Filename = filename
   210  	}
   211  	return b
   212  }
   213  
   214  // Path -
   215  func (b *LoggerConfig) Path(path string) *LoggerConfig {
   216  	if b.err == nil {
   217  		b.path = path
   218  	}
   219  	return b
   220  }
   221  
   222  func (b *LoggerConfig) Metrics(enabled bool) *LoggerConfig {
   223  	if b.err == nil {
   224  		b.metricEnabled = enabled
   225  	}
   226  	return b
   227  }
   228  
   229  func (b *LoggerConfig) Usage(enabled bool) *LoggerConfig {
   230  	if b.err == nil {
   231  		b.usageEnabled = enabled
   232  	}
   233  	return b
   234  }
   235  
   236  func (b *LoggerConfig) validateSize(path string, maxSize int) error {
   237  	if maxSize < 1048576 {
   238  		return ErrInvalidLogConfig.FormatError(path, "minimum of 1048576")
   239  	}
   240  	return nil
   241  }
   242  
   243  func (b *LoggerConfig) validate0orGreater(path string, maxBackups int) error {
   244  	if maxBackups < 0 {
   245  		return ErrInvalidLogConfig.FormatError(path, "0 or greater")
   246  	}
   247  	return nil
   248  }
   249  
   250  // MaxSize -
   251  func (b *LoggerConfig) MaxSize(maxSize int) *LoggerConfig {
   252  	if b.err == nil {
   253  		b.err = b.validateSize("log.file.rotateeverybytes", maxSize)
   254  		b.cfg.MaxSize = ConvertMaxSize(maxSize)
   255  	}
   256  	return b
   257  }
   258  
   259  // MaxBackups -
   260  func (b *LoggerConfig) MaxBackups(maxBackups int) *LoggerConfig {
   261  	if b.err == nil {
   262  		b.err = b.validate0orGreater("log.file.keepfiles", maxBackups)
   263  		b.cfg.MaxBackups = maxBackups
   264  	}
   265  	return b
   266  }
   267  
   268  // MaxAge -
   269  func (b *LoggerConfig) MaxAge(maxAge int) *LoggerConfig {
   270  	if b.err == nil {
   271  		b.err = b.validate0orGreater("log.file.cleanbackupsevery", maxAge)
   272  		b.cfg.MaxAge = maxAge
   273  	}
   274  	return b
   275  }
   276  
   277  // Filename -
   278  func (b *LoggerConfig) MetricFilename(filename string) *LoggerConfig {
   279  	if b.err == nil {
   280  		b.metricCfg.Filename = filename
   281  	}
   282  	return b
   283  }
   284  
   285  // MaxMetricSize -
   286  func (b *LoggerConfig) MaxMetricSize(maxSize int) *LoggerConfig {
   287  	if b.err == nil {
   288  		b.metricCfg.MaxSize = maxSize
   289  	}
   290  	return b
   291  }
   292  
   293  // MaxMetricBackups -
   294  func (b *LoggerConfig) MaxMetricBackups(maxBackups int) *LoggerConfig {
   295  	if b.err == nil {
   296  		b.metricCfg.MaxBackups = maxBackups
   297  	}
   298  	return b
   299  }
   300  
   301  // MaxAge -
   302  func (b *LoggerConfig) MaxMetricAge(maxAge int) *LoggerConfig {
   303  	if b.err == nil {
   304  		b.metricCfg.MaxAge = maxAge
   305  	}
   306  	return b
   307  }
   308  
   309  func (b *LoggerConfig) UsageFilename(filename string) *LoggerConfig {
   310  	if b.err == nil {
   311  		b.usageCfg.Filename = filename
   312  	}
   313  	return b
   314  }
   315  
   316  func (b *LoggerConfig) MaxUsageSize(maxSize int) *LoggerConfig {
   317  	if b.err == nil {
   318  		b.usageCfg.MaxSize = maxSize
   319  	}
   320  	return b
   321  }
   322  
   323  func (b *LoggerConfig) MaxUsageBackups(maxBackups int) *LoggerConfig {
   324  	if b.err == nil {
   325  		b.usageCfg.MaxBackups = maxBackups
   326  	}
   327  	return b
   328  }
   329  
   330  func (b *LoggerConfig) MaxUsageAge(maxAge int) *LoggerConfig {
   331  	if b.err == nil {
   332  		b.usageCfg.MaxAge = maxAge
   333  	}
   334  	return b
   335  }
   336  
   337  // ConvertMaxSize - takes max size in bytes and returns in megabytes for the rotate file hook
   338  func ConvertMaxSize(maxSize int) int {
   339  	return int(maxSize / 1024 / 1024)
   340  }