Skip to content

Commit

Permalink
Merge pull request #10 from infrawatch/pleimer-console-logging
Browse files Browse the repository at this point in the history
Add console logging option
  • Loading branch information
paramite authored Sep 10, 2020
2 parents 32be300 + 32bf366 commit f4da925
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 37 deletions.
137 changes: 100 additions & 37 deletions logging/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import (
"bytes"
"fmt"
"os"
"strings"
"time"
)

// LogLevel defines log levels
type LogLevel int

const (
Expand All @@ -16,62 +18,119 @@ const (
ERROR
)

func (self LogLevel) String() string {
return [...]string{"DEBUG", "INFO", "WARN", "ERROR"}[self]
func (l LogLevel) String() string {
return [...]string{"DEBUG", "INFO", "WARN", "ERROR"}[l]
}

type writeFn func(string) error

// Logger implements a simple logger with 4 levels
type Logger struct {
Level LogLevel
Timestamp bool
metadata map[string]interface{}
logfile *os.File
write writeFn
}

func NewLogger(level LogLevel, path string) (*Logger, error) {
// NewLogger logger factory
func NewLogger(level LogLevel, target string) (*Logger, error) {
var logger Logger
logger.Level = level
logger.Timestamp = false
logger.metadata = make(map[string]interface{})

logfile, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return nil, err
switch strings.ToLower(target) {
case "console":
logger.write = func(message string) error {
fmt.Print(message)
return nil
}
break
default:
var err error
if logger.logfile == nil {
logger.logfile, err = os.OpenFile(target, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
return nil, err
}
}
logger.write = func(message string) error {
_, err := logger.logfile.WriteString(message)
return err
}
}
logger.logfile = logfile

return &logger, nil
}

func (self *Logger) Destroy() error {
return self.logfile.Close()
// Destroy cleanup resources
func (l *Logger) Destroy() error {
if l.logfile != nil {
return l.logfile.Close()
}
return nil
}

// Metadata set metadata to include in message
func (l *Logger) Metadata(metadata map[string]interface{}) {
l.metadata = metadata
}

func (self *Logger) Metadata(metadata map[string]interface{}) {
self.metadata = metadata
// SetLogLevel ..
func (l *Logger) SetLogLevel(level LogLevel) {
l.Level = level
}

func(self *Logger) SetLogLevel(level LogLevel) {
self.Level = level
// SetConsole sets logger target to console
func (l *Logger) SetConsole() {
if l.logfile != nil {
err := l.logfile.Close()
if err != nil {
l.Warn("Failed to close old log file")
}
l.logfile = nil
}

l.write = func(message string) error {
fmt.Print(message)
return nil
}
}

func(self *Logger) SetFile(path string, permissions os.FileMode) error {
// SetFile sets logfile. If logger target was console, switch to file mode
func (l *Logger) SetFile(path string, permissions os.FileMode) error {
newLogfile, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, permissions)
if err != nil {
self.Warn("Couldn't open new log file, leaving the old one")
l.Warn("Couldn't open new log file, leaving the old one")
return err
}

if l.logfile != nil {
err = l.logfile.Close()
if err != nil {
l.Warn("Failed to close old log file")
}
l.logfile = newLogfile
return nil
}

//target was console
l.logfile = newLogfile
l.write = func(message string) error {
_, err := l.logfile.WriteString(message)
return err
}
self.logfile.Close()
self.logfile = newLogfile
return nil
}

func (self *Logger) formatMetadata() (string, error) {
func (l *Logger) formatMetadata() (string, error) {
//var build strings.Builder
// Note: we need to support go-1.9.2 because of CentOS7
var build bytes.Buffer
if len(self.metadata) > 0 {
if len(l.metadata) > 0 {
joiner := ""
for key, item := range self.metadata {
for key, item := range l.metadata {
_, err := fmt.Fprintf(&build, "%s%s: %v", joiner, key, item)
if err != nil {
return build.String(), err
Expand All @@ -82,20 +141,20 @@ func (self *Logger) formatMetadata() (string, error) {
}
}
// clear metadata for next use
self.metadata = make(map[string]interface{})
l.metadata = make(map[string]interface{})
return build.String(), nil
}

func (self *Logger) writeRecord(level LogLevel, message string) error {
metadata, err := self.formatMetadata()
func (l *Logger) writeRecord(level LogLevel, message string) error {
metadata, err := l.formatMetadata()
if err != nil {
return err
}

//var build strings.Builder
// Note: we need to support go-1.9.2 because of CentOS7
var build bytes.Buffer
if self.Timestamp {
if l.Timestamp {
_, err = build.WriteString(time.Now().Format("2006-01-02 15:04:05 "))
}

Expand All @@ -117,34 +176,38 @@ func (self *Logger) writeRecord(level LogLevel, message string) error {
if err != nil {
return nil
}
_, err = self.logfile.WriteString(build.String())
err = l.write(build.String())
return err
}

func (self *Logger) Debug(message string) error {
if self.Level == DEBUG {
return self.writeRecord(DEBUG, message)
// Debug level debug
func (l *Logger) Debug(message string) error {
if l.Level == DEBUG {
return l.writeRecord(DEBUG, message)
}
return nil
}

func (self *Logger) Info(message string) error {
if self.Level <= INFO {
return self.writeRecord(INFO, message)
// Info level info
func (l *Logger) Info(message string) error {
if l.Level <= INFO {
return l.writeRecord(INFO, message)
}
return nil
}

func (self *Logger) Warn(message string) error {
if self.Level <= WARN {
return self.writeRecord(WARN, message)
// Warn level warn
func (l *Logger) Warn(message string) error {
if l.Level <= WARN {
return l.writeRecord(WARN, message)
}
return nil
}

func (self *Logger) Error(message string) error {
if self.Level <= ERROR {
return self.writeRecord(ERROR, message)
// Error level error
func (l *Logger) Error(message string) error {
if l.Level <= ERROR {
return l.writeRecord(ERROR, message)
}
return nil
}
14 changes: 14 additions & 0 deletions tests/logging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,20 @@ func TestLogger(t *testing.T) {
assert.Equal(t, "[ERROR] Test error 4\n", actual)
})

t.Run("Test SetConsole", func(t *testing.T) {
log.Level = logging.INFO
testStr := "should not be in logfile"
log.SetConsole()

lastInFile1, err := getLastLineWithSeek(logpath)
if err != nil {
t.Fatalf("Failed to fetch last line in log file: %s", err)
}

log.Info(testStr)
assert.NotEqual(t, lastInFile1, testStr)
})

t.Run("Test SetFile", func(t *testing.T) {
log.Level = logging.ERROR

Expand Down

0 comments on commit f4da925

Please sign in to comment.