Skip to content

Commit

Permalink
Merge branch 'feature/25_SetLogLevel' of ssh://github.com/cloudogu/k8…
Browse files Browse the repository at this point in the history
…s-ces-control into feature/25_SetLogLevel
  • Loading branch information
sklein94 committed May 23, 2024
2 parents ba6b093 + a89f66b commit a463649
Show file tree
Hide file tree
Showing 3 changed files with 183 additions and 63 deletions.
71 changes: 71 additions & 0 deletions packages/logging/level.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package logging

import (
"errors"
"fmt"
pb "github.com/cloudogu/ces-control-api/generated/logging"
"strings"
)

// LogLevel is the log level that can be defined for a dogu.
type LogLevel int

const (
LevelUnknown LogLevel = iota
LevelError
LevelWarn
LevelInfo
LevelDebug
)

// String converts LogLevel type to a string
func (l LogLevel) String() string {
switch l {
case LevelUnknown:
return "UNKNOWN"
case LevelDebug:
return "DEBUG"
case LevelInfo:
return "INFO"
case LevelWarn:
return "WARN"
case LevelError:
return "ERROR"
default:
return "WARN"
}
}

// CreateLogLevelFromProto maps protobuf log level to an internal log level used in application
func CreateLogLevelFromProto(pLevel pb.LogLevel) (LogLevel, error) {
switch pLevel {
case pb.LogLevel_DEBUG:
return LevelDebug, nil
case pb.LogLevel_INFO:
return LevelInfo, nil
case pb.LogLevel_WARN:
return LevelWarn, nil
case pb.LogLevel_ERROR:
return LevelError, nil
default:
return LevelUnknown, fmt.Errorf("unknown log level: %v", pLevel)
}
}

// CreateLogLevelFromString maps a string to an internal log level used in application
func CreateLogLevelFromString(sLevel string) (LogLevel, error) {
sLevelUpper := strings.ToUpper(sLevel)

switch sLevelUpper {
case LevelError.String():
return LevelError, nil
case LevelWarn.String():
return LevelWarn, nil
case LevelInfo.String():
return LevelInfo, nil
case LevelDebug.String():
return LevelDebug, nil
default:
return LevelUnknown, errors.New("unknown log level")
}
}
105 changes: 105 additions & 0 deletions packages/logging/level_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package logging

import (
"errors"
"fmt"
pbLogging "github.com/cloudogu/ces-control-api/generated/logging"
"testing"
)

func TestCreateLogLevelFromProto(t *testing.T) {
tests := []struct {
name string
expected LogLevel
input pbLogging.LogLevel
err error
}{
{"Debug", LevelDebug, pbLogging.LogLevel_DEBUG, nil},
{"Info", LevelInfo, pbLogging.LogLevel_INFO, nil},
{"Warn", LevelWarn, pbLogging.LogLevel_WARN, nil},
{"Error", LevelError, pbLogging.LogLevel_ERROR, nil},
{"Unknown", LevelUnknown, 100, fmt.Errorf("unknown log level UNKNOWN")},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := CreateLogLevelFromProto(tt.input)

if tt.err != nil {
if err == nil {
t.Errorf("Expected error, got nil")
}

} else {
if err != nil {
t.Errorf("Unexpected error: %v", err)
}

if result != tt.expected {
t.Errorf("Expected log level '%v', got '%v'", tt.expected, result)
}
}
})
}
}

func TestCreateLevelFromString(t *testing.T) {
tests := []struct {
name string
input string
expected LogLevel
err error
}{
{"Debug", "DEBUG", LevelDebug, nil},
{"Info", "INFO", LevelInfo, nil},
{"Warn", "WARN", LevelWarn, nil},
{"Error", "ERROR", LevelError, nil},
{"Unknown", "UNKNOWN", LevelUnknown, fmt.Errorf("unknown log level UNKNOWN")},
{"Empty", "", 0, errors.New("log level string is empty")},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := CreateLogLevelFromString(tt.input)

if tt.err != nil {
if err == nil {
t.Errorf("Expected error, got nil")
}

} else {
if err != nil {
t.Errorf("Unexpected error: %v", err)
}

if result != tt.expected {
t.Errorf("Expected log level '%v', got '%v'", tt.expected, result)
}
}
})
}
}

func TestLogLevel_String(t *testing.T) {
tests := []struct {
name string
input LogLevel
expected string
}{
{"Debug", LevelDebug, "DEBUG"},
{"Info", LevelInfo, "INFO"},
{"Warn", LevelWarn, "WARN"},
{"Error", LevelError, "ERROR"},
{"Unknown", LevelUnknown, "UNKNOWN"},
{"Unknown", LogLevel(100), "WARN"},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := tt.input.String()
if result != tt.expected {
t.Errorf("Expected '%s', got '%s'", tt.expected, result)
}
})
}
}
70 changes: 7 additions & 63 deletions packages/logging/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,33 +42,6 @@ type doguDescriptionGetter interface {
GetCurrent(ctx context.Context, simpleDoguName string) (*core.Dogu, error)
}

