switch logrus and cobra
This commit is contained in:
parent
f10a4f5918
commit
2851513cfb
|
@ -6,8 +6,7 @@ import (
|
|||
"time"
|
||||
|
||||
timeago "github.com/ararog/timeago"
|
||||
|
||||
"github.com/genofire/logmania/log"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type commandFunc func(func(string), string, []string)
|
||||
|
@ -156,11 +155,18 @@ func (b *Bot) setMaxfilter(answer func(string), from string, params []string) {
|
|||
return
|
||||
}
|
||||
to := from
|
||||
max := log.NewLoglevel(params[0])
|
||||
var max log.Level
|
||||
var err error
|
||||
|
||||
if len(params) > 1 {
|
||||
to = params[0]
|
||||
max = log.NewLoglevel(params[1])
|
||||
max, err = log.ParseLevel(params[1])
|
||||
} else {
|
||||
max, err = log.ParseLevel(params[0])
|
||||
}
|
||||
if err != nil {
|
||||
answer("invalid priority: CMD Priority\n or\n CMD IPAddress Priority")
|
||||
return
|
||||
}
|
||||
|
||||
b.state.MaxPrioIn[to] = max
|
||||
|
|
|
@ -9,7 +9,7 @@ dependencies:
|
|||
- mkdir -p ~/.go_workspace/src/github.com/${CIRCLE_PROJECT_USERNAME}
|
||||
- ln -s ${HOME}/${CIRCLE_PROJECT_REPONAME} ${HOME}/.go_workspace/src/github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}
|
||||
- go get -t -d -v ./...
|
||||
- go install github.com/genofire/logmania/cmd/logmania
|
||||
- go install github.com/genofire/logmania
|
||||
post:
|
||||
- cp ~/.go_workspace/bin/logmania logmania.bin
|
||||
- tar -cvzf logmania-builded.tar.gz logmania.bin logmania_example.conf
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
// logmania Server
|
||||
//
|
||||
// reload config with SIGUSR1
|
||||
//
|
||||
// Usage of logmania:
|
||||
// -config string
|
||||
// config file (default "logmania.conf")
|
||||
// -debug
|
||||
// enable debuging
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/genofire/logmania/bot"
|
||||
"github.com/genofire/logmania/lib"
|
||||
log "github.com/genofire/logmania/log"
|
||||
"github.com/genofire/logmania/notify"
|
||||
allNotify "github.com/genofire/logmania/notify/all"
|
||||
configNotify "github.com/genofire/logmania/notify/config"
|
||||
"github.com/genofire/logmania/receive"
|
||||
allReceiver "github.com/genofire/logmania/receive/all"
|
||||
)
|
||||
|
||||
var (
|
||||
configPath string
|
||||
config *lib.Config
|
||||
notifyState *configNotify.NotifyState
|
||||
notifier notify.Notifier
|
||||
receiver receive.Receiver
|
||||
logChannel chan *log.Entry
|
||||
logmaniaBot *bot.Bot
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&configPath, "config", "logmania.conf", "config file")
|
||||
flag.Parse()
|
||||
|
||||
config, err := lib.ReadConfig(configPath)
|
||||
if config == nil || err != nil {
|
||||
log.Panicf("Could not load '%s' for configuration.", configPath)
|
||||
}
|
||||
|
||||
notifyState := configNotify.ReadStateFile(config.Notify.StateFile)
|
||||
go notifyState.Saver(config.Notify.StateFile)
|
||||
|
||||
logmaniaBot = bot.NewBot(notifyState)
|
||||
|
||||
notifier = allNotify.Init(&config.Notify, notifyState, logmaniaBot)
|
||||
log.Save = notifier.Send
|
||||
logChannel = make(chan *log.Entry)
|
||||
|
||||
go func() {
|
||||
for a := range logChannel {
|
||||
log.Save(a)
|
||||
}
|
||||
}()
|
||||
if config.Notify.AlertCheck.Duration > time.Duration(time.Second) {
|
||||
go notifyState.Alert(config.Notify.AlertCheck.Duration, log.Save)
|
||||
}
|
||||
|
||||
log.Info("starting logmania")
|
||||
|
||||
receiver = allReceiver.Init(&config.Receive, logChannel)
|
||||
|
||||
go receiver.Listen()
|
||||
|
||||
// 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.Panic("terminated of logmania")
|
||||
os.Exit(0)
|
||||
case syscall.SIGQUIT:
|
||||
quit()
|
||||
case syscall.SIGHUP:
|
||||
quit()
|
||||
case syscall.SIGUSR1:
|
||||
reload()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func quit() {
|
||||
receiver.Close()
|
||||
notifier.Close()
|
||||
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("reload: could not load '%s' for new configuration. Skip reload.", configPath)
|
||||
return
|
||||
}
|
||||
receiver.Close()
|
||||
receiver = allReceiver.Init(&config.Receive, logChannel)
|
||||
go receiver.Listen()
|
||||
|
||||
notifier.Close()
|
||||
notifier = allNotify.Init(&config.Notify, notifyState, logmaniaBot)
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// RootCmd represents the base command when called without any subcommands
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "logmania",
|
||||
Short: "logging centralize",
|
||||
Long: `centralize logging manager`,
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
if err := RootCmd.Execute(); err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/genofire/logmania/bot"
|
||||
"github.com/genofire/logmania/lib"
|
||||
"github.com/genofire/logmania/notify"
|
||||
allNotify "github.com/genofire/logmania/notify/all"
|
||||
configNotify "github.com/genofire/logmania/notify/config"
|
||||
"github.com/genofire/logmania/receive"
|
||||
allReceiver "github.com/genofire/logmania/receive/all"
|
||||
)
|
||||
|
||||
var (
|
||||
configPath string
|
||||
config *lib.Config
|
||||
notifyState *configNotify.NotifyState
|
||||
notifier notify.Notifier
|
||||
receiver receive.Receiver
|
||||
logChannel chan *log.Entry
|
||||
logmaniaBot *bot.Bot
|
||||
)
|
||||
|
||||
// serverCmd represents the serve command
|
||||
var serverCmd = &cobra.Command{
|
||||
Use: "server",
|
||||
Short: "Runs the logmania server",
|
||||
Example: "logmania server --config /etc/yanic.toml",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
log.SetFormatter(&log.TextFormatter{
|
||||
DisableTimestamp: true,
|
||||
})
|
||||
config, err := lib.ReadConfig(configPath)
|
||||
if config == nil || err != nil {
|
||||
log.Panicf("Could not load '%s' for configuration.", configPath)
|
||||
}
|
||||
|
||||
notifyState := configNotify.ReadStateFile(config.Notify.StateFile)
|
||||
go notifyState.Saver(config.Notify.StateFile)
|
||||
|
||||
logmaniaBot = bot.NewBot(notifyState)
|
||||
|
||||
notifier = allNotify.Init(&config.Notify, notifyState, logmaniaBot)
|
||||
log.AddHook(notifier)
|
||||
logChannel = make(chan *log.Entry)
|
||||
|
||||
go func() {
|
||||
for a := range logChannel {
|
||||
notifier.Fire(a)
|
||||
}
|
||||
}()
|
||||
|
||||
if config.Notify.AlertCheck.Duration > time.Duration(time.Second) {
|
||||
go notifyState.Alert(config.Notify.AlertCheck.Duration, notifier.Fire)
|
||||
}
|
||||
|
||||
log.Info("starting logmania")
|
||||
|
||||
receiver = allReceiver.Init(&config.Receive, logChannel)
|
||||
|
||||
go receiver.Listen()
|
||||
|
||||
// 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.Panic("terminated of logmania")
|
||||
os.Exit(0)
|
||||
case syscall.SIGQUIT:
|
||||
quit()
|
||||
case syscall.SIGHUP:
|
||||
quit()
|
||||
case syscall.SIGUSR1:
|
||||
reload()
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func quit() {
|
||||
receiver.Close()
|
||||
notifier.Close()
|
||||
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("reload: could not load '%s' for new configuration. Skip reload.", configPath)
|
||||
return
|
||||
}
|
||||
receiver.Close()
|
||||
receiver = allReceiver.Init(&config.Receive, logChannel)
|
||||
go receiver.Listen()
|
||||
|
||||
notifier.Close()
|
||||
notifier = allNotify.Init(&config.Notify, notifyState, logmaniaBot)
|
||||
}
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(serverCmd)
|
||||
serverCmd.Flags().StringVarP(&configPath, "config", "c", "logmania.conf", "Path to configuration file")
|
||||
}
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
"github.com/BurntSushi/toml"
|
||||
|
||||
"github.com/genofire/logmania/log"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Struct of the configuration
|
||||
|
|
|
@ -45,7 +45,7 @@ func Parse(binaryMsg []byte) *SyslogMessage {
|
|||
}
|
||||
}
|
||||
|
||||
msg.Content = match[2][timeLength:]
|
||||
msg.Content = strings.TrimLeft(match[2][timeLength:], " ")
|
||||
|
||||
/*
|
||||
TODO: detect other parts in content
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
package client
|
||||
|
||||
/* logger to bind at github.com/genofire/logmania/log.AddLogger to send log entries to logmania server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
|
||||
"github.com/genofire/logmania/log"
|
||||
)
|
||||
|
||||
// client logger
|
||||
type Logger struct {
|
||||
log.Logger
|
||||
AboveLevel log.LogLevel
|
||||
conn *websocket.Conn
|
||||
}
|
||||
|
||||
const LOGGER_NAME = "client"
|
||||
|
||||
// CurrentLogger (for override settings e.g. AboveLevel)
|
||||
var CurrentLogger *Logger
|
||||
|
||||
// create a new logmania client logger
|
||||
func NewLogger(url, token string, AboveLevel log.LogLevel) *Logger {
|
||||
c, _, err := websocket.DefaultDialer.Dial(fmt.Sprint(url, "/logger"), nil)
|
||||
if err != nil {
|
||||
log.Error("[logmania] error on connect: ", err)
|
||||
return nil
|
||||
}
|
||||
err = c.WriteMessage(websocket.TextMessage, []byte(token))
|
||||
if err != nil {
|
||||
log.Error("[logmania] could not send token:", err)
|
||||
return nil
|
||||
}
|
||||
return &Logger{
|
||||
AboveLevel: AboveLevel,
|
||||
conn: c,
|
||||
}
|
||||
}
|
||||
|
||||
// handle a log entry (send to logmania server)
|
||||
func (l *Logger) Hook(e *log.Entry) {
|
||||
if e.Level < l.AboveLevel {
|
||||
return
|
||||
}
|
||||
err := l.conn.WriteJSON(e)
|
||||
if err != nil {
|
||||
l.Close()
|
||||
log.Error("[logmania] could not send log entry:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Listen if logmania server want to close the connection
|
||||
func (l *Logger) Listen() {
|
||||
for {
|
||||
msgType, _, err := l.conn.ReadMessage()
|
||||
if msgType == -1 {
|
||||
l.conn.Close()
|
||||
l.Close()
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
l.Close()
|
||||
log.Warn("[logmania] close listener:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// close connection to logger
|
||||
func (l *Logger) Close() {
|
||||
l.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
||||
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(LOGGER_NAME, CurrentLogger)
|
||||
return CurrentLogger
|
||||
}
|
||||
*/
|
|
@ -1 +0,0 @@
|
|||
package client
|
46
log/init.go
46
log/init.go
|
@ -1,46 +0,0 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
wsGozilla "github.com/gorilla/websocket"
|
||||
"golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
func getIP(r *http.Request) string {
|
||||
ip := r.Header.Get("X-Forwarded-For")
|
||||
if ip == "" {
|
||||
ip = r.RemoteAddr
|
||||
}
|
||||
return ip
|
||||
}
|
||||
|
||||
// init log entry with extra fields of interesting http request context
|
||||
func HTTP(r *http.Request) *Entry {
|
||||
return New().AddFields(map[string]interface{}{
|
||||
"remote": getIP(r),
|
||||
"method": r.Method,
|
||||
"url": r.URL.RequestURI(),
|
||||
})
|
||||
}
|
||||
|
||||
// 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,
|
||||
"url": r.URL.RequestURI(),
|
||||
})
|
||||
}
|
||||
|
||||
// init log entry with extra fields of interesting websocket request context
|
||||
func WebsocketGozilla(ws *wsGozilla.Conn) *Entry {
|
||||
return New().AddFields(map[string]interface{}{
|
||||
"remote": ws.RemoteAddr().String(),
|
||||
"websocket": true,
|
||||
})
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
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))
|
||||
}
|
156
log/level.go
156
log/level.go
|
@ -1,156 +0,0 @@
|
|||
package log
|
||||
|
||||
// definition of loglevel
|
||||
type LogLevel int32
|
||||
|
||||
// accepted LogLevels and his internal int values
|
||||
const (
|
||||
DebugLevel = LogLevel(-1)
|
||||
InfoLevel = LogLevel(0)
|
||||
WarnLevel = LogLevel(1)
|
||||
ErrorLevel = LogLevel(2)
|
||||
PanicLevel = LogLevel(3)
|
||||
)
|
||||
|
||||
// string of loglevel
|
||||
func (l LogLevel) String() string {
|
||||
switch l {
|
||||
case DebugLevel:
|
||||
return "Debug"
|
||||
case InfoLevel:
|
||||
return "Info"
|
||||
case WarnLevel:
|
||||
return "Warn"
|
||||
case ErrorLevel:
|
||||
return "ERROR"
|
||||
case PanicLevel:
|
||||
return "PANIC"
|
||||
|
||||
}
|
||||
return "NOT VALID"
|
||||
}
|
||||
|
||||
func NewLoglevel(by string) LogLevel {
|
||||
switch by {
|
||||
case "debug":
|
||||
return DebugLevel
|
||||
case "info":
|
||||
return InfoLevel
|
||||
case "warn":
|
||||
return WarnLevel
|
||||
case "error":
|
||||
return ErrorLevel
|
||||
case "panic":
|
||||
return PanicLevel
|
||||
|
||||
}
|
||||
return DebugLevel
|
||||
}
|
||||
|
||||
/**
|
||||
* log command
|
||||
*/
|
||||
|
||||
// close logentry with debug
|
||||
func (e *Entry) Debug(v ...interface{}) {
|
||||
e.Log(DebugLevel, v...)
|
||||
}
|
||||
|
||||
// close logentry with formated debug
|
||||
func (e *Entry) Debugf(format string, v ...interface{}) {
|
||||
e.Logf(DebugLevel, format, v...)
|
||||
}
|
||||
|
||||
// close logentry with info
|
||||
func (e *Entry) Info(v ...interface{}) {
|
||||
e.Log(InfoLevel, v...)
|
||||
}
|
||||
|
||||
// close logentry with formated info
|
||||
func (e *Entry) Infof(format string, v ...interface{}) {
|
||||
e.Logf(InfoLevel, format, v...)
|
||||
}
|
||||
|
||||
// close logentry with warning
|
||||
func (e *Entry) Warn(v ...interface{}) {
|
||||
e.Log(WarnLevel, v...)
|
||||
}
|
||||
|
||||
// close logentry with formated warning
|
||||
func (e *Entry) Warnf(format string, v ...interface{}) {
|
||||
e.Logf(WarnLevel, format, v...)
|
||||
}
|
||||
|
||||
// close logentry with error
|
||||
func (e *Entry) Error(v ...interface{}) {
|
||||
e.Log(ErrorLevel, v...)
|
||||
}
|
||||
|
||||
// close logentry with formated error
|
||||
func (e *Entry) Errorf(format string, v ...interface{}) {
|
||||
e.Logf(ErrorLevel, format, v...)
|
||||
}
|
||||
|
||||
// close logentry with panic
|
||||
func (e *Entry) Panic(v ...interface{}) {
|
||||
e.Log(PanicLevel, v...)
|
||||
}
|
||||
|
||||
// close logentry with formated panic
|
||||
func (e *Entry) Panicf(format string, v ...interface{}) {
|
||||
e.Logf(PanicLevel, format, v...)
|
||||
}
|
||||
|
||||
/**
|
||||
* Direct log command
|
||||
*/
|
||||
|
||||
// direct log with debug
|
||||
func Debug(v ...interface{}) {
|
||||
New().Log(DebugLevel, v...)
|
||||
}
|
||||
|
||||
// direct log with formated debug
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
New().Logf(DebugLevel, format, v...)
|
||||
}
|
||||
|
||||
// direct log with info
|
||||
func Info(v ...interface{}) {
|
||||
New().Log(InfoLevel, v...)
|
||||
}
|
||||
|
||||
// direct log with formated info
|
||||
func Infof(format string, v ...interface{}) {
|
||||
New().Logf(InfoLevel, format, v...)
|
||||
}
|
||||
|
||||
// direct log with warning
|
||||
func Warn(v ...interface{}) {
|
||||
New().Log(WarnLevel, v...)
|
||||
}
|
||||
|
||||
// direct log with formated warning
|
||||
func Warnf(format string, v ...interface{}) {
|
||||
New().Logf(WarnLevel, format, v...)
|
||||
}
|
||||
|
||||
// direct log with error
|
||||
func Error(v ...interface{}) {
|
||||
New().Log(ErrorLevel, v...)
|
||||
}
|
||||
|
||||
// direct log with formated error
|
||||
func Errorf(format string, v ...interface{}) {
|
||||
New().Logf(ErrorLevel, format, v...)
|
||||
}
|
||||
|
||||
// direct log with panic
|
||||
func Panic(v ...interface{}) {
|
||||
New().Log(PanicLevel, v...)
|
||||
}
|
||||
|
||||
// direct log with formated panic
|
||||
func Panicf(format string, v ...interface{}) {
|
||||
New().Logf(PanicLevel, format, v...)
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package log
|
||||
|
||||
type loggerFunc func(*Entry)
|
||||
|
||||
var Save loggerFunc
|
||||
|
||||
func init() {
|
||||
Save = func(*Entry) {}
|
||||
}
|
55
log/main.go
55
log/main.go
|
@ -1,55 +0,0 @@
|
|||
// log package with entry as a lib in other go applications
|
||||
package log
|
||||
|
||||
import "fmt"
|
||||
|
||||
// a struct with all information of a log entry
|
||||
type Entry struct {
|
||||
Level LogLevel `json:"level"`
|
||||
Hostname string `json:"hostname"`
|
||||
Service string `json:"service"`
|
||||
Fields map[string]interface{} `json:"fields"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
// Save/out current state of log entry
|
||||
func (e *Entry) Log(level LogLevel, v ...interface{}) {
|
||||
e.Text = fmt.Sprint(v...)
|
||||
e.Level = level
|
||||
Save(e)
|
||||
}
|
||||
|
||||
// Save/out current state of log entry with formation
|
||||
func (e *Entry) Logf(level LogLevel, format string, v ...interface{}) {
|
||||
e.Text = fmt.Sprintf(format, v...)
|
||||
e.Level = level
|
||||
Save(e)
|
||||
}
|
||||
|
||||
// init new log entry
|
||||
func New() *Entry {
|
||||
return &Entry{Fields: make(map[string]interface{})}
|
||||
}
|
||||
|
||||
// add extra value to entry (log entry with context)
|
||||
func (e *Entry) AddField(key string, value interface{}) *Entry {
|
||||
e.Fields[key] = value
|
||||
return e
|
||||
}
|
||||
|
||||
// add multi extra values to entry (log entry with context)
|
||||
func (e *Entry) AddFields(fields map[string]interface{}) *Entry {
|
||||
for key, value := range fields {
|
||||
e.Fields[key] = value
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
// create a readable string of extra values (log entry with context)
|
||||
func (e *Entry) FieldString() string {
|
||||
text := ""
|
||||
for key, value := range e.Fields {
|
||||
text = fmt.Sprintf("%s %s=%v", text, key, value)
|
||||
}
|
||||
return text[1:]
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
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")
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package main
|
||||
|
||||
import "github.com/genofire/logmania/cmd"
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
package all
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/genofire/logmania/bot"
|
||||
"github.com/genofire/logmania/lib"
|
||||
"github.com/genofire/logmania/log"
|
||||
"github.com/genofire/logmania/notify"
|
||||
configNotify "github.com/genofire/logmania/notify/config"
|
||||
)
|
||||
|
@ -36,13 +37,14 @@ func Init(config *lib.NotifyConfig, state *configNotify.NotifyState, bot *bot.Bo
|
|||
func (n *Notifier) sender() {
|
||||
for c := range n.channelNotify {
|
||||
for _, item := range n.list {
|
||||
item.Send(c)
|
||||
item.Fire(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Notifier) Send(e *log.Entry) {
|
||||
func (n *Notifier) Fire(e *log.Entry) error {
|
||||
n.channelNotify <- e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Notifier) Close() {
|
||||
|
@ -50,3 +52,14 @@ func (n *Notifier) Close() {
|
|||
item.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Notifier) Levels() []log.Level {
|
||||
return []log.Level{
|
||||
log.DebugLevel,
|
||||
log.InfoLevel,
|
||||
log.WarnLevel,
|
||||
log.ErrorLevel,
|
||||
log.FatalLevel,
|
||||
log.PanicLevel,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package all
|
||||
|
||||
import (
|
||||
_ "github.com/genofire/logmania/notify/console"
|
||||
_ "github.com/genofire/logmania/notify/xmpp"
|
||||
)
|
||||
|
|
|
@ -2,12 +2,11 @@ package config
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/genofire/logmania/log"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const AlertMsg = "alert service from logmania, device did not send new message for a while"
|
||||
|
@ -15,26 +14,30 @@ const AlertMsg = "alert service from logmania, device did not send new message f
|
|||
type NotifyState struct {
|
||||
Hostname map[string]string `json:"hostname"`
|
||||
HostTo map[string]map[string]bool `json:"host_to"`
|
||||
MaxPrioIn map[string]log.LogLevel `json:"maxLevel"`
|
||||
MaxPrioIn map[string]log.Level `json:"maxLevel"`
|
||||
RegexIn map[string]map[string]*regexp.Regexp `json:"regexIn"`
|
||||
Lastseen map[string]time.Time `json:"lastseen,omitempty"`
|
||||
LastseenNotify map[string]time.Time `json:"-"`
|
||||
}
|
||||
|
||||
func (state *NotifyState) SendTo(e *log.Entry) []string {
|
||||
if to, ok := state.HostTo[e.Hostname]; ok {
|
||||
if e.Text != AlertMsg && e.Hostname != "" {
|
||||
state.Lastseen[e.Hostname] = time.Now()
|
||||
hostname, ok := e.Data["hostname"].(string)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
if to, ok := state.HostTo[hostname]; ok {
|
||||
if e.Message != AlertMsg && hostname != "" {
|
||||
state.Lastseen[hostname] = time.Now()
|
||||
}
|
||||
var toList []string
|
||||
for toEntry, _ := range to {
|
||||
if lvl := state.MaxPrioIn[toEntry]; e.Level < lvl {
|
||||
if lvl := state.MaxPrioIn[toEntry]; e.Level >= lvl {
|
||||
continue
|
||||
}
|
||||
if regex, ok := state.RegexIn[toEntry]; ok {
|
||||
stopForTo := false
|
||||
for _, expr := range regex {
|
||||
if expr.MatchString(e.Text) {
|
||||
if expr.MatchString(e.Message) {
|
||||
stopForTo = true
|
||||
continue
|
||||
}
|
||||
|
@ -45,12 +48,12 @@ func (state *NotifyState) SendTo(e *log.Entry) []string {
|
|||
}
|
||||
toList = append(toList, toEntry)
|
||||
}
|
||||
if hostname, ok := state.Hostname[e.Hostname]; ok {
|
||||
e.Hostname = hostname
|
||||
if replaceHostname, ok := state.Hostname[hostname]; ok {
|
||||
e.WithField("hostname", replaceHostname)
|
||||
}
|
||||
return toList
|
||||
} else {
|
||||
state.HostTo[e.Hostname] = make(map[string]bool)
|
||||
state.HostTo[hostname] = make(map[string]bool)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -71,7 +74,7 @@ func ReadStateFile(path string) *NotifyState {
|
|||
var state NotifyState
|
||||
if f, err := os.Open(path); err == nil { // transform data to legacy meshviewer
|
||||
if err = json.NewDecoder(f).Decode(&state); err == nil {
|
||||
fmt.Println("loaded", len(state.HostTo), "hosts")
|
||||
log.Infof("loaded %d hosts", len(state.HostTo))
|
||||
if state.Lastseen == nil {
|
||||
state.Lastseen = make(map[string]time.Time)
|
||||
}
|
||||
|
@ -89,15 +92,15 @@ func ReadStateFile(path string) *NotifyState {
|
|||
}
|
||||
return &state
|
||||
} else {
|
||||
fmt.Println("failed to unmarshal nodes:", err)
|
||||
log.Error("failed to unmarshal nodes:", err)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("failed to open state notify file: ", path, ":", err)
|
||||
log.Error("failed to open state notify file: ", path, ":", err)
|
||||
}
|
||||
return &NotifyState{
|
||||
Hostname: make(map[string]string),
|
||||
HostTo: make(map[string]map[string]bool),
|
||||
MaxPrioIn: make(map[string]log.LogLevel),
|
||||
MaxPrioIn: make(map[string]log.Level),
|
||||
RegexIn: make(map[string]map[string]*regexp.Regexp),
|
||||
Lastseen: make(map[string]time.Time),
|
||||
LastseenNotify: make(map[string]time.Time),
|
||||
|
@ -112,7 +115,7 @@ func (state *NotifyState) Saver(path string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (state *NotifyState) Alert(expired time.Duration, send func(e *log.Entry)) {
|
||||
func (state *NotifyState) Alert(expired time.Duration, send func(e *log.Entry) error) {
|
||||
c := time.Tick(time.Minute)
|
||||
|
||||
for range c {
|
||||
|
@ -121,11 +124,11 @@ func (state *NotifyState) Alert(expired time.Duration, send func(e *log.Entry))
|
|||
if time.Before(now.Add(expired * -2)) {
|
||||
if timeNotify, ok := state.LastseenNotify[host]; !ok || !time.Before(timeNotify) {
|
||||
state.LastseenNotify[host] = now
|
||||
send(&log.Entry{
|
||||
Hostname: host,
|
||||
Level: log.ErrorLevel,
|
||||
Text: AlertMsg,
|
||||
})
|
||||
entry := log.NewEntry(log.New())
|
||||
entry.Level = log.ErrorLevel
|
||||
entry.Message = AlertMsg
|
||||
entry.WithField("hostname", host)
|
||||
send(entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
package console
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/bclicn/color"
|
||||
|
||||
"github.com/genofire/logmania/bot"
|
||||
"github.com/genofire/logmania/lib"
|
||||
"github.com/genofire/logmania/log"
|
||||
"github.com/genofire/logmania/notify"
|
||||
configNotify "github.com/genofire/logmania/notify/config"
|
||||
)
|
||||
|
||||
var (
|
||||
errOutput io.Writer = os.Stderr
|
||||
output io.Writer = os.Stdout
|
||||
)
|
||||
|
||||
// logger for output
|
||||
type Notifier struct {
|
||||
notify.Notifier
|
||||
TimeFormat string
|
||||
ShowTime bool
|
||||
Debug bool
|
||||
}
|
||||
|
||||
func Init(config *lib.NotifyConfig, state *configNotify.NotifyState, bot *bot.Bot) notify.Notifier {
|
||||
return &Notifier{
|
||||
TimeFormat: "2006-01-02 15:04:05",
|
||||
ShowTime: true,
|
||||
Debug: config.Console,
|
||||
}
|
||||
}
|
||||
|
||||
// handle a log entry (print it on the terminal with color)
|
||||
func (n *Notifier) Send(e *log.Entry) {
|
||||
if e == nil || n == nil {
|
||||
return
|
||||
}
|
||||
if e.Hostname != "" && !n.Debug {
|
||||
return
|
||||
}
|
||||
v := []interface{}{}
|
||||
format := "[%s]"
|
||||
|
||||
if n.ShowTime {
|
||||
format = "%s [%s]"
|
||||
v = append(v, color.LightBlue(time.Now().Format(n.TimeFormat)))
|
||||
}
|
||||
|
||||
// Hostname and Service
|
||||
if e.Hostname != "" && e.Service != "" {
|
||||
format = fmt.Sprintf("%s [%%s-%%s]", format)
|
||||
v = append(v, color.Purple(e.Hostname), color.Cyan(e.Service))
|
||||
} else if e.Hostname != "" {
|
||||
format = fmt.Sprintf("%s [%%s]", format)
|
||||
v = append(v, color.Purple(e.Hostname))
|
||||
} else if e.Service != "" {
|
||||
format = fmt.Sprintf("%s [%%s]", format)
|
||||
v = append(v, color.Cyan(e.Service))
|
||||
}
|
||||
|
||||
format = fmt.Sprintf("%s %%s", format)
|
||||
lvl := e.Level.String()
|
||||
switch e.Level {
|
||||
case log.DebugLevel:
|
||||
lvl = color.DarkGray(lvl)
|
||||
case log.InfoLevel:
|
||||
lvl = color.Green(lvl)
|
||||
case log.WarnLevel:
|
||||
lvl = color.Yellow(lvl)
|
||||
case log.ErrorLevel:
|
||||
lvl = color.Red(lvl)
|
||||
case log.PanicLevel:
|
||||
lvl = color.BRed(lvl)
|
||||
}
|
||||
|
||||
v = append(v, lvl, e.Text)
|
||||
|
||||
if len(e.Fields) > 0 {
|
||||
v = append(v, color.Purple(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.WarnLevel {
|
||||
errOutput.Write([]byte(text))
|
||||
} else {
|
||||
output.Write([]byte(text))
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Notifier) Close() {}
|
||||
|
||||
func init() {
|
||||
notify.AddNotifier(Init)
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
package console
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/genofire/logmania/log"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func captureOutput(f func()) (string, string) {
|
||||
var bufErrOutput bytes.Buffer
|
||||
var bufOutput bytes.Buffer
|
||||
errOutput = &bufErrOutput
|
||||
output = &bufOutput
|
||||
f()
|
||||
errOutput = os.Stderr
|
||||
output = os.Stdout
|
||||
return bufOutput.String(), bufErrOutput.String()
|
||||
}
|
||||
|
||||
// Warning: colors are not tested (it should be in the imported package)
|
||||
func TestOutput(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
assert.True(true)
|
||||
out, err := captureOutput(func() {
|
||||
log.Info("test")
|
||||
})
|
||||
assert.Equal("", err)
|
||||
|
||||
out, err = captureOutput(func() {
|
||||
log.Warn("test")
|
||||
})
|
||||
assert.NotRegexp("-.*\\[.{5}Warn.{4}\\] test", out)
|
||||
assert.Equal("", err)
|
||||
|
||||
out, err = captureOutput(func() {
|
||||
log.Error("test")
|
||||
})
|
||||
assert.Equal("", out)
|
||||
|
||||
out, err = captureOutput(func() {
|
||||
log.Debug("test")
|
||||
})
|
||||
assert.Equal("", out)
|
||||
assert.Equal("", err)
|
||||
|
||||
out, err = captureOutput(func() {
|
||||
log.Info("test")
|
||||
})
|
||||
assert.Equal("", out)
|
||||
assert.Equal("", err)
|
||||
|
||||
}
|
|
@ -1,16 +1,18 @@
|
|||
package notify
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/genofire/logmania/bot"
|
||||
"github.com/genofire/logmania/lib"
|
||||
"github.com/genofire/logmania/log"
|
||||
configNotify "github.com/genofire/logmania/notify/config"
|
||||
)
|
||||
|
||||
var NotifyRegister []NotifyInit
|
||||
|
||||
type Notifier interface {
|
||||
Send(entry *log.Entry)
|
||||
Fire(entry *log.Entry) error
|
||||
Levels() []log.Level
|
||||
Close()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package xmpp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/genofire/logmania/log"
|
||||
)
|
||||
|
||||
func formatEntry(e *log.Entry) string {
|
||||
if e.Hostname != "" && e.Service != "" {
|
||||
return fmt.Sprintf("[%s-%s] [%s] %s", e.Hostname, e.Service, e.Level, e.Text)
|
||||
|
||||
} else if e.Hostname != "" {
|
||||
return fmt.Sprintf("[%s] [%s] %s", e.Hostname, e.Level, e.Text)
|
||||
|
||||
} else if e.Service != "" {
|
||||
return fmt.Sprintf("[%s] [%s] %s", e.Service, e.Level, e.Text)
|
||||
|
||||
}
|
||||
return fmt.Sprintf("[%s] %s", e.Level, e.Text)
|
||||
}
|
|
@ -1,22 +1,26 @@
|
|||
package xmpp
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
xmpp "github.com/mattn/go-xmpp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/genofire/logmania/bot"
|
||||
"github.com/genofire/logmania/lib"
|
||||
"github.com/genofire/logmania/log"
|
||||
"github.com/genofire/logmania/notify"
|
||||
configNotify "github.com/genofire/logmania/notify/config"
|
||||
)
|
||||
|
||||
var logger = log.WithField("notify", "xmpp")
|
||||
|
||||
type Notifier struct {
|
||||
notify.Notifier
|
||||
client *xmpp.Client
|
||||
state *configNotify.NotifyState
|
||||
formatter *log.TextFormatter
|
||||
}
|
||||
|
||||
func Init(config *lib.NotifyConfig, state *configNotify.NotifyState, bot *bot.Bot) notify.Notifier {
|
||||
|
@ -32,13 +36,14 @@ func Init(config *lib.NotifyConfig, state *configNotify.NotifyState, bot *bot.Bo
|
|||
}
|
||||
client, err := options.NewClient()
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
return nil
|
||||
}
|
||||
go func() {
|
||||
for {
|
||||
chat, err := client.Recv()
|
||||
if err != nil {
|
||||
log.Warn(err)
|
||||
logger.Warn(err)
|
||||
}
|
||||
switch v := chat.(type) {
|
||||
case xmpp.Chat:
|
||||
|
@ -48,30 +53,52 @@ func Init(config *lib.NotifyConfig, state *configNotify.NotifyState, bot *bot.Bo
|
|||
}
|
||||
}
|
||||
}()
|
||||
log.Info("xmpp startup")
|
||||
return &Notifier{client: client, state: state}
|
||||
logger.Info("startup")
|
||||
return &Notifier{
|
||||
client: client,
|
||||
state: state,
|
||||
formatter: &log.TextFormatter{
|
||||
DisableTimestamp: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Notifier) Send(e *log.Entry) {
|
||||
func (n *Notifier) Fire(e *log.Entry) error {
|
||||
to := n.state.SendTo(e)
|
||||
if to == nil {
|
||||
return
|
||||
return errors.New("no reciever found")
|
||||
}
|
||||
text, err := n.formatter.Format(e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, toAddr := range to {
|
||||
to := strings.TrimPrefix(toAddr, "xmpp:")
|
||||
if strings.Contains(toAddr, "conference") || strings.Contains(toAddr, "irc") {
|
||||
n.client.JoinMUCNoHistory(to, "logmania")
|
||||
_, err := n.client.SendHtml(xmpp.Chat{Remote: to, Type: "groupchat", Text: formatEntry(e)})
|
||||
_, err = n.client.SendHtml(xmpp.Chat{Remote: to, Type: "groupchat", Text: string(text)})
|
||||
if err != nil {
|
||||
fmt.Println("xmpp to ", to, " error:", err)
|
||||
logger.Error("xmpp to ", to, " error:", err)
|
||||
}
|
||||
} else {
|
||||
_, err := n.client.SendHtml(xmpp.Chat{Remote: to, Type: "chat", Text: formatEntry(e)})
|
||||
_, err := n.client.SendHtml(xmpp.Chat{Remote: to, Type: "chat", Text: string(text)})
|
||||
if err != nil {
|
||||
fmt.Println("xmpp to ", to, " error:", err)
|
||||
logger.Error("xmpp to ", to, " error:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Notifier) Levels() []log.Level {
|
||||
return []log.Level{
|
||||
log.DebugLevel,
|
||||
log.InfoLevel,
|
||||
log.WarnLevel,
|
||||
log.ErrorLevel,
|
||||
log.FatalLevel,
|
||||
log.PanicLevel,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Notifier) Close() {}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package all
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/genofire/logmania/lib"
|
||||
"github.com/genofire/logmania/log"
|
||||
"github.com/genofire/logmania/receive"
|
||||
)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"github.com/genofire/logmania/log"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type JournalMessage struct {
|
||||
|
@ -34,7 +34,7 @@ type JournalMessage struct {
|
|||
Message string `json:"MESSAGE"`
|
||||
}
|
||||
|
||||
var PriorityMap = map[int]log.LogLevel{
|
||||
var PriorityMap = map[int]log.Level{
|
||||
0: log.PanicLevel, // emerg
|
||||
1: log.PanicLevel, // alert
|
||||
2: log.PanicLevel, // crit
|
||||
|
@ -57,15 +57,16 @@ func toLogEntry(msg []byte, from string) *log.Entry {
|
|||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
e := &log.Entry{
|
||||
Level: PriorityMap[prio],
|
||||
Hostname: from,
|
||||
Service: data.SyslogIdentifier,
|
||||
Text: data.Message,
|
||||
Fields: mapEntry,
|
||||
}
|
||||
entry := log.NewEntry(nil)
|
||||
entry = entry.WithFields(mapEntry)
|
||||
entry = entry.WithFields(log.Fields{
|
||||
"hostname": from,
|
||||
"service": data.SyslogIdentifier,
|
||||
})
|
||||
if data.SystemdUnit == "" {
|
||||
e.Service = data.SystemdUnit
|
||||
entry = entry.WithField("service", data.SystemdUnit)
|
||||
}
|
||||
return e
|
||||
entry.Level = PriorityMap[prio]
|
||||
entry.Message = data.Message
|
||||
return entry
|
||||
}
|
||||
|
|
|
@ -3,11 +3,14 @@ package journald_json
|
|||
import (
|
||||
"net"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/genofire/logmania/lib"
|
||||
"github.com/genofire/logmania/log"
|
||||
"github.com/genofire/logmania/receive"
|
||||
)
|
||||
|
||||
var logger = log.WithField("receive", "journald_json")
|
||||
|
||||
type Receiver struct {
|
||||
receive.Receiver
|
||||
exportChannel chan *log.Entry
|
||||
|
@ -19,7 +22,7 @@ func Init(config *lib.ReceiveConfig, exportChannel chan *log.Entry) receive.Rece
|
|||
ln, err := net.ListenUDP(config.JournaldJSON.Type, addr)
|
||||
|
||||
if err != nil {
|
||||
log.Error("journald-json init ", err)
|
||||
logger.Error("init ", err)
|
||||
return nil
|
||||
}
|
||||
recv := &Receiver{
|
||||
|
@ -27,7 +30,7 @@ func Init(config *lib.ReceiveConfig, exportChannel chan *log.Entry) receive.Rece
|
|||
exportChannel: exportChannel,
|
||||
}
|
||||
|
||||
log.Info("journald-json init")
|
||||
logger.Info("init")
|
||||
|
||||
return recv
|
||||
}
|
||||
|
@ -35,12 +38,12 @@ func Init(config *lib.ReceiveConfig, exportChannel chan *log.Entry) receive.Rece
|
|||
const maxDataGramSize = 8192
|
||||
|
||||
func (rc *Receiver) Listen() {
|
||||
log.Info("journald-json listen")
|
||||
logger.Info("listen")
|
||||
for {
|
||||
buf := make([]byte, maxDataGramSize)
|
||||
n, src, err := rc.serverSocket.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
log.Warn("failed to accept connection", err)
|
||||
logger.Warn("failed to accept connection", err)
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package receive
|
|||
|
||||
import (
|
||||
"github.com/genofire/logmania/lib"
|
||||
"github.com/genofire/logmania/log"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var Register = make(map[string]ReceiverInit)
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package syslog
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
libSyslog "github.com/genofire/logmania/lib/syslog"
|
||||
"github.com/genofire/logmania/log"
|
||||
)
|
||||
|
||||
var SyslogPriorityMap = map[int]log.LogLevel{
|
||||
var SyslogPriorityMap = map[int]log.Level{
|
||||
0: log.PanicLevel,
|
||||
1: log.PanicLevel,
|
||||
2: log.PanicLevel,
|
||||
|
@ -19,9 +20,10 @@ var SyslogPriorityMap = map[int]log.LogLevel{
|
|||
func toLogEntry(msg []byte, from string) *log.Entry {
|
||||
syslogMsg := libSyslog.Parse(msg)
|
||||
|
||||
return &log.Entry{
|
||||
Level: SyslogPriorityMap[syslogMsg.Severity],
|
||||
Text: syslogMsg.Content,
|
||||
Hostname: from,
|
||||
}
|
||||
entry := log.NewEntry(nil)
|
||||
entry = entry.WithField("hostname", from)
|
||||
entry.Time = syslogMsg.Timestemp
|
||||
entry.Level = SyslogPriorityMap[syslogMsg.Severity]
|
||||
entry.Message = syslogMsg.Content
|
||||
return entry
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package syslog
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func TestToEntry(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
entry := toLogEntry([]byte("<11>Aug 17 11:43:33 Msg"), "::1")
|
||||
assert.Equal("Msg", entry.Message)
|
||||
assert.Equal(log.ErrorLevel, entry.Level)
|
||||
|
||||
hostname, ok := entry.Data["hostname"]
|
||||
assert.True(ok)
|
||||
assert.Equal("::1", hostname)
|
||||
|
||||
}
|
|
@ -3,11 +3,14 @@ package syslog
|
|||
import (
|
||||
"net"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/genofire/logmania/lib"
|
||||
"github.com/genofire/logmania/log"
|
||||
"github.com/genofire/logmania/receive"
|
||||
)
|
||||
|
||||
var logger = log.WithField("receive", "syslog")
|
||||
|
||||
type Receiver struct {
|
||||
receive.Receiver
|
||||
exportChannel chan *log.Entry
|
||||
|
@ -19,7 +22,7 @@ func Init(config *lib.ReceiveConfig, exportChannel chan *log.Entry) receive.Rece
|
|||
ln, err := net.ListenUDP(config.Syslog.Type, addr)
|
||||
|
||||
if err != nil {
|
||||
log.Error("syslog init ", err)
|
||||
logger.Error("init ", err)
|
||||
return nil
|
||||
}
|
||||
recv := &Receiver{
|
||||
|
@ -27,7 +30,7 @@ func Init(config *lib.ReceiveConfig, exportChannel chan *log.Entry) receive.Rece
|
|||
exportChannel: exportChannel,
|
||||
}
|
||||
|
||||
log.Info("syslog init")
|
||||
logger.Info("init")
|
||||
|
||||
return recv
|
||||
}
|
||||
|
@ -35,18 +38,21 @@ func Init(config *lib.ReceiveConfig, exportChannel chan *log.Entry) receive.Rece
|
|||
const maxDataGramSize = 8192
|
||||
|
||||
func (rc *Receiver) Listen() {
|
||||
log.Info("syslog listen")
|
||||
logger.Info("listen")
|
||||
for {
|
||||
buf := make([]byte, maxDataGramSize)
|
||||
n, src, err := rc.serverSocket.ReadFromUDP(buf)
|
||||
if err != nil {
|
||||
log.Warn("failed to accept connection", err)
|
||||
logger.Warn("failed to accept connection", err)
|
||||
continue
|
||||
}
|
||||
|
||||
raw := make([]byte, n)
|
||||
copy(raw, buf)
|
||||
rc.exportChannel <- toLogEntry(raw, src.IP.String())
|
||||
entry := toLogEntry(raw, src.IP.String())
|
||||
if entry != nil {
|
||||
rc.exportChannel <- entry
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue