Skip to content

Commit

Permalink
Update Hook.Fire to redial on Write error and Update Hook.Levels to r…
Browse files Browse the repository at this point in the history
…eturn proper info

fix #2
  • Loading branch information
jonathan-robertson committed Jan 18, 2017
1 parent 13de9f2 commit 3c6bdcb
Showing 1 changed file with 49 additions and 24 deletions.
73 changes: 49 additions & 24 deletions logentrus.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,57 +7,82 @@ import (
"fmt"
"net"
"os"
"time"

"github.com/sirupsen/logrus"
)

// Hook used to send logs to logentries
type Hook struct {
Token string
Priority logrus.Level

levels []logrus.Level
token string
formatter *logrus.JSONFormatter
tlsConfig *tls.Config
conn net.Conn
}

const (
host = "data.logentries.com"
port = 443
host = "data.logentries.com"
port = 443
retryCount = 3
)

// New creates and returns a new hook for use in Logrus
func New(token, timestampFormat string, priority logrus.Level, config *tls.Config) (*Hook, error) {
func New(token, timestampFormat string, priority logrus.Level, config *tls.Config) (hook *Hook, err error) {
if token == "" {
return nil, fmt.Errorf("Unable to create new LogentriesHook since a Token is required")
}
err = fmt.Errorf("Unable to create new LogentriesHook since a Token is required")
} else {
hook = &Hook{
levels: logrus.AllLevels[:priority+1], // Include all levels at or within the provided priority
token: token,
tlsConfig: config,
formatter: &logrus.JSONFormatter{
TimestampFormat: timestampFormat,
},
}

tlsConn, err := tls.Dial("tcp", fmt.Sprintf("%s:%d", host, port), config)
hook := &Hook{
Priority: priority,
Token: token,
formatter: &logrus.JSONFormatter{TimestampFormat: timestampFormat},
conn: tlsConn,
err = hook.dial()
}

return hook, err
return
}

// Fire formats and sends JSON entry to Logentries service
func (hook *Hook) Fire(entry *logrus.Entry) error {
func (hook *Hook) Fire(entry *logrus.Entry) (err error) {
line, err := hook.format(entry)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
fmt.Fprintf(os.Stderr, "Unable to read entry | err: %v | entry: %+v\n", err, entry)
return err
}

if entry.Level <= hook.Priority {
if _, err := hook.conn.Write([]byte(hook.Token + line)); err != nil {
fmt.Fprintf(os.Stderr, "Unable to write to conn, %v", err)
return err
if err = hook.write(line); err != nil { // First write attempt
for i := 0; i < retryCount; i++ {
time.Sleep(time.Second) // Rest 1 second between retries
fmt.Fprintf(os.Stderr, "WARNING: Trouble writing to conn; retrying %d of %d | err: %v\n", i, retryCount, err)
if dialErr := hook.dial(); dialErr != nil { // Problem with write, so dial new connection and retry if possible
fmt.Fprintf(os.Stderr, "ERROR: Unable to dial new connection | dialErr: %v\n", dialErr)
return err
}
if err = hook.write(line); err == nil { // Retry write
break
}
}
}

return nil
if err != nil {
fmt.Fprintf(os.Stderr, "ERROR: Unable to write to conn | err: %v | line: %s\n", err, line)
}

return
}

func (hook *Hook) dial() (err error) {
hook.conn, err = tls.Dial("tcp", fmt.Sprintf("%s:%d", host, port), hook.tlsConfig)
return
}

func (hook Hook) write(line string) (err error) {
_, err = hook.conn.Write([]byte(hook.token + line))
return
}

func (hook Hook) format(entry *logrus.Entry) (string, error) {
Expand All @@ -71,5 +96,5 @@ func (hook Hook) format(entry *logrus.Entry) (string, error) {

// Levels returns the log levels supported by this hook
func (hook *Hook) Levels() []logrus.Level {
return logrus.AllLevels
return hook.levels
}

0 comments on commit 3c6bdcb

Please sign in to comment.