Logger: Add support for toggling sub logger name output for log events (#407)

* Adds new optional log field. Adds padding to the fields to make it have a consistent output

* Line space and correct err message

* Removes padding code

* Moves `ShowLogSystemName` to advanced settings

* Uppers the names. Prevents pointer crash. Adds to config_example.json

* Adds test scenario for nil and true ShowLogSystemName

* buffer reset
This commit is contained in:
Scott
2020-01-03 03:12:23 +00:00
committed by Adrian Gallagher
parent 98a277a4c3
commit f8ef6da93d
8 changed files with 93 additions and 53 deletions

View File

@@ -1189,6 +1189,10 @@ func (c *Config) CheckLoggerConfig() error {
f := func(f bool) *bool { return &f }(false)
if c.Logging.AdvancedSettings.ShowLogSystemName == nil {
c.Logging.AdvancedSettings.ShowLogSystemName = f
}
if c.Logging.LoggerFileConfig != nil {
if c.Logging.LoggerFileConfig.FileName == "" {
c.Logging.LoggerFileConfig.FileName = "log.txt"

View File

@@ -1732,6 +1732,7 @@ func TestCheckLoggerConfig(t *testing.T) {
c.Logging.LoggerFileConfig.FileName = ""
c.Logging.LoggerFileConfig.Rotate = nil
c.Logging.LoggerFileConfig.MaxSize = -1
c.Logging.AdvancedSettings.ShowLogSystemName = nil
err = c.CheckLoggerConfig()
if err != nil {
@@ -1740,11 +1741,16 @@ func TestCheckLoggerConfig(t *testing.T) {
if c.Logging.LoggerFileConfig.FileName != "log.txt" ||
c.Logging.LoggerFileConfig.Rotate == nil ||
c.Logging.LoggerFileConfig.MaxSize != 100 {
c.Logging.LoggerFileConfig.MaxSize != 100 ||
c.Logging.AdvancedSettings.ShowLogSystemName == nil ||
*c.Logging.AdvancedSettings.ShowLogSystemName {
t.Error("unexpected result")
}
c.LoadConfig(TestFile, true)
err = c.LoadConfig(TestFile, true)
if err != nil {
t.Errorf("Failed to load config: %v", err)
}
err = c.CheckLoggerConfig()
if err != nil {
t.Errorf("Failed to create logger with user settings: reason: %v", err)

View File

@@ -25,6 +25,7 @@
"maxsize": 250
},
"advancedSettings": {
"showLogSystemName": false,
"spacer": " | ",
"timeStampFormat": "02/01/2006 15:04:05",
"headers": {

View File

@@ -9,16 +9,17 @@ import (
func newLogger(c *Config) *Logger {
return &Logger{
Timestamp: c.AdvancedSettings.TimeStampFormat,
Spacer: c.AdvancedSettings.Spacer,
ErrorHeader: c.AdvancedSettings.Headers.Error,
InfoHeader: c.AdvancedSettings.Headers.Info,
WarnHeader: c.AdvancedSettings.Headers.Warn,
DebugHeader: c.AdvancedSettings.Headers.Debug,
Timestamp: c.AdvancedSettings.TimeStampFormat,
Spacer: c.AdvancedSettings.Spacer,
ErrorHeader: c.AdvancedSettings.Headers.Error,
InfoHeader: c.AdvancedSettings.Headers.Info,
WarnHeader: c.AdvancedSettings.Headers.Warn,
DebugHeader: c.AdvancedSettings.Headers.Debug,
ShowLogSystemName: *c.AdvancedSettings.ShowLogSystemName,
}
}
func (l *Logger) newLogEvent(data, header string, w io.Writer) error {
func (l *Logger) newLogEvent(data, header, slName string, w io.Writer) error {
if w == nil {
return errors.New("io.Writer not set")
}
@@ -26,6 +27,10 @@ func (l *Logger) newLogEvent(data, header string, w io.Writer) error {
e := eventPool.Get().(*LogEvent)
e.output = w
e.data = append(e.data, []byte(header)...)
if l.ShowLogSystemName {
e.data = append(e.data, l.Spacer...)
e.data = append(e.data, slName...)
}
e.data = append(e.data, l.Spacer...)
if l.Timestamp != "" {
e.data = time.Now().AppendFormat(e.data, l.Timestamp)

View File

@@ -47,8 +47,9 @@ func GenDefaultSettings() (log Config) {
MaxSize: 0,
},
AdvancedSettings: advancedSettings{
Spacer: " | ",
TimeStampFormat: timestampFormat,
ShowLogSystemName: f,
Spacer: " | ",
TimeStampFormat: timestampFormat,
Headers: headers{
Info: "[INFO]",
Warn: "[WARN]",
@@ -78,7 +79,7 @@ func configureSubLogger(logger, levels string, output io.Writer) error {
func SetupSubLoggers(s []SubLoggerConfig) {
for x := range s {
output := getWriters(&s[x])
err := configureSubLogger(s[x].Name, s[x].Level, output)
err := configureSubLogger(strings.ToUpper(s[x].Name), s[x].Level, output)
if err != nil {
continue
}
@@ -122,7 +123,7 @@ func splitLevel(level string) (l Levels) {
func registerNewSubLogger(logger string) *subLogger {
temp := subLogger{
name: logger,
name: strings.ToUpper(logger),
output: os.Stdout,
}
@@ -134,24 +135,24 @@ func registerNewSubLogger(logger string) *subLogger {
// register all loggers at package init()
func init() {
Global = registerNewSubLogger("log")
Global = registerNewSubLogger("LOG")
ConnectionMgr = registerNewSubLogger("connection")
CommunicationMgr = registerNewSubLogger("comms")
ConfigMgr = registerNewSubLogger("config")
DatabaseMgr = registerNewSubLogger("database")
OrderMgr = registerNewSubLogger("order")
PortfolioMgr = registerNewSubLogger("portfolio")
SyncMgr = registerNewSubLogger("sync")
TimeMgr = registerNewSubLogger("timekeeper")
WebsocketMgr = registerNewSubLogger("websocket")
EventMgr = registerNewSubLogger("event")
DispatchMgr = registerNewSubLogger("dispatch")
ConnectionMgr = registerNewSubLogger("CONNECTION")
CommunicationMgr = registerNewSubLogger("COMMS")
ConfigMgr = registerNewSubLogger("CONFIG")
DatabaseMgr = registerNewSubLogger("DATABASE")
OrderMgr = registerNewSubLogger("ORDER")
PortfolioMgr = registerNewSubLogger("PORTFOLIO")
SyncMgr = registerNewSubLogger("SYNC")
TimeMgr = registerNewSubLogger("TIMEKEEPER")
WebsocketMgr = registerNewSubLogger("WEBSOCKET")
EventMgr = registerNewSubLogger("EVENT")
DispatchMgr = registerNewSubLogger("DISPATCH")
ExchangeSys = registerNewSubLogger("exchange")
GRPCSys = registerNewSubLogger("grpc")
RESTSys = registerNewSubLogger("rest")
ExchangeSys = registerNewSubLogger("EXCHANGE")
GRPCSys = registerNewSubLogger("GRPC")
RESTSys = registerNewSubLogger("REST")
Ticker = registerNewSubLogger("ticker")
OrderBook = registerNewSubLogger("orderbook")
Ticker = registerNewSubLogger("TICKER")
OrderBook = registerNewSubLogger("ORDERBOOK")
}

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"io/ioutil"
"os"
"strings"
"testing"
)
@@ -20,8 +21,9 @@ func SetupTest() {
Level: "INFO|WARN|DEBUG|ERROR",
},
AdvancedSettings: advancedSettings{
Spacer: " | ",
TimeStampFormat: timestampFormat,
ShowLogSystemName: trueptr,
Spacer: " | ",
TimeStampFormat: timestampFormat,
Headers: headers{
Info: "[INFO]",
Warn: "[WARN]",
@@ -31,7 +33,7 @@ func SetupTest() {
},
SubLoggers: []SubLoggerConfig{
{
Name: "test",
Name: "TEST",
Level: "INFO|DEBUG|WARN|ERROR",
Output: "stdout",
}},
@@ -101,9 +103,9 @@ func TestRemoveWriter(t *testing.T) {
func TestLevel(t *testing.T) {
SetupTest()
_, err := Level("log")
_, err := Level("LOG")
if err != nil {
t.Errorf("Failed to get log %s levels skippin", err)
t.Errorf("Failed to get log %s levels skipping", err)
}
_, err = Level("totallyinvalidlogger")
@@ -115,7 +117,7 @@ func TestLevel(t *testing.T) {
func TestSetLevel(t *testing.T) {
SetupTest()
newLevel, err := SetLevel("log", "ERROR")
newLevel, err := SetLevel("LOG", "ERROR")
if err != nil {
t.Skipf("Failed to get log %s levels skipping", err)
}
@@ -135,7 +137,7 @@ func TestSetLevel(t *testing.T) {
}
func TestValidSubLogger(t *testing.T) {
b, logPtr := validSubLogger("log")
b, logPtr := validSubLogger("LOG")
if !b {
t.Skip("validSubLogger() should return found, pointer if valid logger found")
@@ -163,6 +165,9 @@ func TestConfigureSubLogger(t *testing.T) {
}) {
t.Error("configureSubLogger() incorrectly configure subLogger")
}
if Global.name != "LOG" {
t.Error("configureSubLogger() Failed to uppercase name")
}
}
func TestSplitLevel(t *testing.T) {
@@ -209,13 +214,13 @@ func BenchmarkInfoln(b *testing.B) {
func TestNewLogEvent(t *testing.T) {
w := &bytes.Buffer{}
logger.newLogEvent("out", "header", w)
logger.newLogEvent("out", "header", "SUBLOGGER", w)
if w.String() == "" {
t.Error("newLogEvent() failed expected output got empty string")
}
err := logger.newLogEvent("out", "header", nil)
err := logger.newLogEvent("out", "header", "SUBLOGGER", nil)
if err == nil {
t.Error("Error expected with output is set to nil")
}
@@ -225,7 +230,7 @@ func TestInfo(t *testing.T) {
w := &bytes.Buffer{}
tempSL := subLogger{
"testymctestalot",
"TESTYMCTESTALOT",
splitLevel("INFO|WARN|DEBUG|ERROR"),
w,
}
@@ -239,10 +244,27 @@ func TestInfo(t *testing.T) {
tempSL.output = nil
w.Reset()
SetLevel("testymctestalot", "INFO")
SetLevel("TESTYMCTESTALOT", "INFO")
Debug(&tempSL, "HelloHello")
if w.String() != "" {
t.Error("Expected output buffer to be empty but Debug wrote to output")
}
}
func TestSubLoggerName(t *testing.T) {
SetupTest()
w := &bytes.Buffer{}
registerNewSubLogger("sublogger")
logger.newLogEvent("out", "header", "SUBLOGGER", w)
if !strings.Contains(w.String(), "SUBLOGGER") {
t.Error("Expected SUBLOGGER in output")
}
logger.ShowLogSystemName = false
w.Reset()
logger.newLogEvent("out", "header", "SUBLOGGER", w)
if strings.Contains(w.String(), "SUBLOGGER") {
t.Error("Unexpected SUBLOGGER in output")
}
}

View File

@@ -7,7 +7,6 @@ import (
const (
timestampFormat = " 02/01/2006 15:04:05 "
spacer = "|"
)
var (
@@ -41,9 +40,10 @@ type Config struct {
}
type advancedSettings struct {
Spacer string `json:"spacer"`
TimeStampFormat string `json:"timeStampFormat"`
Headers headers `json:"headers"`
ShowLogSystemName *bool `json:"showLogSystemName"`
Spacer string `json:"spacer"`
TimeStampFormat string `json:"timeStampFormat"`
Headers headers `json:"headers"`
}
type headers struct {
@@ -68,6 +68,7 @@ type loggerFileConfig struct {
// Logger each instance of logger settings
type Logger struct {
ShowLogSystemName bool
Timestamp string
InfoHeader, ErrorHeader, DebugHeader, WarnHeader string
Spacer string

View File

@@ -15,7 +15,7 @@ func Info(sl *subLogger, data string) {
return
}
displayError(logger.newLogEvent(data, logger.InfoHeader, sl.output))
displayError(logger.newLogEvent(data, logger.InfoHeader, sl.name, sl.output))
}
// Infoln takes a pointer subLogger struct and interface sends to newLogEvent
@@ -28,7 +28,7 @@ func Infoln(sl *subLogger, v ...interface{}) {
return
}
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.InfoHeader, sl.output))
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.InfoHeader, sl.name, sl.output))
}
// Infof takes a pointer subLogger struct, string & interface formats and sends to Info()
@@ -54,7 +54,7 @@ func Debug(sl *subLogger, data string) {
return
}
displayError(logger.newLogEvent(data, logger.DebugHeader, sl.output))
displayError(logger.newLogEvent(data, logger.DebugHeader, sl.name, sl.output))
}
// Debugln takes a pointer subLogger struct, string and interface sends to newLogEvent
@@ -67,7 +67,7 @@ func Debugln(sl *subLogger, v ...interface{}) {
return
}
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.DebugHeader, sl.output))
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.DebugHeader, sl.name, sl.output))
}
// Debugf takes a pointer subLogger struct, string & interface formats and sends to Info()
@@ -93,7 +93,7 @@ func Warn(sl *subLogger, data string) {
return
}
displayError(logger.newLogEvent(data, logger.WarnHeader, sl.output))
displayError(logger.newLogEvent(data, logger.WarnHeader, sl.name, sl.output))
}
// Warnln takes a pointer subLogger struct & interface formats and sends to newLogEvent()
@@ -106,7 +106,7 @@ func Warnln(sl *subLogger, v ...interface{}) {
return
}
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.WarnHeader, sl.output))
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.WarnHeader, sl.name, sl.output))
}
// Warnf takes a pointer subLogger struct, string & interface formats and sends to Warn()
@@ -132,7 +132,7 @@ func Error(sl *subLogger, data ...interface{}) {
return
}
displayError(logger.newLogEvent(fmt.Sprint(data...), logger.ErrorHeader, sl.output))
displayError(logger.newLogEvent(fmt.Sprint(data...), logger.ErrorHeader, sl.name, sl.output))
}
// Errorln takes a pointer subLogger struct, string & interface formats and sends to newLogEvent()
@@ -145,7 +145,7 @@ func Errorln(sl *subLogger, v ...interface{}) {
return
}
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.ErrorHeader, sl.output))
displayError(logger.newLogEvent(fmt.Sprintln(v...), logger.ErrorHeader, sl.name, sl.output))
}
// Errorf takes a pointer subLogger struct, string & interface formats and sends to Debug()