Skip to content

Commit

Permalink
#6 Refactor logging
Browse files Browse the repository at this point in the history
  • Loading branch information
codemental committed Feb 9, 2024
1 parent ee8fed4 commit ac60aed
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 38 deletions.
16 changes: 4 additions & 12 deletions clarum.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
package clarum

import (
"fmt"
"github.com/goclarum/clarum/core/config"
"github.com/goclarum/clarum/core/control"
"log/slog"
"os"
"github.com/goclarum/clarum/core/logging"
)

func Setup() {
slog.Info(fmt.Sprintf("Starting clarum %s", config.Version()))

// TODO: go 1.22 will allow us to set the level on the default logger without changing the format
// this change is what we need: https://github.com/golang/go/commit/3188758653fc7d2b229e234273d41878ddfdd5f2
// release date February 2024
h := slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: config.LoggingLevel()})
slog.SetDefault(slog.New(h))
logging.Infof("Starting clarum %s", config.Version())
}

func Finish() {
slog.Info("Waiting for all actions to finish.")
logging.Info("Waiting for all actions to finish.")

control.RunningActions.Wait()

slog.Info("All actions finished.")
logging.Info("All actions finished.")
}
6 changes: 3 additions & 3 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package config

import (
"fmt"
"github.com/goclarum/clarum/core/files"
"github.com/goclarum/clarum/core/logging"
"gopkg.in/yaml.v3"
"log/slog"
"path"
Expand All @@ -26,7 +26,7 @@ func init() {
configFilePath := path.Join(*baseDir, *configFile)
config, err := files.ReadYamlFileToStruct[Config](configFilePath)
if err != nil {
slog.Info("Failed to load config file. Default values will be used instead")
logging.Info("Failed to load config file. Default values will be used instead")
config = &Config{}
}

Expand All @@ -35,7 +35,7 @@ func init() {
c = config

configYaml, _ := yaml.Marshal(config)
slog.Info(fmt.Sprintf("Using the following config:\n[\n%s]", configYaml))
logging.Infof("Using the following config:\n[\n%s]", configYaml)
}

func Version() string {
Expand Down
2 changes: 1 addition & 1 deletion durations/durations.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package durations

import "time"

// Get either the value configured without changing anything
// GetDurationWithDefault gets either the value configured without changing anything
// OR the default provided in case the value is 0
func GetDurationWithDefault(value time.Duration, defaultToSet time.Duration) time.Duration {
var warmupToSet time.Duration
Expand Down
9 changes: 4 additions & 5 deletions files/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,28 @@ package files

import (
"errors"
"fmt"
"github.com/goclarum/clarum/core/logging"
"github.com/goclarum/clarum/core/validators/strings"
"gopkg.in/yaml.v3"
"log/slog"
"os"
)

func ReadYamlFileToStruct[S any](filePath string) (*S, error) {
if strings.IsBlank(filePath) {
slog.Error("Unable to read file. File path is empty")
logging.Error("Unable to read file. File path is empty")
return nil, errors.New("file path is empty")
}

buf, err := os.ReadFile(filePath)
if err != nil {
slog.Error(fmt.Sprintf("Failed to load file: %s", err.Error()))
logging.Errorf("Failed to load file: %s", err.Error())
return nil, err
}

out := new(S)

if err := yaml.Unmarshal(buf, out); err != nil {
slog.Error(fmt.Sprintf("Failed to unmarshal yaml file %s: %s", filePath, err.Error()))
logging.Errorf("Failed to unmarshal yaml file %s: %s", filePath, err.Error())
return nil, err
}

Expand Down
106 changes: 106 additions & 0 deletions logging/logging.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package logging

import (
"fmt"
"log"
"log/slog"
"os"
)

var internalLogger = log.New(os.Stdout, "", log.LstdFlags|log.Lmicroseconds)
var defaultLogger = NewLogger(slog.LevelInfo, "")

type Logger struct {
level slog.Level
prefix string
}

func NewLogger(level slog.Level, prefix string) *Logger {
return &Logger{level, prefix}
}

func (logger *Logger) Info(message string) {
if logger.level <= slog.LevelInfo {
internalLogger.Println("INFO " + logger.prefix + message)
}
}

func (logger *Logger) Infof(format string, a ...any) {
if logger.level <= slog.LevelInfo {
internalLogger.Println("INFO " + logger.prefix + fmt.Sprintf(format, a...))
}
}

func (logger *Logger) Debug(message string) {
if logger.level <= slog.LevelDebug {
internalLogger.Println("DEBUG " + logger.prefix + message)
}
}

func (logger *Logger) Debugf(format string, a ...any) {
if logger.level <= slog.LevelDebug {
internalLogger.Println("DEBUG " + logger.prefix + fmt.Sprintf(format, a...))
}
}

func (logger *Logger) Warn(message string) {
if logger.level <= slog.LevelWarn {
internalLogger.Println("WARN " + logger.prefix + message)
}
}

func (logger *Logger) Warnf(format string, a ...any) {
if logger.level <= slog.LevelWarn {
internalLogger.Println("WARN " + logger.prefix + fmt.Sprintf(format, a...))
}
}

func (logger *Logger) Error(message string) {
if logger.level <= slog.LevelError {
internalLogger.Println("ERROR " + logger.prefix + message)
}
}

func (logger *Logger) Errorf(format string, a ...any) {
if logger.level <= slog.LevelError {
internalLogger.Println("ERROR " + logger.prefix + fmt.Sprintf(format, a...))
}
}

func (logger *Logger) Prefix() string {
return logger.prefix
}

// calls on the default logger

func Info(message string) {
defaultLogger.Info(message)
}

func Infof(format string, a ...any) {
defaultLogger.Infof(format, a...)
}

func Debug(message string) {
defaultLogger.Debug(message)
}

func Debugf(format string, a ...any) {
defaultLogger.Debugf(format, a...)
}

func Warn(message string) {
defaultLogger.Warn(message)
}

func Warnf(format string, a ...any) {
defaultLogger.Warnf(format, a...)
}

func Error(message string) {
defaultLogger.Error(message)
}

func Errorf(format string, a ...any) {
defaultLogger.Errorf(format, a...)
}
34 changes: 17 additions & 17 deletions orchestration/command/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ package command
import (
"context"
"fmt"
"github.com/goclarum/clarum/core/config"
"github.com/goclarum/clarum/core/control"
"github.com/goclarum/clarum/core/durations"
"github.com/goclarum/clarum/core/logging"
clarumstrings "github.com/goclarum/clarum/core/validators/strings"
"log/slog"
"os/exec"
"time"
)
Expand All @@ -17,6 +18,7 @@ type Endpoint struct {
warmup time.Duration
cmd *exec.Cmd
cmdCancel context.CancelFunc
logger *logging.Logger
}

func newCommandEndpoint(name string, components []string, warmup time.Duration) *Endpoint {
Expand All @@ -28,29 +30,29 @@ func newCommandEndpoint(name string, components []string, warmup time.Duration)
name: name,
cmdComponents: components,
warmup: durations.GetDurationWithDefault(warmup, 1*time.Second),
logger: logging.NewLogger(config.LoggingLevel(), logPrefix(name)),
}
}

// Start the process from the given command & arguments.
// The process will be started into a cancelable context so that we can
// cancel it later in the post-integration test phase.
func (endpoint *Endpoint) start() error {
logPrefix := logPrefix(endpoint.name)
slog.Info(fmt.Sprintf("%s: running cmd [%s]", logPrefix, endpoint.cmdComponents))
endpoint.logger.Infof("running cmd [%s]", endpoint.cmdComponents)
ctx, cancel := context.WithCancel(context.Background())

endpoint.cmd = exec.CommandContext(ctx, endpoint.cmdComponents[0], endpoint.cmdComponents[1:]...)
endpoint.cmdCancel = cancel

slog.Debug(fmt.Sprintf("%s: starting command", logPrefix))
endpoint.logger.Debug("starting command")
if err := endpoint.cmd.Start(); err != nil {
return err
} else {
slog.Debug(fmt.Sprintf("%s: cmd start successful", logPrefix))
endpoint.logger.Debug("cmd start successful")
}

time.Sleep(endpoint.warmup)
slog.Debug(fmt.Sprintf("%s: warmup ended", logPrefix))
endpoint.logger.Debug("warmup ended")

return nil
}
Expand All @@ -62,43 +64,41 @@ func (endpoint *Endpoint) stop() error {
control.RunningActions.Add(1)
defer control.RunningActions.Done()

logPrefix := logPrefix(endpoint.name)
slog.Info(fmt.Sprintf("%s: stopping cmd [%s]", logPrefix, endpoint.cmdComponents))
endpoint.logger.Infof("stopping cmd [%s]", endpoint.cmdComponents)

if endpoint.cmdCancel != nil {
slog.Debug(fmt.Sprintf("%s: cancelling cmd", logPrefix))
endpoint.logger.Debug("cancelling cmd")
endpoint.cmdCancel()

if _, err := endpoint.cmd.Process.Wait(); err != nil {
slog.Error(fmt.Sprintf(fmt.Sprintf("%s: cmd.Wait() returned error - [%s]", logPrefix, err)))
endpoint.logger.Errorf("cmd.Wait() returned error - [%s]", err)
endpoint.killProcess()
return err
} else {
slog.Debug(fmt.Sprintf("%s: context cancel finished successfully", logPrefix))
endpoint.logger.Debug("context cancel finished successfully")
}
} else {
if err := endpoint.cmd.Process.Release(); err != nil {
slog.Error(fmt.Sprintf("%s: cmd.Release() returned error - [%s]", logPrefix, err))
endpoint.logger.Errorf("cmd.Release() returned error - [%s]", err)
endpoint.killProcess()
return err
} else {
slog.Debug(fmt.Sprintf("%s: cmd kill successful", logPrefix))
endpoint.logger.Debug("cmd kill successful")
}
}

return nil
}

func (endpoint *Endpoint) killProcess() {
logPrefix := logPrefix(endpoint.name)
slog.Info(fmt.Sprintf(fmt.Sprintf("%s: killing process", logPrefix)))
endpoint.logger.Info("killing process")

if err := endpoint.cmd.Process.Kill(); err != nil {
slog.Error(fmt.Sprintf("%s: cmd.Kill() returned error - [%s]", logPrefix, err))
endpoint.logger.Errorf("cmd.Kill() returned error - [%s]", err)
return
}
}

func logPrefix(cmdName string) string {
return fmt.Sprintf("Command %s", cmdName)
return fmt.Sprintf("Command %s: ", cmdName)
}

0 comments on commit ac60aed

Please sign in to comment.