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 }