Skip to content

Commit

Permalink
fix: log formatting + add disallow override file option to config
Browse files Browse the repository at this point in the history
  • Loading branch information
furan917 committed Nov 22, 2023
1 parent 66eb5ea commit 544767e
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 57 deletions.
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ The tool looks for a configuration file in `/etc/magecomm/`(unix) / `%APPDATA%\m

## Beta
Currently this tool is in beta, and is not recommended for production use.
Tested commands: RMQ based magerun command publishing, message listening, cat all supported archive types


## Installation

Expand All @@ -22,6 +20,7 @@ Download the latest release from the [releases page](https://github.com/furan917

example config.yml:
```
disallow_configfile_overwrite: true
magecomm_log_path: /var/log/magecomm.log
magecomm_log_level: warn
magecomm_max_operational_cpu_limit: 80
Expand Down Expand Up @@ -64,6 +63,7 @@ magecomm_required_magerun_command_args:
example config.json:
```
{
"disallow_configfile_overwrite": true,
"magecomm_log_path": "/var/log/magecomm.log",
"magecomm_log_level": "warn",
"magecomm_max_operational_cpu_limit": 80,
Expand Down Expand Up @@ -117,11 +117,14 @@ example config.json:
### Global Flags

- `--debug`: Enable debug mode
- `--config`: Path to overwrite config file, argument can be disabled by default config file

e.g
`magecomm --debug listen`
`magecomm --debug magerun cache:clean`
`magecomm --debug cat path/to/archive.tar.gz /path/to/file.txt`
`magecomm --config=/custom/config/path.json magerun indexer:status`
`magecomm --config=/custom/config/path.json --debug magerun indexer:reindex`

### Commands

Expand All @@ -143,11 +146,15 @@ e.g

## Configuration

The tool can be configured using a yaml or json config file at `/etc/magecomm/`(unix) / `%APPDATA%\magecomm\`(windows) or by environment variables.
lowercase for file based config, uppercase for ENV.
The tool can be configured using a yaml or json config file at `/etc/magecomm/` (unix) | `%APPDATA%\magecomm\` (windows), or using `--config=/custom/config/path.json` before the command e.g. `magecomm --config=... magerun`, or by ENV variables.
Magecomm has a fallback strategy of, config file -> ENV -> default values

_You can disable by the config override argument by placing `disallow_configfile_overwrite: true` in the default config file_

The tool supports slack command run notifications via Webhook or App integration
The tool can also supports slack command run notifications via Webhook or App integration

## Config Options
_All caps for envs, lowercase for config file_
- `MAGECOMM_LOG_PATH`: Path to log file, default: SYSLOG
- `MAGECOMM_LOG_LEVEL`: Log level, default: WARN, options (TRACE, DEBUG, INFO, WARN, ERROR, FATAL, PANIC)
- `MAGECOMM_MAX_OPERATIONAL_CPU_LIMIT`: Maximum CPU limit of system before we defer processing messages, default: 80
Expand Down
10 changes: 7 additions & 3 deletions cmd/magerun.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,16 @@ func handleGlobalArguments(args []string) []string {
// global Arg handling must be done manually
var globalArguments []string
var overrideFilePath string
var enableDebugLogging bool

//Note arguments between start and magerun command.
for i, arg := range args {
if strings.HasPrefix(arg, "--") {
globalArguments = append(globalArguments, arg)

//if arg is --debug then enable debug mode
//if arg is --debug then flag debug to be enabled after configuration step
if arg == "--debug" {
logger.Warnf("Magerun: Debug mode enabled")
logger.EnableDebugMode()
enableDebugLogging = true
}

//if arg is --config then configure
Expand Down Expand Up @@ -137,6 +137,10 @@ func handleGlobalArguments(args []string) []string {
}
}

if enableDebugLogging {
logger.EnableDebugMode()
}

config_manager.Configure(overrideFilePath)
initializeModuleWhichRequireConfig()

Expand Down
77 changes: 51 additions & 26 deletions config_manager/base_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,49 +105,74 @@ func getDefault(key string) string {
}

func Configure(overrideFile string) {
if overrideFile != "" {
viper.SetConfigFile(overrideFile)
} else {
// Set base folder and file name of config file
viper.SetConfigName("config")
if runtime.GOOS == "windows" {
viper.AddConfigPath(os.Getenv("APPDATA") + "\\magecomm\\")
} else {
viper.AddConfigPath("/etc/magecomm/")
}
// Search for json config file first, then fallback to yaml
viper.SetConfigType("json")
if err := viper.ReadInConfig(); err != nil {
viper.SetConfigType("yaml")
}
overrideFile = strings.TrimSpace(overrideFile)
overrideFile = strings.Trim(overrideFile, `'"`)
defaultConfigError := configureDefaultsConfig()
disallowOverwrite := viper.GetBool("disallow_configfile_overwrite")

