traefik/vendor/github.com/gravitational/trace/udphook.go
2018-01-22 12:16:03 +01:00

112 lines
2.4 KiB
Go

package trace
import (
"encoding/json"
"net"
"time"
"github.com/jonboulle/clockwork"
log "github.com/sirupsen/logrus"
)
const (
// UDPDefaultAddr is a default address to emit logs to
UDPDefaultAddr = "127.0.0.1:5000"
// UDPDefaultNet is a default network
UDPDefaultNet = "udp"
)
// UDPOptionSetter represents functional arguments passed to ELKHook
type UDPOptionSetter func(f *UDPHook)
// NewUDPHook returns logrus-compatible hook that sends data to UDP socket
func NewUDPHook(opts ...UDPOptionSetter) (*UDPHook, error) {
f := &UDPHook{}
for _, o := range opts {
o(f)
}
if f.Clock == nil {
f.Clock = clockwork.NewRealClock()
}
if f.clientNet == "" {
f.clientNet = UDPDefaultNet
}
if f.clientAddr == "" {
f.clientAddr = UDPDefaultAddr
}
addr, err := net.ResolveUDPAddr(f.clientNet, f.clientAddr)
if err != nil {
return nil, Wrap(err)
}
conn, err := net.ListenPacket("udp", ":0")
if err != nil {
return nil, Wrap(err)
}
f.addr = addr
f.conn = conn.(*net.UDPConn)
return f, nil
}
type UDPHook struct {
Clock clockwork.Clock
clientNet string
clientAddr string
addr *net.UDPAddr
conn *net.UDPConn
}
type Frame struct {
Time time.Time `json:"time"`
Type string `json:"type"`
Entry map[string]interface{} `json:"entry"`
Message string `json:"message"`
Level string `json:"level"`
}
// Fire fires the event to the ELK beat
func (elk *UDPHook) Fire(e *log.Entry) error {
// Make a copy to safely modify
entry := e.WithFields(nil)
if frameNo := findFrame(); frameNo != -1 {
t := newTrace(frameNo-1, nil)
entry.Data[FileField] = t.String()
entry.Data[FunctionField] = t.Func()
}
data, err := json.Marshal(Frame{
Time: elk.Clock.Now().UTC(),
Type: "trace",
Entry: entry.Data,
Message: entry.Message,
Level: entry.Level.String(),
})
if err != nil {
return Wrap(err)
}
conn, err := net.ListenPacket("udp", ":0")
if err != nil {
return Wrap(err)
}
defer conn.Close()
resolvedAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:5000")
if err != nil {
return Wrap(err)
}
_, err = (conn.(*net.UDPConn)).WriteToUDP(data, resolvedAddr)
return Wrap(err)
}
// Levels returns logging levels supported by logrus
func (elk *UDPHook) Levels() []log.Level {
return []log.Level{
log.PanicLevel,
log.FatalLevel,
log.ErrorLevel,
log.WarnLevel,
log.InfoLevel,
log.DebugLevel,
}
}