~bayindirh/nudge

4779def2ef4c126fa71df4971669604cc1174fa4 — Hakan Bayindir 7 months ago a86277c
proj: Release version 0.2

- proj: Version is changed to 0.2.0
- proj: Version 0.2.0 is released.
- feat: Log levels can be configured with command line now.
- refactor: Change “warning” to “warn” since it's how Zap uses it.
- refactor: Remove getZapAtomicLevel() function since Zap provides a better one already.
- refactor: Change place of checkConfigurationSanity() function to correct place. After applying everything, yet before doing anything.
- refactor: Rewrite and refine some comments to make them more meaningful.
2 files changed, 44 insertions(+), 36 deletions(-)

M CHANGELOG.md
M src/nudge.go
M CHANGELOG.md => CHANGELOG.md +10 -0
@@ 2,6 2,16 @@

**Note:** Please add newest entries on top. Use ISO date format YYYY-MM-DD and markdown formatting.

## 2023-07-31

- proj: Version is changed to 0.2.0
- proj: Version 0.2.0 is released.
- feat: Log levels can be configured with command line now.
- refactor: Change `warning` to `warn` since it's how Zap uses it.
- refactor: Remove `getZapAtomicLevel()` function since Zap provides a better one already.
- refactor: Change place of `checkConfigurationSanity()` function to correct place. After applying everything, yet before doing anything.
- refactor: Rewrite and refine some comments to make them more meaningful.

## 2023-07-30

- refactor: Remove logging directives from `initializeValidConfigurationOptions()`, because it needs to run before logger initialization.

M src/nudge.go => src/nudge.go +34 -36
@@ 32,7 32,6 @@ import (

	"github.com/spf13/viper"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// This struct contains all the fields required for sending a notification.


@@ 93,7 92,7 @@ type ValidConfigurationOptions struct {
// used by the configuration sanity checker down the road, to make sure that everything
// is nice and shiny.
func initializeValidConfigurationOptions(ValidConfigurationOptions *ValidConfigurationOptions) {
	ValidConfigurationOptions.possibleLogLevels = []string{"debug", "info", "warning", "error", "fatal", "panic"}
	ValidConfigurationOptions.possibleLogLevels = []string{"debug", "info", "warn", "error", "fatal", "panic"}
}

// This function stores and applies the defaults of the application.


@@ 119,10 118,10 @@ func applyDefaultConfiguration(runtimeConfiguration *RuntimeConfiguration, notif
	// Let's set defaults for the application itself, again where it makes sense.
	applicationName := strings.Split(os.Args[0], "/")
	runtimeConfiguration.applicationName = applicationName[len(applicationName)-1]
	runtimeConfiguration.version = "0.2.0a20230729"
	runtimeConfiguration.version = "0.2.0"
	runtimeConfiguration.dryrun = false
	runtimeConfiguration.logfilePaths = []string{"stdout"}
	runtimeConfiguration.logLevel = "warning"
	runtimeConfiguration.logLevel = "warn"
}

// This function reads the configuration file and applies it to relevant data structures.


@@ 295,30 294,6 @@ func applyFlags(setFlags *[]string, flagStorage *FlagStorage, runtimeConfigurati
	logger.Debugf("Application of flags is completed, returning.")
}

/*
 * This function returns the appropriate Zap level for configuring the logger on the fly.
 * As a precaution, this function returns a sane default (INFO) if the supplied level
 * makes no sense.
 */
func getZapLoggerLevel(logLevel *string) zap.AtomicLevel {
	switch *logLevel {
	case "debug", "DEBUG":
		return zap.NewAtomicLevelAt(zapcore.DebugLevel)
	case "info", "INFO":
		return zap.NewAtomicLevelAt(zapcore.InfoLevel)
	case "warning", "WARNING":
		return zap.NewAtomicLevelAt(zapcore.WarnLevel)
	case "error", "ERROR":
		return zap.NewAtomicLevelAt(zapcore.ErrorLevel)
	case "fatal", "FATAL":
		return zap.NewAtomicLevelAt(zapcore.FatalLevel)
	case "panic", "PANIC":
		return zap.NewAtomicLevelAt(zapcore.PanicLevel)
	default:
		return zap.NewAtomicLevel()
	}
}

// This function checks configuration sanity when called, and creates warnings or errors depending on the situation.
// This function also called just before sending the notification, hence it handles showing help, creating warnings and other
// related user interfacing notifications.


@@ 451,14 426,24 @@ func main() {
	  }
	}`)

	var zapDefaultConfig zap.Config
	if err := json.Unmarshal(zapDefaultConfigJSON, &zapDefaultConfig); err != nil {
	var zapRuntimeConfig zap.Config
	if err := json.Unmarshal(zapDefaultConfigJSON, &zapRuntimeConfig); err != nil {
		panic(err)
	}
	
	// Let's change the logger's logging level before building the logger.
	zapDefaultConfig.Level = getZapLoggerLevel(&runtimeConfiguration.logLevel)
	logger := zap.Must(zapDefaultConfig.Build())
	/*
	 * We build the logger with the default configuration before everything else.
	 * We know that the config is sane, because it's hardcoded. We're using built-in
	 * defaults at that point.
	 */
	zapDefaultAtomicLevel, err := zap.ParseAtomicLevel(runtimeConfiguration.logLevel)
	
	if err != nil {
		panic (err)
	}
	
	zapRuntimeConfig.Level = zapDefaultAtomicLevel
	logger := zap.Must(zapRuntimeConfig.Build())

	defer logger.Sync() // Make sure that we sync when we exit.



@@ 483,13 468,26 @@ func main() {
		setFlags = append(setFlags, setFlag.Name)
	})
	
	// Then I can apply the set flags.
	applyFlags(&setFlags, &flagStorage, &runtimeConfiguration, &notificationToSend, sugaredLogger)
	
	// Run all the configuration checks and issue relevant warnings or errors.
	// TODO: Is here the best place to call this? Take a look before releasing.
	checkConfigurationSanity(&notificationToSend, &runtimeConfiguration, &validConfigurationOptions, sugaredLogger)

	// Then I can apply the set flags.
	applyFlags(&setFlags, &flagStorage, &runtimeConfiguration, &notificationToSend, sugaredLogger)

	// This is the demarcation line between config reading and starting doing things.
	
	// Let's try to change the logging level of our current logger.
	newLogLevelJSON := []byte(runtimeConfiguration.logLevel)
	
	err = zapRuntimeConfig.Level.UnmarshalText(newLogLevelJSON)
	
	if err != nil {
		sugaredLogger.Panicf("Supplied log level %s is invalid, exiting.", runtimeConfiguration.logLevel)
	}
	
	sugaredLogger.Debug("Logging level is changed to %s.", runtimeConfiguration.logLevel)
	
	// Check whether our version is asked or not.
	// Version info shall always return clean.
	if flagStorage.versionRequested {