if disallowOverwrite && overrideFile != "" {
logger.Warnf("Config file overwriting is disallowed, ignoring passed in config file")
}

err := viper.ReadInConfig()
if err != nil {
// If the configuration file does not exist, warn user that env vars will be used
var configFileNotFoundError viper.ConfigFileNotFoundError
if errors.As(err, &configFileNotFoundError) {
logger.Infof("No config file found, reading fully from env vars, this is less secure")
} else {
logger.Warnf("Failed to read the config file, reading from ENV vars, this is less secure: %v", err)
return
if !disallowOverwrite && overrideFile != "" {
viper.Reset()
viper.SetConfigFile(overrideFile)
err := viper.ReadInConfig()
if err != nil {
if defaultConfigError == nil {
logger.Warnf("Failed to read the config file, reapplying default config")
err := configureDefaultsConfig()
if err != nil {
// We checked for this above, so this should never happen
}
} else {
logger.Warnf("Failed to read the both the override and default config file, defaulting to env variable reading")
}
}
}

if logPath := GetValue(ConfigLogPath); logPath != "" {
logger.ConfigureLogPath(logPath)
logger.Infof("Logging to file: %s", logPath)
}

if logLevel := GetValue(ConfigLogLevel); logLevel != "" {
logger.SetLogLevel(logLevel)
logger.Infof("Logging level set to: %s", logLevel)
}

configName := viper.ConfigFileUsed()
logger.Infof("Using config file: %s", configName)
}

func configureDefaultsConfig() error {
viper.Reset()

viper.SetConfigName("config")
if runtime.GOOS == "windows" {
viper.AddConfigPath(os.Getenv("APPDATA") + "\\magecomm\\")
} else {
viper.AddConfigPath("/etc/magecomm/")
}
// Search for json config file first, then fallback to yaml
viper.SetConfigType("json")
if err := viper.ReadInConfig(); err != nil {
viper.SetConfigType("yaml")
}
err := viper.ReadInConfig()
if err != nil {
// If the configuration file does not exist, warn user that env vars will be used
var configFileNotFoundError viper.ConfigFileNotFoundError
if errors.As(err, &configFileNotFoundError) {
logger.Infof("No default config file found, reading fully from env vars, this is less secure")
return err
} else {
logger.Warnf("Failed to read the default config file, reading from ENV vars, this is less secure: %v", err)
return err
}
}

return nil
}

func GetBoolValue(key string) bool {
value := GetValue(key)
for _, v := range trueValues {
Expand Down
51 changes: 33 additions & 18 deletions logger/logger.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package logger

// This package is used to log messages easily It is a wrapper around the logrus package.
// This package is used to Log messages easily It is a wrapper around the logrus package.

import (
"github.com/sirupsen/logrus"
Expand All @@ -19,14 +19,17 @@ const (
PanicLevel = logrus.PanicLevel
)

var Log *logrus.Logger
var (
Log *logrus.Logger
debugFlagSet bool
)

func init() {
logrus.SetFormatter(&logrus.TextFormatter{
Log = logrus.StandardLogger()
Log.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
})
logrus.SetLevel(logrus.WarnLevel)
Log = logrus.StandardLogger()
Log.SetLevel(logrus.WarnLevel)
}

func ConfigureLogPath(logFile string) {
Expand All @@ -37,18 +40,23 @@ func ConfigureLogPath(logFile string) {

if _, err := os.Stat(logFile); os.IsNotExist(err) {
if err := createLogFile(logFile); err != nil {
Log.Errorf("Unable to create log file, please contact your system administrator")
Log.Errorf("Unable to create Log file, please contact your system administrator")
}
}

file, err := os.OpenFile(logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0755)
if err != nil {
logrus.SetOutput(os.Stdout)
Log.Errorf("Unable to open log file, printing to stdout, please contact your system administrator")
Log.SetOutput(os.Stdout)
Log.Errorf("Unable to open Log file, printing to stdout, please contact your system administrator")
return
}

logrus.SetOutput(file)
//Log.SetFormatter(&logrus.JSONFormatter{})
Log.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
})
Log.SetOutput(file)
Log.Infof("Logging to file: %s", file.Name())
}

func createLogFile(logFile string) error {
Expand All @@ -58,24 +66,31 @@ func createLogFile(logFile string) error {
}
defer func(file *os.File) {
if err := file.Close(); err != nil {
Log.Fatal("Unable to close log file, please contact your system administrator")
Log.Fatal("Unable to close Log file, please contact your system administrator")
}
}(file)
return nil
}

func EnableDebugMode() {
SetLogLevel(logrus.DebugLevel.String())
debugFlagSet = true
}

func SetLogLevel(level string) {
if debugFlagSet {
Log.Info("Debug mode enabled by flag, ignoring log level configuration")
return
}

logrusLevel, err := logrus.ParseLevel(strings.ToLower(level))
if err != nil {
logrus.Warnf("Invalid log level: %s, defaulting to %s", level, logrus.WarnLevel.String())
Log.Warnf("Invalid Log level: %s, defaulting to %s", level, logrus.WarnLevel.String())
logrusLevel = logrus.WarnLevel
}

logrus.SetLevel(logrusLevel)
Log.SetLevel(logrusLevel)
Log.Infof("Log level set to %s", logrusLevel)
}

func Trace(args ...interface{}) {
Expand Down Expand Up @@ -111,25 +126,25 @@ func Tracef(format string, args ...interface{}) {
}

func Debugf(format string, args ...interface{}) {
logrus.Debugf(format, args...)
Log.Debugf(format, args...)
}

func Infof(format string, args ...interface{}) {
logrus.Infof(format, args...)
Log.Infof(format, args...)
}

func Warnf(format string, args ...interface{}) {
logrus.Warnf(format, args...)
Log.Warnf(format, args...)
}

func Errorf(format string, args ...interface{}) {
logrus.Errorf(format, args...)
Log.Errorf(format, args...)
}

func Fatalf(format string, args ...interface{}) {
logrus.Fatalf(format, args...)
Log.Fatalf(format, args...)
}

func Panicf(format string, args ...interface{}) {
logrus.Panicf(format, args...)
Log.Panicf(format, args...)
}
11 changes: 6 additions & 5 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,22 @@ import (
"magecomm/logger"
"magecomm/notifictions"
"magecomm/services"
"strings"
)

var RootCmd = &cobra.Command{
Use: "magecomm",
Short: "MageComm CLI is a command line tool for managing Magento applications",
PersistentPreRun: func(cmd *cobra.Command, args []string) {

overrideFilePath, _ := cmd.Flags().GetString("config")
config_manager.Configure(overrideFilePath)
initializeModuleWhichRequireConfig()

debug, _ := cmd.Flags().GetBool("debug")
if debug {
logger.EnableDebugMode()
}

overrideFilePath, _ := cmd.Flags().GetString("config")
config_manager.Configure(overrideFilePath)
initializeModuleWhichRequireConfig()
},
}

Expand All @@ -43,6 +44,6 @@ func main() {

err := RootCmd.Execute()
if err != nil {
logger.Fatalf("Failed to execute command: %s", err)
logger.Fatalf("Failed to execute command: %s", strings.ReplaceAll(err.Error(), "\n", " "))
}
}

0 comments on commit 544767e

Please sign in to comment.