mirror of
https://github.com/zrepl/zrepl.git
synced 2024-11-22 00:13:52 +01:00
experimental TCP hook for logrus
This commit is contained in:
parent
9465b593f9
commit
83edcb3889
@ -5,6 +5,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
type LoggingConfig struct {
|
||||
@ -12,6 +13,15 @@ type LoggingConfig struct {
|
||||
Level logrus.Level
|
||||
Format LogFormat
|
||||
}
|
||||
TCP *TCPLoggingConfig
|
||||
}
|
||||
|
||||
type TCPLoggingConfig struct {
|
||||
Level logrus.Level
|
||||
Format LogFormat
|
||||
Net string
|
||||
Address string
|
||||
RetryInterval time.Duration
|
||||
}
|
||||
|
||||
func parseLogging(i interface{}) (c *LoggingConfig, err error) {
|
||||
@ -28,6 +38,13 @@ func parseLogging(i interface{}) (c *LoggingConfig, err error) {
|
||||
Level string
|
||||
Format string
|
||||
}
|
||||
TCP struct {
|
||||
Level string
|
||||
Format string
|
||||
Net string
|
||||
Address string
|
||||
RetryInterval string `mapstructure:"retry_interval"`
|
||||
}
|
||||
}
|
||||
if err = mapstructure.Decode(i, &asMap); err != nil {
|
||||
return nil, errors.Wrap(err, "mapstructure error")
|
||||
@ -48,6 +65,20 @@ func parseLogging(i interface{}) (c *LoggingConfig, err error) {
|
||||
c.Stdout.Format = format
|
||||
}
|
||||
|
||||
if asMap.TCP.Address != "" {
|
||||
c.TCP = &TCPLoggingConfig{}
|
||||
c.TCP.Format, err = parseLogFormat(asMap.TCP.Format)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot parse log format")
|
||||
}
|
||||
c.TCP.Level, err = logrus.ParseLevel(asMap.TCP.Level)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot parse level")
|
||||
}
|
||||
c.TCP.RetryInterval, err = time.ParseDuration(asMap.TCP.RetryInterval)
|
||||
c.TCP.Net, c.TCP.Address = asMap.TCP.Net, asMap.TCP.Address
|
||||
}
|
||||
|
||||
return c, nil
|
||||
|
||||
}
|
||||
@ -96,9 +127,12 @@ func (c *LoggingConfig) MakeLogrus() (l logrus.FieldLogger) {
|
||||
|
||||
log := logrus.New()
|
||||
log.Out = os.Stdout
|
||||
log.Level = c.Stdout.Level
|
||||
log.Level = logrus.DebugLevel // FIXTHIS IN LOGRUS
|
||||
log.Formatter = c.Stdout.Format.Formatter()
|
||||
|
||||
th := &TCPHook{Formatter: JSONFormatter{}, MinLevel: c.TCP.Level, Net: c.TCP.Net, Address: c.TCP.Address, RetryInterval: c.TCP.RetryInterval}
|
||||
log.Hooks.Add(th)
|
||||
|
||||
return log
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@ -121,6 +122,50 @@ func (f JSONFormatter) Format(e *logrus.Entry) ([]byte, error) {
|
||||
|
||||
}
|
||||
|
||||
type TCPHook struct {
|
||||
Formatter logrus.Formatter
|
||||
MinLevel logrus.Level
|
||||
Net, Address string
|
||||
RetryInterval time.Duration
|
||||
conn net.Conn
|
||||
retry time.Time
|
||||
}
|
||||
|
||||
func (h *TCPHook) Levels() []logrus.Level {
|
||||
for i := range logrus.AllLevels { // assume it's ordered
|
||||
if logrus.AllLevels[i] == h.MinLevel {
|
||||
return logrus.AllLevels[:i]
|
||||
}
|
||||
}
|
||||
return logrus.AllLevels
|
||||
}
|
||||
|
||||
func (h *TCPHook) Fire(e *logrus.Entry) error {
|
||||
b, err := h.Formatter.Format(e)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if h.conn == nil {
|
||||
if time.Now().Sub(h.retry) < h.RetryInterval {
|
||||
return errors.New("TCP hook reconnect prohibited by retry interval")
|
||||
}
|
||||
h.conn, err = net.Dial(h.Net, h.Address)
|
||||
if err != nil {
|
||||
h.retry = time.Now()
|
||||
return errors.Wrap(err, "cannot dial")
|
||||
}
|
||||
}
|
||||
|
||||
_, err = h.conn.Write(b)
|
||||
if err != nil {
|
||||
h.conn.Close()
|
||||
h.conn = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type nopWriter int
|
||||
|
||||
func (w nopWriter) Write(p []byte) (n int, err error) { return len(p), nil }
|
||||
|
Loading…
Reference in New Issue
Block a user