type LogLevel int

const (
LevelUnknown LogLevel = iota
LevelError
LevelWarn
LevelInfo
LevelDebug
)

func (l LogLevel) String() string {
switch l {
case LevelUnknown:
return "UNKNOWN"
case LevelDebug:
return "DEBUG"
case LevelInfo:
return "INFO"
case LevelWarn:
return "WARN"
case LevelError:
return "ERROR"
default:
return "WARN"
}
}

// NewLoggingService creates a new logging service.
func NewLoggingService(provider logProvider, cp configProvider, restarter doguRestarter, descriptionGetter doguDescriptionGetter) *loggingService {
return &loggingService{
Expand Down Expand Up @@ -150,7 +123,7 @@ func (s *loggingService) ApplyLogLevelWithRestart(ctx context.Context, req *pb.L
return nil, createInternalErrWithCtx(errMissingDoguName, codes.InvalidArgument)
}

lLevel, err := mapLogLevelFromProto(req.GetLogLevel())
lLevel, err := CreateLogLevelFromProto(req.GetLogLevel())
if err != nil {
return nil, createInternalErrWithCtx(fmt.Errorf("unable to map log level from proto message: %w", err), codes.InvalidArgument)
}
Expand All @@ -166,8 +139,7 @@ func (s *loggingService) ApplyLogLevelWithRestart(ctx context.Context, req *pb.L
return &emptypb.Empty{}, nil
}

// Decouple grpc-request context from RestartDogu context by creating a new context
if lErr := s.doguRestarter.RestartDogu(context.Background(), doguName); lErr != nil {
if lErr := s.doguRestarter.RestartDogu(context.WithoutCancel(ctx), doguName); lErr != nil {
return nil, createInternalErrWithCtx(fmt.Errorf("unable to restart dogu %s after setting new log level: %w", doguName, lErr), codes.Internal)
}

Expand Down Expand Up @@ -197,6 +169,10 @@ func (s *loggingService) setLogLevel(ctx context.Context, doguName string, l Log
return true, nil
}

// GetLogLevel provides the log level currently set for a specific dogu.
// For this the dogu config is checked as well as the dogu description as fall back.
// When there is no value set for the log level LevelUnknown is returned without an error.
// An error is only returned in case dogu config or dogu description cannot be read.
func (s *loggingService) GetLogLevel(ctx context.Context, doguName string) (LogLevel, error) {
dConfig := s.configProvider.DoguConfig(doguName)

Expand Down Expand Up @@ -225,7 +201,7 @@ func (s *loggingService) getLogLevel(ctx context.Context, doguName string, doguC

logrus.Debugf("current log level from dogu %s is %s", doguName, currentLogLevelStr)

currentLogLevel, err := mapLogLevelFromString(currentLogLevelStr)
currentLogLevel, err := CreateLogLevelFromString(currentLogLevelStr)
if err != nil {
logrus.Warnf("invalid log level set for dogu %s: %s", doguName, currentLogLevelStr)

Expand Down Expand Up @@ -262,38 +238,6 @@ func (s *loggingService) getDefaultLogLevel(ctx context.Context, doguName string
return defaultLevelStr, nil
}

func mapLogLevelFromProto(pLevel pb.LogLevel) (LogLevel, error) {
switch pLevel {
case pb.LogLevel_DEBUG:
return LevelDebug, nil
case pb.LogLevel_INFO:
return LevelInfo, nil
case pb.LogLevel_WARN:
return LevelWarn, nil
case pb.LogLevel_ERROR:
return LevelError, nil
default:
return LevelUnknown, fmt.Errorf("unknown log level: %v", pLevel)
}
}

func mapLogLevelFromString(sLevel string) (LogLevel, error) {
sLevelUpper := strings.ToUpper(sLevel)

switch sLevelUpper {
case LevelError.String():
return LevelError, nil
case LevelWarn.String():
return LevelWarn, nil
case LevelInfo.String():
return LevelInfo, nil
case LevelDebug.String():
return LevelDebug, nil
default:
return LevelUnknown, errors.New("unknown log level")
}
}

func (s *loggingService) writeLogLevel(_ context.Context, dConfig registry.ConfigurationContext, l LogLevel) error {
err := dConfig.Set(loggingKey, l.String())
if err != nil {
Expand Down

0 comments on commit a463649

Please sign in to comment.