github.com/Axway/agent-sdk@v1.1.101/pkg/config/logconfig.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"path/filepath"
     6  	"strings"
     7  
     8  	"github.com/Axway/agent-sdk/pkg/cmd/properties"
     9  	"github.com/Axway/agent-sdk/pkg/util/log"
    10  	"github.com/elastic/beats/v7/libbeat/cfgfile"
    11  	"github.com/elastic/beats/v7/libbeat/common"
    12  	"github.com/sirupsen/logrus"
    13  )
    14  
    15  // LogConfig - Interface for logging config
    16  type LogConfig interface {
    17  	SetLevel(level string)
    18  	GetMetricConfig() LogFileConfiguration
    19  	GetUsageConfig() LogFileConfiguration
    20  }
    21  
    22  // LogConfiguration -
    23  type LogConfiguration struct {
    24  	LogConfig
    25  	Level        string               `config:"level"`
    26  	Format       string               `config:"format"`
    27  	Output       string               `config:"output"`
    28  	File         LogFileConfiguration `config:"file"`
    29  	MetricFile   LogFileConfiguration `config:"metricfile"`
    30  	UsageFile    LogFileConfiguration `config:"usagefile"`
    31  	MaskedValues string               `config:"maskedvalues"`
    32  }
    33  
    34  func (l *LogConfiguration) setupLogger(agentType AgentType) error {
    35  	return log.GlobalLoggerConfig.Level(l.Level).
    36  		Format(l.Format).
    37  		Output(l.Output).
    38  		Filename(l.File.Name).
    39  		Path(l.File.Path).
    40  		MaxSize(l.File.MaxSize).
    41  		MaxBackups(l.File.MaxBackups).
    42  		MaxAge(l.File.MaxAge).
    43  		Metrics(agentType == TraceabilityAgent && l.MetricFile.Enabled).
    44  		MetricFilename(l.MetricFile.Name).
    45  		MaxMetricSize(l.MetricFile.MaxSize).
    46  		MaxMetricBackups(l.MetricFile.MaxBackups).
    47  		MaxMetricAge(l.MetricFile.MaxAge).
    48  		Usage(agentType == TraceabilityAgent && l.UsageFile.Enabled).
    49  		UsageFilename(l.UsageFile.Name).
    50  		MaxUsageSize(l.UsageFile.MaxSize).
    51  		MaxUsageBackups(l.UsageFile.MaxBackups).
    52  		MaxUsageAge(l.UsageFile.MaxAge).
    53  		Apply()
    54  }
    55  
    56  func (l *LogConfiguration) GetMetricConfig() LogFileConfiguration {
    57  	return l.MetricFile
    58  }
    59  
    60  func (l *LogConfiguration) GetUsagefileConfig() LogFileConfiguration {
    61  	return l.UsageFile
    62  }
    63  
    64  // LogFileConfiguration - setup the logging configuration for file output
    65  type LogFileConfiguration struct {
    66  	Enabled    bool   `config:"enable"`
    67  	Name       string `config:"name"`
    68  	Path       string `config:"path"`
    69  	MaxSize    int    `config:"rotateeverybytes"`
    70  	MaxAge     int    `config:"cleanbackups"`
    71  	MaxBackups int    `config:"keepfiles"`
    72  }
    73  
    74  const (
    75  	pathLogLevel                 = "log.level"
    76  	pathLogFormat                = "log.format"
    77  	pathLogOutput                = "log.output"
    78  	pathLogMaskedValues          = "log.maskedValues"
    79  	pathLogFileName              = "log.file.name"
    80  	pathLogFilePath              = "log.file.path"
    81  	pathLogFileMaxSize           = "log.file.rotateeverybytes"
    82  	pathLogFileMaxAge            = "log.file.cleanbackups"
    83  	pathLogFileMaxBackups        = "log.file.keepfiles"
    84  	pathLogMetricsFileEnabled    = "log.metricfile.enabled"
    85  	pathLogMetricsFileName       = "log.metricfile.name"
    86  	pathLogMetricsFileMaxSize    = "log.metricfile.rotateeverybytes"
    87  	pathLogMetricsFileMaxAge     = "log.metricfile.cleanbackups"
    88  	pathLogMetricsFileMaxBackups = "log.metricfile.keepfiles"
    89  	pathLogUsageFileEnabled      = "log.usagefile.enabled"
    90  	pathLogUsageFileName         = "log.usagefile.name"
    91  	pathLogUsageFileMaxSize      = "log.usagefile.rotateeverybytes"
    92  	pathLogUsageFileMaxAge       = "log.usagefile.cleanbackupsevery"
    93  	pathLogUsageFileMaxBackups   = "log.usagefile.keepfiles"
    94  )
    95  
    96  // AddLogConfigProperties - Adds the command properties needed for Log Config
    97  func AddLogConfigProperties(props properties.Properties, defaultFileName string) {
    98  	props.AddStringProperty(pathLogLevel, "info", "Log level (trace, debug, info, warn, error)")
    99  	props.AddStringProperty(pathLogFormat, "json", "Log format (json, line)")
   100  	props.AddStringProperty(pathLogOutput, "stdout", "Log output type (stdout, file, both)")
   101  	props.AddStringProperty(pathLogMaskedValues, "", "List of key words in the config to be masked (e.g. pwd, password, secret, key")
   102  
   103  	// Log file options
   104  	props.AddStringProperty(pathLogFileName, defaultFileName, "Name of the log files")
   105  	props.AddStringProperty(pathLogFilePath, "logs", "Log file path if output type is file or both")
   106  	props.AddIntProperty(pathLogFileMaxSize, 10485760, "The maximum size of a log file, in bytes  (default: 10485760 - 10 MB)")
   107  	props.AddIntProperty(pathLogFileMaxAge, 0, "The maximum number of days, 24 hour periods, to keep the log file backups")
   108  	props.AddIntProperty(pathLogFileMaxBackups, 7, "The maximum number of backups to keep of log files (default: 7)")
   109  }
   110  
   111  // AddMetricLogConfigProperties - Adds the command properties needed for Log Config
   112  func AddMetricLogConfigProperties(props properties.Properties, agentType AgentType) {
   113  	if agentType == DiscoveryAgent {
   114  		return
   115  	}
   116  	// Metric log file options
   117  	props.AddBoolProperty(pathLogMetricsFileEnabled, true, "Set to false to disable metrics file logging")
   118  	props.AddStringProperty(pathLogMetricsFileName, "metrics.log", "Name of the metric log files")
   119  	props.AddIntProperty(pathLogMetricsFileMaxSize, 10485760, "The maximum size of a metrics log file, in bytes (default: 10485760 - 10 MB)")
   120  	props.AddIntProperty(pathLogMetricsFileMaxAge, 0, "The maximum number of days, 24 hour periods, to keep the metrics log file backups")
   121  	props.AddIntProperty(pathLogMetricsFileMaxBackups, 0, "The maximum number of backups to keep of metrics log files (default: unlimited)")
   122  }
   123  
   124  func AddUsageConfigProperties(props properties.Properties, agentType AgentType) {
   125  	if agentType == DiscoveryAgent {
   126  		return
   127  	}
   128  
   129  	props.AddBoolProperty(pathLogUsageFileEnabled, true, "Set to false to disable usage file logging")
   130  	props.AddStringProperty(pathLogUsageFileName, "usage.log", "Name of the usage log files")
   131  	props.AddIntProperty(pathLogUsageFileMaxSize, 10485760, "The maximum size of a usage log file, in bytes (default: 10485760 - 10 MB)")
   132  	props.AddIntProperty(pathLogUsageFileMaxAge, 365, "The maximum number of days, 24 hour periods, to keep the usage log file backups")
   133  	props.AddIntProperty(pathLogUsageFileMaxBackups, 0, "The maximum number of backups to keep of metrics log files (default: unlimited)")
   134  }
   135  
   136  // ParseAndSetupLogConfig - Parses the Log Config and setups the logger
   137  func ParseAndSetupLogConfig(props properties.Properties, agentType AgentType) (LogConfig, error) {
   138  	cfg := &LogConfiguration{
   139  		Level:        props.StringPropertyValue(pathLogLevel),
   140  		Format:       props.StringPropertyValue(pathLogFormat),
   141  		Output:       props.StringPropertyValue(pathLogOutput),
   142  		MaskedValues: props.StringPropertyValue(pathLogMaskedValues),
   143  		File: LogFileConfiguration{
   144  			Name:       props.StringPropertyValue(pathLogFileName),
   145  			Path:       props.StringPropertyValue(pathLogFilePath),
   146  			MaxSize:    props.IntPropertyValue(pathLogFileMaxSize),
   147  			MaxBackups: props.IntPropertyValue(pathLogFileMaxBackups),
   148  			MaxAge:     props.IntPropertyValue(pathLogFileMaxAge),
   149  		},
   150  	}
   151  
   152  	if agentType == TraceabilityAgent {
   153  		cfg.MetricFile = LogFileConfiguration{
   154  			Enabled:    props.BoolPropertyValue(pathLogMetricsFileEnabled),
   155  			Name:       props.StringPropertyValue(pathLogMetricsFileName),
   156  			Path:       filepath.Join(cfg.File.Path, "metrics"),
   157  			MaxSize:    props.IntPropertyValue(pathLogMetricsFileMaxSize),
   158  			MaxBackups: props.IntPropertyValue(pathLogMetricsFileMaxBackups),
   159  			MaxAge:     props.IntPropertyValue(pathLogMetricsFileMaxAge),
   160  		}
   161  		cfg.UsageFile = LogFileConfiguration{
   162  			Enabled:    props.BoolPropertyValue(pathLogUsageFileEnabled),
   163  			Name:       props.StringPropertyValue(pathLogUsageFileName),
   164  			Path:       filepath.Join(cfg.File.Path, "usage"),
   165  			MaxSize:    props.IntPropertyValue(pathLogUsageFileMaxSize),
   166  			MaxBackups: props.IntPropertyValue(pathLogUsageFileMaxBackups),
   167  			MaxAge:     props.IntPropertyValue(pathLogUsageFileMaxAge),
   168  		}
   169  	}
   170  
   171  	// Only attempt to mask values if the key maskValues AND key words for maskValues exist
   172  	if cfg.MaskedValues != "" {
   173  		props.MaskValues(cfg.MaskedValues)
   174  	}
   175  
   176  	return cfg, cfg.setupLogger(agentType)
   177  }
   178  
   179  const (
   180  	logLevelYAMLPath       = "logging.level"
   181  	logJSONYAMLPath        = "logging.json"
   182  	logSTDERRYAMLPath      = "logging.to_stderr"
   183  	logFileYAMLPath        = "logging.to_files"
   184  	logFilePermissionsPath = "logging.files.permissions"
   185  )
   186  
   187  // LogConfigOverrides - override the filebeat config options
   188  func LogConfigOverrides() []cfgfile.ConditionalOverride {
   189  	overrides := make([]cfgfile.ConditionalOverride, 0)
   190  	overrides = setLogLevel(overrides)
   191  	return overrideLogLevel(overrides)
   192  }
   193  
   194  func setLogLevel(overrides []cfgfile.ConditionalOverride) []cfgfile.ConditionalOverride {
   195  	// Set level to info
   196  	overrides = append(overrides, cfgfile.ConditionalOverride{
   197  		Check: func(cfg *common.Config) bool {
   198  			aliasKeyPrefix := properties.GetAliasKeyPrefix()
   199  			output, _ := cfg.String(fmt.Sprintf("%s.%s", aliasKeyPrefix, pathLogLevel), 0)
   200  			level, err := logrus.ParseLevel(output)
   201  			if err == nil && level == logrus.InfoLevel {
   202  				return true
   203  			}
   204  			return false
   205  		},
   206  		Config: common.MustNewConfigFrom(map[string]interface{}{
   207  			logLevelYAMLPath: "info",
   208  		}),
   209  	})
   210  
   211  	// Set level to warn
   212  	overrides = append(overrides, cfgfile.ConditionalOverride{
   213  		Check: func(cfg *common.Config) bool {
   214  			aliasKeyPrefix := properties.GetAliasKeyPrefix()
   215  			output, _ := cfg.String(fmt.Sprintf("%s.%s", aliasKeyPrefix, pathLogLevel), 0)
   216  			level, err := logrus.ParseLevel(output)
   217  			if err == nil && level == logrus.WarnLevel {
   218  				return true
   219  			}
   220  			return false
   221  		},
   222  		Config: common.MustNewConfigFrom(map[string]interface{}{
   223  			logLevelYAMLPath: "warn",
   224  		}),
   225  	})
   226  
   227  	// Set level to error
   228  	overrides = append(overrides, cfgfile.ConditionalOverride{
   229  		Check: func(cfg *common.Config) bool {
   230  			aliasKeyPrefix := properties.GetAliasKeyPrefix()
   231  			output, _ := cfg.String(fmt.Sprintf("%s.%s", aliasKeyPrefix, pathLogLevel), 0)
   232  			level, err := logrus.ParseLevel(output)
   233  			if err == nil && level == logrus.ErrorLevel {
   234  				return true
   235  			}
   236  			return false
   237  		},
   238  		Config: common.MustNewConfigFrom(map[string]interface{}{
   239  			logLevelYAMLPath: "error",
   240  		}),
   241  	})
   242  
   243  	return overrides
   244  }
   245  
   246  func overrideLogLevel(overrides []cfgfile.ConditionalOverride) []cfgfile.ConditionalOverride {
   247  	// Override the level to debug, if trace or debug
   248  	overrides = append(overrides, cfgfile.ConditionalOverride{
   249  		Check: func(cfg *common.Config) bool {
   250  			aliasKeyPrefix := properties.GetAliasKeyPrefix()
   251  			output, _ := cfg.String(fmt.Sprintf("%s.%s", aliasKeyPrefix, pathLogLevel), 0)
   252  			level, err := logrus.ParseLevel(output)
   253  			if err == nil && (level == logrus.TraceLevel || level == logrus.DebugLevel) {
   254  				return true
   255  			}
   256  			return false
   257  		},
   258  		Config: common.MustNewConfigFrom(map[string]interface{}{
   259  			logLevelYAMLPath: "debug",
   260  		}),
   261  	})
   262  
   263  	// Override the log output format
   264  	overrides = append(overrides, cfgfile.ConditionalOverride{
   265  		Check: func(cfg *common.Config) bool {
   266  			aliasKeyPrefix := properties.GetAliasKeyPrefix()
   267  			output, _ := cfg.String(fmt.Sprintf("%s.%s", aliasKeyPrefix, pathLogFormat), 0)
   268  			return strings.ToLower(output) == "json"
   269  		},
   270  		Config: common.MustNewConfigFrom(map[string]interface{}{
   271  			logJSONYAMLPath: true,
   272  		}),
   273  	})
   274  
   275  	// Override the log output stream
   276  	overrides = append(overrides, cfgfile.ConditionalOverride{
   277  		Check: func(cfg *common.Config) bool {
   278  			aliasKeyPrefix := properties.GetAliasKeyPrefix()
   279  			output, _ := cfg.String(fmt.Sprintf("%s.%s", aliasKeyPrefix, pathLogOutput), 0)
   280  			return strings.ToLower(output) == "stdout"
   281  		},
   282  		Config: common.MustNewConfigFrom(map[string]interface{}{
   283  			logSTDERRYAMLPath: true,
   284  			logFileYAMLPath:   false,
   285  		}),
   286  	})
   287  
   288  	// Override the log output to file
   289  	overrides = append(overrides, cfgfile.ConditionalOverride{
   290  		Check: func(cfg *common.Config) bool {
   291  			aliasKeyPrefix := properties.GetAliasKeyPrefix()
   292  			output, _ := cfg.String(fmt.Sprintf("%s.%s", aliasKeyPrefix, pathLogOutput), 0)
   293  			if strings.ToLower(output) == "file" || strings.ToLower(output) == "both" {
   294  				if strings.ToLower(output) == "both" {
   295  					log.Warn("Traceability agent can only log to one output type, setting to file output")
   296  				}
   297  				return true
   298  			}
   299  			return false
   300  		},
   301  		Config: common.MustNewConfigFrom(map[string]interface{}{
   302  			logFileYAMLPath:        true,
   303  			logSTDERRYAMLPath:      false,
   304  			logFilePermissionsPath: "0600",
   305  		}),
   306  	})
   307  
   308  	return overrides
   309  }