From 941d84fb3f9f4663dacb887d3d6134b8e8ed6a05 Mon Sep 17 00:00:00 2001 From: Bruno Clermont Date: Wed, 8 Feb 2017 18:26:03 +0800 Subject: [PATCH] switch to logrus --- src/cypherpunks.ru/govpn/logger.go | 111 +++++++++++++++++++++++------ 1 file changed, 89 insertions(+), 22 deletions(-) diff --git a/src/cypherpunks.ru/govpn/logger.go b/src/cypherpunks.ru/govpn/logger.go index f38a245..967b843 100644 --- a/src/cypherpunks.ru/govpn/logger.go +++ b/src/cypherpunks.ru/govpn/logger.go @@ -1,3 +1,5 @@ +// +build !windows + /* GoVPN -- simple secure free software virtual private network daemon Copyright (C) 2014-2017 Sergey Matveev @@ -20,37 +22,102 @@ along with this program. If not, see . package govpn import ( - "log" - "log/syslog" -) + "bytes" + "fmt" + logsyslog "log/syslog" + "os" + "sort" + "time" -var ( - sysloger *log.Logger + "github.com/Sirupsen/logrus" + "github.com/Sirupsen/logrus/hooks/syslog" + "github.com/pkg/errors" ) -// Enable logging to syslog, instead of default stdout log. -func SyslogEnable() { - var err error - sysloger, err = syslog.NewLogger(syslog.LOG_INFO, 0) - if err != nil { - log.Fatalln(err) +// syslogFormatter is a formatter that is syslog friendly +type syslogFormatter struct { +} + +// Format convert a log entry into a list of bytes +func (sf *syslogFormatter) Format(entry *logrus.Entry) ([]byte, error) { + buf := bytes.NewBuffer(nil) + var ( + err error + index int + ) + keys := make([]string, len(entry.Data)) + for k := range entry.Data { + keys[index] = k + index++ + } + sort.Strings(keys) + + for index = range keys { + k := keys[index] + v := entry.Data[k] + if _, err = buf.WriteString(fmt.Sprintf("[%s]%+v ", k, v)); err != nil { + return nil, errors.Wrapf(err, "buf.WriteString %s", k) + } } + if _, err = buf.WriteString(entry.Message); err != nil { + return nil, errors.Wrap(err, "buf.WriteString message") + } + return buf.Bytes(), nil } -// Call either syslog-related logger.Printf if SyslogEnabled, -// default log.Printf otherwise. -func Printf(f string, v ...interface{}) { - if sysloger == nil { - log.Printf(f, v...) +// NewLogger return a logger for specified level. Syslog or Windows Events can be turned on. +func NewLogger(level string, syslog bool) (*logrus.Logger, error) { + var logger *logrus.Logger + logLevel, err := logrus.ParseLevel(level) + if err != nil { + return nil, errors.Wrap(err, "logrus.ParseLevel") + } + + if syslog { + syslogHook, err := logrus_syslog.NewSyslogHook("", "", logsyslog.LOG_INFO, "GoVPN") + if err != nil { + return nil, errors.Wrap(err, "logrus_syslog.NewSyslogHook") + } + logger = &logrus.Logger{ + Formatter: &syslogFormatter{}, + Hooks: make(logrus.LevelHooks), + } + logger.Hooks.Add(syslogHook) } else { - sysloger.Printf(f, v...) + logger = &logrus.Logger{ + Formatter: &logrus.TextFormatter{ + ForceColors: true, + DisableColors: false, + DisableTimestamp: false, + FullTimestamp: true, + TimestampFormat: time.RFC3339Nano, + DisableSorting: false, + }, + Hooks: make(logrus.LevelHooks), + } + } + logger.Out = os.Stderr + logger.Level = logLevel + logger.WithFields(logrus.Fields{ + "version": VersionGet(), + "level": logLevel.String(), + }).Info("Initialize logging") + return logger, nil +} + +// ExtendLogFields add to existing fields a new batch of log Fields +func ExtendLogFields(input *logrus.Fields, add logrus.Fields) { + i := *input + for k, v := range add { + i[k] = v } } -// Call both default log.Printf and syslog-related one. -func BothPrintf(f string, v ...interface{}) { - log.Printf(f, v...) - if sysloger != nil { - sysloger.Printf(f, v...) +// MergeLogFields combine multiple log fields into a single one +func MergeLogFields(fields ...logrus.Fields) (output logrus.Fields) { + output = logrus.Fields{} + for _, f := range fields { + ExtendLogFields(&output, f) } + return } -- 2.44.0