[TASK] improve log with hook
This commit is contained in:
parent
a096771e20
commit
102cf0004f
|
@ -0,0 +1,57 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/genofire/logmania/lib"
|
||||
"github.com/genofire/logmania/log"
|
||||
_ "github.com/genofire/logmania/log/hook/output"
|
||||
)
|
||||
|
||||
var (
|
||||
configPath string
|
||||
config *lib.Config
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&configPath, "config", "logmania.conf", "config file")
|
||||
log.Info("starting logmania")
|
||||
config, err := lib.ReadConfig(configPath)
|
||||
if config == nil || err != nil {
|
||||
log.Panicf("Could not load '%s' for configuration.", configPath)
|
||||
}
|
||||
|
||||
// Wait for system signal
|
||||
sigchan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigchan, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGUSR1)
|
||||
for sig := range sigchan {
|
||||
switch sig {
|
||||
case syscall.SIGTERM:
|
||||
log.Warn("terminated of logmania")
|
||||
os.Exit(0)
|
||||
case syscall.SIGQUIT:
|
||||
quit()
|
||||
case syscall.SIGHUP:
|
||||
quit()
|
||||
case syscall.SIGUSR1:
|
||||
reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func quit() {
|
||||
log.Info("quit of logmania")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func reload() {
|
||||
log.Info("reload config file")
|
||||
config, err := lib.ReadConfig(configPath)
|
||||
if config == nil || err != nil {
|
||||
log.Errorf("Could not load '%s' for new configuration. Skip reload.", configPath)
|
||||
return
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package entry
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
var TimeFormat = "2006-01-02 15:04:05"
|
||||
|
||||
var InternelSend = func(e *Entry) {
|
||||
format := "%s [%s] %s\n"
|
||||
v := []interface{}{time.Now().Format(TimeFormat), e.Level.String(), e.Text}
|
||||
if len(e.Fields) > 0 {
|
||||
format = "%s [%s] %s (%s)\n"
|
||||
v = append(v, e.FieldString())
|
||||
}
|
||||
text := fmt.Sprintf(format, v...)
|
||||
|
||||
if e.Level == PanicLevel {
|
||||
panic(text)
|
||||
} else if e.Level > WarnLevel {
|
||||
os.Stderr.WriteString(text)
|
||||
} else {
|
||||
os.Stdout.WriteString(text)
|
||||
}
|
||||
}
|
||||
|
||||
var FieldOutput = func(fields map[string]interface{}) string {
|
||||
text := ""
|
||||
for key, value := range fields {
|
||||
text = fmt.Sprintf("%s %s=%v", text, key, value)
|
||||
}
|
||||
return text[1:]
|
||||
}
|
||||
|
||||
func save(e *Entry) {
|
||||
InternelSend(e)
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/genofire/logmania/log"
|
||||
logClient "github.com/genofire/logmania/log/hook/client"
|
||||
logOutput "github.com/genofire/logmania/log/hook/output"
|
||||
)
|
||||
|
||||
func main() {
|
||||
logClient.Init("ws://localhost:8081/blub", "example")
|
||||
log.Info("startup")
|
||||
log.New().AddField("answer", 42).AddFields(map[string]interface{}{"answer": 3, "foo": "bar"}).Warn("Some spezial")
|
||||
log.Debug("Never shown up")
|
||||
logOutput.ShowTime = false
|
||||
logOutput.AboveLevel = log.DebugLevel
|
||||
log.Debugf("Startup %v", time.Now())
|
||||
logOutput.ShowTime = true
|
||||
log.Panic("let it crash")
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/genofire/logmania/log"
|
||||
logOutput "github.com/genofire/logmania/log/hook/output"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.Info("startup")
|
||||
log.New().AddField("answer", 42).AddFields(map[string]interface{}{"answer": 3, "foo": "bar"}).Warn("Some spezial")
|
||||
log.Debug("Never shown up")
|
||||
logOutput.ShowTime = false
|
||||
logOutput.AboveLevel = log.DebugLevel
|
||||
log.Debugf("Startup %v", time.Now())
|
||||
logOutput.ShowTime = true
|
||||
log.Panic("let it crash")
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package lib
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/genofire/logmania/log"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
API struct {
|
||||
Bind string `toml:"bind"`
|
||||
Interactive bool `toml:"interactive"`
|
||||
} `toml:"api"`
|
||||
Database struct {
|
||||
Type string `toml:"type"`
|
||||
Connect string `toml:"connect"`
|
||||
} `toml:"database"`
|
||||
Webserver struct {
|
||||
Enable bool `toml:"enable"`
|
||||
Bind string `toml:"bind"`
|
||||
} `toml:"webserver"`
|
||||
}
|
||||
|
||||
func ReadConfig(path string) (*Config, error) {
|
||||
log.Debugf("load of configfile: %s", path)
|
||||
var config Config
|
||||
file, _ := ioutil.ReadFile(path)
|
||||
err := toml.Unmarshal(file, &config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &config, nil
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package log
|
||||
|
||||
type Hook func(e *Entry)
|
||||
|
||||
var hooks = make([]Hook, 0)
|
||||
|
||||
func AddHook(hook Hook) {
|
||||
hooks = append(hooks, hook)
|
||||
}
|
||||
|
||||
func save(e *Entry) {
|
||||
for _, hook := range hooks {
|
||||
hook(e)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
|
||||
"github.com/genofire/logmania/log"
|
||||
)
|
||||
|
||||
type Logger struct {
|
||||
AboveLevel log.LogLevel
|
||||
conn *websocket.Conn
|
||||
}
|
||||
|
||||
func (l *Logger) hook(e *log.Entry) {
|
||||
if e.Level < l.AboveLevel {
|
||||
return
|
||||
}
|
||||
err := l.conn.WriteJSON(e)
|
||||
if err != nil {
|
||||
log.Panic("[logmania] could not send token")
|
||||
}
|
||||
}
|
||||
func (l *Logger) Close() {
|
||||
l.conn.Close()
|
||||
}
|
||||
|
||||
func Init(url, token string) *Logger {
|
||||
logger := &Logger{
|
||||
AboveLevel: log.InfoLevel,
|
||||
}
|
||||
c, _, err := websocket.DefaultDialer.Dial(fmt.Sprint(url, "/logger"), nil)
|
||||
if err != nil {
|
||||
log.Panic("[logmania] error on connect")
|
||||
return nil
|
||||
}
|
||||
err = c.WriteJSON(token)
|
||||
if err != nil {
|
||||
log.Panic("[logmania] could not send token")
|
||||
return nil
|
||||
}
|
||||
logger.conn = c
|
||||
log.AddHook(logger.hook)
|
||||
return logger
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package output
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/genofire/logmania/log"
|
||||
)
|
||||
|
||||
var (
|
||||
TimeFormat = "2006-01-02 15:04:05"
|
||||
ShowTime = true
|
||||
AboveLevel = log.InfoLevel
|
||||
)
|
||||
|
||||
func hook(e *log.Entry) {
|
||||
if e.Level < AboveLevel {
|
||||
return
|
||||
}
|
||||
v := []interface{}{}
|
||||
format := "[%s] %s"
|
||||
|
||||
if ShowTime {
|
||||
format = "%s [%s] %s"
|
||||
v = append(v, time.Now().Format(TimeFormat))
|
||||
}
|
||||
|
||||
v = append(v, e.Level.String(), e.Text)
|
||||
|
||||
if len(e.Fields) > 0 {
|
||||
v = append(v, e.FieldString())
|
||||
format = fmt.Sprintf("%s (%%s)\n", format)
|
||||
} else {
|
||||
format = fmt.Sprintf("%s\n", format)
|
||||
}
|
||||
|
||||
text := fmt.Sprintf(format, v...)
|
||||
|
||||
if e.Level == log.PanicLevel {
|
||||
panic(text)
|
||||
} else if e.Level > log.WarnLevel {
|
||||
os.Stderr.WriteString(text)
|
||||
} else {
|
||||
os.Stdout.WriteString(text)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
log.AddHook(hook)
|
||||
}
|
|
@ -1,16 +1,16 @@
|
|||
package entry
|
||||
package log
|
||||
|
||||
type logLevel int32
|
||||
type LogLevel int32
|
||||
|
||||
const (
|
||||
DebugLevel = -1
|
||||
InfoLevel = 0
|
||||
WarnLevel = 1
|
||||
ErrorLevel = 2
|
||||
PanicLevel = 3
|
||||
DebugLevel = LogLevel(-1)
|
||||
InfoLevel = LogLevel(0)
|
||||
WarnLevel = LogLevel(1)
|
||||
ErrorLevel = LogLevel(2)
|
||||
PanicLevel = LogLevel(3)
|
||||
)
|
||||
|
||||
func (l logLevel) String() string {
|
||||
func (l LogLevel) String() string {
|
||||
switch l {
|
||||
case DebugLevel:
|
||||
return "Debug"
|
|
@ -1,19 +1,19 @@
|
|||
package entry
|
||||
package log
|
||||
|
||||
import "fmt"
|
||||
|
||||
type Entry struct {
|
||||
Level logLevel `json:"level"`
|
||||
Level LogLevel `json:"level"`
|
||||
Fields map[string]interface{} `json:"fields"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
func (e *Entry) Log(level logLevel, v ...interface{}) {
|
||||
func (e *Entry) Log(level LogLevel, v ...interface{}) {
|
||||
e.Text = fmt.Sprint(v...)
|
||||
e.Level = level
|
||||
save(e)
|
||||
}
|
||||
func (e *Entry) Logf(level logLevel, format string, v ...interface{}) {
|
||||
func (e *Entry) Logf(level LogLevel, format string, v ...interface{}) {
|
||||
e.Text = fmt.Sprintf(format, v...)
|
||||
e.Level = level
|
||||
save(e)
|
||||
|
@ -35,5 +35,9 @@ func (e *Entry) AddFields(fields map[string]interface{}) *Entry {
|
|||
}
|
||||
|
||||
func (e *Entry) FieldString() string {
|
||||
return FieldOutput(e.Fields)
|
||||
text := ""
|
||||
for key, value := range e.Fields {
|
||||
text = fmt.Sprintf("%s %s=%v", text, key, value)
|
||||
}
|
||||
return text[1:]
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
[api]
|
||||
|
||||
[database]
|
||||
|
||||
[webserver]
|
||||
enable = true
|
Loading…
Reference in New Issue