diff --git a/hooks/papertrail/papertrail.go b/hooks/papertrail/papertrail.go new file mode 100644 index 0000000..ca445bb --- /dev/null +++ b/hooks/papertrail/papertrail.go @@ -0,0 +1,61 @@ +package logrus_papertrail + +import ( + "fmt" + "net" + "os" + "time" + + "github.com/Sirupsen/logrus" +) + +const ( + format = "Jan 2 15:04:05" +) + +// PapertrailHook to send logs to a logging service compatible with the Papertrail API. +type PapertrailHook struct { + Host string + Port int + AppName string + UDPConn net.Conn +} + +// NewPapertrailHook creates a hook to be added to an instance of logger. +func NewPapertrailHook(host string, port int, appName string) (*PapertrailHook, error) { + conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", host, port)) + return &PapertrailHook{host, port, appName, conn}, err +} + +// Fire is called when a log event is fired. +func (hook *PapertrailHook) Fire(entry *logrus.Entry) error { + defer hook.UDPConn.Close() + date := time.Now().Format(format) + + line, err := entry.String() + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err) + return err + } + + payload := fmt.Sprintf("<22> %s %s: [%s] %s", date, hook.AppName, entry.Data["level"], line) + + _, err = hook.UDPConn.Write([]byte(payload)) + if err != nil { + fmt.Fprintf(os.Stderr, "Unable to send log line to Papertrail via UDP, %v", err) + return err + } + + return nil +} + +// Levels returns the available logging levels. +func (hook *PapertrailHook) Levels() []logrus.Level { + return []logrus.Level{ + logrus.Panic, + logrus.Fatal, + logrus.Error, + logrus.Warn, + logrus.Info, + } +} diff --git a/hooks/papertrail/papertrail_test.go b/hooks/papertrail/papertrail_test.go new file mode 100644 index 0000000..a52874c --- /dev/null +++ b/hooks/papertrail/papertrail_test.go @@ -0,0 +1,43 @@ +package logrus_papertrail + +import ( + "net" + "testing" + + "github.com/Sirupsen/logrus" +) + +func TestWritingToUDP(t *testing.T) { + log := logrus.New() + port := 16661 + + addr := net.UDPAddr{ + Port: port, + IP: net.ParseIP("127.0.0.1"), + } + + c, err := net.ListenUDP("udp", &addr) + if err != nil { + t.Fatalf("ListenUDP failed: %v", err) + } + defer c.Close() + + hook, err := NewPapertrailHook("localhost", port, "test") + if err != nil { + t.Errorf("Unable to connect to local UDP server.") + } + + log.Hooks.Add(hook) + log.Info("Today was a good day.") + + var buf = make([]byte, 1500) + n, _, err := c.ReadFromUDP(buf) + + if err != nil { + t.Fatalf("Error reading data from local UDP server") + } + + if n <= 0 { + t.Errorf("Nothing written to local UDP server.") + } +}