-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 for v0.3 Release
- Loading branch information
Showing
17 changed files
with
1,302 additions
and
1,023 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// Copyright (c) Jeevanandam M (https://github.com/jeevatkm) | ||
// go-aah/log source code and usage is governed by a MIT style | ||
// license that can be found in the LICENSE file. | ||
|
||
package log | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"os" | ||
"runtime" | ||
"sync" | ||
|
||
"aahframework.org/config.v0" | ||
) | ||
|
||
var ( | ||
// ANSI color codes | ||
resetColor = []byte("\033[0m") | ||
levelToColor = [][]byte{ | ||
levelFatal: []byte("\033[0;31m"), // red | ||
levelPanic: []byte("\033[0;31m"), // red | ||
LevelError: []byte("\033[0;31m"), // red | ||
LevelWarn: []byte("\033[0;33m"), // yellow | ||
LevelInfo: []byte("\033[0;37m"), // white | ||
LevelDebug: []byte("\033[0;34m"), // blue | ||
LevelTrace: []byte("\033[0;35m"), // magenta (purple) | ||
} | ||
|
||
_ Receiver = &ConsoleReceiver{} | ||
) | ||
|
||
// ConsoleReceiver writes the log entry into os.Stderr. | ||
// For non-windows it writes with color. | ||
type ConsoleReceiver struct { | ||
rw *sync.RWMutex | ||
out io.Writer | ||
formatter string | ||
flags *[]FlagPart | ||
isCallerInfo bool | ||
isColor bool | ||
} | ||
|
||
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ | ||
// ConsoleReceiver methods | ||
//___________________________________ | ||
|
||
// Init method initializes the console logger. | ||
func (c *ConsoleReceiver) Init(cfg *config.Config) error { | ||
c.out = os.Stderr | ||
c.isColor = runtime.GOOS != "windows" | ||
|
||
c.formatter = cfg.StringDefault("log.format", "text") | ||
if !(c.formatter == textFmt || c.formatter == jsonFmt) { | ||
return fmt.Errorf("log: unsupported format '%s'", c.formatter) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// SetPattern method initializes the logger format pattern. | ||
func (c *ConsoleReceiver) SetPattern(pattern string) error { | ||
c.rw.Lock() | ||
defer c.rw.Unlock() | ||
flags, err := parseFlag(pattern) | ||
if err != nil { | ||
return err | ||
} | ||
c.flags = flags | ||
if c.formatter == textFmt { | ||
c.isCallerInfo = isCallerInfo(c.flags) | ||
} | ||
return nil | ||
} | ||
|
||
// IsCallerInfo method returns true if log receiver is configured with caller info | ||
// otherwise false. | ||
func (c *ConsoleReceiver) IsCallerInfo() bool { | ||
return c.isCallerInfo | ||
} | ||
|
||
// Log method writes the log entry into os.Stderr. | ||
func (c *ConsoleReceiver) Log(entry *Entry) { | ||
c.rw.RLock() | ||
defer c.rw.RUnlock() | ||
if c.isColor { | ||
_, _ = c.out.Write(levelToColor[entry.Level]) | ||
} | ||
|
||
msg := applyFormatter(c.formatter, c.flags, entry) | ||
if len(msg) == 0 || msg[len(msg)-1] != '\n' { | ||
msg = append(msg, '\n') | ||
} | ||
_, _ = c.out.Write(msg) | ||
|
||
if c.isColor { | ||
_, _ = c.out.Write(resetColor) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
// Copyright (c) Jeevanandam M (https://github.com/jeevatkm) | ||
// go-aah/log source code and usage is governed by a MIT style | ||
// license that can be found in the LICENSE file. | ||
|
||
package log | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"aahframework.org/config.v0" | ||
"aahframework.org/test.v0/assert" | ||
) | ||
|
||
func TestConsoleLoggerTextJSON(t *testing.T) { | ||
// Text 1 | ||
textConfigStr1 := ` | ||
log { | ||
receiver = "console" | ||
level = "debug" | ||
pattern = "%utctime:2006-01-02 15:04:05.000 %level:-5 %longfile %line %custom:- %message" | ||
} | ||
` | ||
testConsoleLogger(t, textConfigStr1) | ||
|
||
// Text 2 | ||
textConfigStr2 := ` | ||
log { | ||
receiver = "console" | ||
level = "debug" | ||
pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %shortfile %line %custom:- %message" | ||
} | ||
` | ||
testConsoleLogger(t, textConfigStr2) | ||
|
||
// JSON | ||
jsonConfigStr := ` | ||
log { | ||
receiver = "console" | ||
level = "debug" | ||
format = "json" | ||
} | ||
` | ||
testConsoleLogger(t, jsonConfigStr) | ||
} | ||
|
||
func TestConsoleLoggerUnsupportedFormat(t *testing.T) { | ||
configStr := ` | ||
log { | ||
# default config plus | ||
pattern = "%utctime:2006-01-02 15:04:05.000 %level:-5 %longfile %line %custom:- %message" | ||
format = "xml" | ||
} | ||
` | ||
cfg, _ := config.ParseString(configStr) | ||
logger, err := New(cfg) | ||
assert.Nil(t, logger) | ||
assert.Equal(t, "log: unsupported format 'xml'", err.Error()) | ||
} | ||
|
||
func TestConsoleLoggerUnknownFormatFlag(t *testing.T) { | ||
configStr := ` | ||
log { | ||
# default config plus | ||
pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %myfile %line %custom:- %message" | ||
} | ||
` | ||
cfg, _ := config.ParseString(configStr) | ||
logger, err := New(cfg) | ||
assert.Nil(t, logger) | ||
assert.Equal(t, "unrecognized log format flag: myfile", err.Error()) | ||
} | ||
|
||
func TestConsoleLoggerUnknownLevel(t *testing.T) { | ||
configStr := ` | ||
log { | ||
# default config plus | ||
level = "MYLEVEL" | ||
pattern = "%time:2006-01-02 15:04:05.000 %level:-5 %message" | ||
} | ||
` | ||
cfg, _ := config.ParseString(configStr) | ||
logger, err := New(cfg) | ||
assert.Nil(t, logger) | ||
assert.Equal(t, "log: unknown log level 'MYLEVEL'", err.Error()) | ||
} | ||
|
||
func TestConsoleLoggerDefaults(t *testing.T) { | ||
configStr := ` | ||
log { | ||
# default config | ||
} | ||
` | ||
cfg, _ := config.ParseString(configStr) | ||
logger, err := New(cfg) | ||
assert.NotNil(t, logger) | ||
assert.Nil(t, err) | ||
|
||
// receiver nil scenario | ||
logger.receiver = nil | ||
err = logger.SetPattern("%time:2006-01-02 15:04:05.000 %level:-5 %message") | ||
assert.Equal(t, "log: receiver is nil", err.Error()) | ||
} | ||
|
||
func testConsoleLogger(t *testing.T, cfgStr string) { | ||
cfg, _ := config.ParseString(cfgStr) | ||
logger, err := New(cfg) | ||
assert.FailNowOnError(t, err, "unexpected error") | ||
|
||
logger.Trace("I shoudn't see this msg, because standard logger level is DEBUG") | ||
logger.Tracef("I shoudn't see this msg, because standard logger level is DEBUG: %v", 4) | ||
|
||
logger.Debug("I would like to see this message, debug is useful for dev") | ||
logger.Debugf("I would like to see this message, debug is useful for %v", "dev") | ||
|
||
logger.Info("Yes, I would love to see") | ||
logger.Infof("Yes, I would love to %v", "see") | ||
|
||
logger.Warn("Yes, yes it's an warning") | ||
logger.Warnf("Yes, yes it's an %v", "warning") | ||
|
||
logger.Error("Yes, yes, yes - finally an error") | ||
logger.Errorf("Yes, yes, yes - %v", "finally an error") | ||
|
||
time.Sleep(1 * time.Millisecond) | ||
} |
Oops, something went wrong.