diff --git a/cmd/logmania/main.go b/cmd/logmania/main.go index 2abaf68..074f0a4 100644 --- a/cmd/logmania/main.go +++ b/cmd/logmania/main.go @@ -49,7 +49,7 @@ func main() { } database.Connect(config.Database.Type, config.Database.Connect) - log.AddLogger(logger) + log.AddLogger("selflogger", logger) api = &lib.HTTPServer{ Addr: config.API.Bind, diff --git a/log/hook/client/main.go b/log/hook/client/main.go index c4f3e20..cdd611b 100644 --- a/log/hook/client/main.go +++ b/log/hook/client/main.go @@ -14,9 +14,10 @@ type Logger struct { log.Logger AboveLevel log.LogLevel conn *websocket.Conn - closed bool } +const LOGGER_NAME = "client" + // CurrentLogger (for override settings e.g. AboveLevel) var CurrentLogger *Logger @@ -40,9 +41,6 @@ func NewLogger(url, token string, AboveLevel log.LogLevel) *Logger { // handle a log entry (send to logmania server) func (l *Logger) Hook(e *log.Entry) { - if l.closed { - return - } if e.Level < l.AboveLevel { return } @@ -58,8 +56,8 @@ func (l *Logger) Listen() { for { msgType, _, err := l.conn.ReadMessage() if msgType == -1 { - l.closed = true l.conn.Close() + l.Close() return } if err != nil { @@ -71,13 +69,13 @@ func (l *Logger) Listen() { // close connection to logger func (l *Logger) Close() { l.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) - l.closed = true + log.RemoveLogger(LOGGER_NAME) } // init logmania's client logger and bind func Init(url, token string, AboveLevel log.LogLevel) *Logger { CurrentLogger = NewLogger(url, token, AboveLevel) go CurrentLogger.Listen() - log.AddLogger(CurrentLogger) + log.AddLogger(LOGGER_NAME, CurrentLogger) return CurrentLogger } diff --git a/log/hook/output/main.go b/log/hook/output/main.go index 494416d..80edf12 100644 --- a/log/hook/output/main.go +++ b/log/hook/output/main.go @@ -88,5 +88,5 @@ func (l *Logger) Close() { func init() { CurrentLogger = NewLogger() - log.AddLogger(CurrentLogger) + log.AddLogger("output", CurrentLogger) } diff --git a/log/init.go b/log/init.go index 2358e40..c8d2b2c 100644 --- a/log/init.go +++ b/log/init.go @@ -27,6 +27,9 @@ func HTTP(r *http.Request) *Entry { // init log entry with extra fields of interesting websocket request context func WebsocketX(ws *websocket.Conn) *Entry { r := ws.Request() + if r == nil { + return New().AddField("websocket", true) + } return New().AddFields(map[string]interface{}{ "remote": getIP(r), "websocket": true, diff --git a/log/init_test.go b/log/init_test.go new file mode 100644 index 0000000..d7339a5 --- /dev/null +++ b/log/init_test.go @@ -0,0 +1,43 @@ +package log + +import ( + "net/http" + "testing" + + "golang.org/x/net/websocket" + + "github.com/stretchr/testify/assert" +) + +func TestGetIP(t *testing.T) { + assert := assert.New(t) + + req, _ := http.NewRequest("GET", "https://google.com/lola/duda?q=wasd", nil) + req.RemoteAddr = "127.0.0.1" + assert.Equal("127.0.0.1", getIP(req)) + req.Header.Set("X-Forwarded-For", "8.8.8.8") + assert.Equal("8.8.8.8", getIP(req)) + +} + +func TestHTTP(t *testing.T) { + assert := assert.New(t) + + req, _ := http.NewRequest("GET", "https://google.com/lola/duda?q=wasd", nil) + entry := HTTP(req) + _, ok := entry.Fields["remote"] + + assert.NotNil(ok, "remote address not set in logger") + assert.Equal("GET", entry.Fields["method"], "method not set in logger") + assert.Equal("/lola/duda?q=wasd", entry.Fields["url"], "path not set in logger") +} + +func TestWebsocketX(t *testing.T) { + assert := assert.New(t) + ws := &websocket.Conn{} + entry := WebsocketX(ws) + _, ok := entry.Fields["remote"] + + assert.NotNil(ok, "remote address not set in logger") + assert.True(entry.Fields["websocket"].(bool)) +} diff --git a/log/level_test.go b/log/level_test.go new file mode 100644 index 0000000..be15444 --- /dev/null +++ b/log/level_test.go @@ -0,0 +1,105 @@ +package log + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestString(t *testing.T) { + assert := assert.New(t) + + results := map[LogLevel]string{ + DebugLevel: "Debug", + InfoLevel: "Info", + WarnLevel: "Warn", + ErrorLevel: "ERROR", + PanicLevel: "PANIC", + LogLevel(-2): "NOT VALID", + } + + for value, expected := range results { + assert.Equal(expected, value.String()) + } +} + +func TestLogLevelFunc(t *testing.T) { + assert := assert.New(t) + + results := map[LogLevel]func(...interface{}){ + DebugLevel: entry.Debug, + InfoLevel: entry.Info, + WarnLevel: entry.Warn, + ErrorLevel: entry.Error, + } + + for value, function := range results { + function() + assert.Equal(value, entry.Level) + } + assert.Panics(func() { + entry.Panic() + assert.Equal(PanicLevel, entry.Level) + }) +} +func TestLogLevelFormatFunc(t *testing.T) { + assert := assert.New(t) + + results := map[LogLevel]func(string, ...interface{}){ + DebugLevel: entry.Debugf, + InfoLevel: entry.Infof, + WarnLevel: entry.Warnf, + ErrorLevel: entry.Errorf, + } + + for value, function := range results { + function("%.1f", 31.121) + assert.Equal(value, entry.Level) + assert.Equal("31.1", entry.Text) + } + assert.Panics(func() { + entry.Panicf("") + assert.Equal(PanicLevel, entry.Level) + }) +} + +func TestLogLevelInit(t *testing.T) { + assert := assert.New(t) + + results := map[LogLevel]func(...interface{}){ + DebugLevel: Debug, + InfoLevel: Info, + WarnLevel: Warn, + ErrorLevel: Error, + } + + for value, function := range results { + function() + assert.Equal(value, entry.Level) + } + assert.Panics(func() { + Panic() + assert.Equal(PanicLevel, entry.Level) + }) +} + +func TestLogLevelInitFormatFunc(t *testing.T) { + assert := assert.New(t) + + results := map[LogLevel]func(string, ...interface{}){ + DebugLevel: Debugf, + InfoLevel: Infof, + WarnLevel: Warnf, + ErrorLevel: Errorf, + } + + for value, function := range results { + function("%.1f", 31.121) + assert.Equal(value, entry.Level) + assert.Equal("31.1", entry.Text) + } + assert.Panics(func() { + Panicf("") + assert.Equal(PanicLevel, entry.Level) + }) +} diff --git a/log/logger.go b/log/logger.go index e5609bc..f02b103 100644 --- a/log/logger.go +++ b/log/logger.go @@ -6,11 +6,14 @@ type Logger interface { Close() } -var loggers = make([]Logger, 0) +var loggers = make(map[string]Logger) // bind logger to handle saving/output of a Log entry -func AddLogger(logger Logger) { - loggers = append(loggers, logger) +func AddLogger(name string, logger Logger) { + loggers[name] = logger +} +func RemoveLogger(name string) { + delete(loggers, name) } func save(e *Entry) { diff --git a/log/logger_test.go b/log/logger_test.go new file mode 100644 index 0000000..3151fa6 --- /dev/null +++ b/log/logger_test.go @@ -0,0 +1,37 @@ +package log + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +var entry *Entry + +type SaveLogger struct { + Logger +} + +func (*SaveLogger) Hook(e *Entry) { + entry = e +} +func (*SaveLogger) Close() {} + +func init() { + entry = &Entry{} + AddLogger("name", &SaveLogger{}) +} + +func TestLogger(t *testing.T) { + assert := assert.New(t) + assert.Len(loggers, 1) + + AddLogger("blub", &SaveLogger{}) + assert.Len(loggers, 2) + RemoveLogger("blub") + assert.Len(loggers, 1) + + assert.PanicsWithValue("panic see last log in logmania", func() { + save(&Entry{Level: PanicLevel}) + }) +} diff --git a/log/main_test.go b/log/main_test.go index 7330d54..75b2829 100644 --- a/log/main_test.go +++ b/log/main_test.go @@ -1 +1,46 @@ package log + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestLog(t *testing.T) { + assert := assert.New(t) + //save := func(e *Entry) {} + entry := New() + assert.Equal(0, int(entry.Level)) + assert.Equal("", entry.Text) + + entry.Log(WarnLevel, "blub") + assert.Equal(1, int(entry.Level)) + assert.Equal("blub", entry.Text) + + entry.Logf(ErrorLevel, "lola %.1f", 13.13431) + assert.Equal(2, int(entry.Level)) + assert.Equal("lola 13.1", entry.Text) +} + +func TestAddFields(t *testing.T) { + assert := assert.New(t) + entry := New() + assert.Len(entry.Fields, 0) + + entry.AddField("a", "lola") + assert.Len(entry.Fields, 1) + assert.Equal("lola", entry.Fields["a"]) + + entry.AddFields(map[string]interface{}{"a": 232., "foo": "bar"}) + assert.Len(entry.Fields, 2) + assert.Equal(232.0, entry.Fields["a"]) +} + +func TestFieldString(t *testing.T) { + assert := assert.New(t) + entry := New() + entry.AddFields(map[string]interface{}{"a": 232., "foo": "bar"}) + str := entry.FieldString() + assert.Contains(str, "a=232") + assert.Contains(str, "foo=bar") +}