logrjack

package module
v0.0.0-...-45aaa36 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 18, 2018 License: MIT Imports: 9 Imported by: 0

README

logrjack

GoDoc MIT License Go Report Card Build Status

Logrus (structured, leveled logging) and Lumberjack (rolling logs).

Example

package main

import (
	"errors"
	"fmt"
	"runtime"
	"time"

	log "github.com/judwhite/logrjack"
)

type fields map[string]interface{} // optional, makes the call the AddFields look nice

func main() {
	start := time.Now()

	// Setup the log file name, log rolling options
	log.Setup(log.Settings{
		Filename:    "example.log", // optional, defaults to ./logs/<procname>.log
		MaxSizeMB:   100,
		MaxAgeDays:  30,
		WriteStdout: true,
	})

	// Simple log message
	log.Info("Welcome!")

	// AddFields example
	entry := log.NewEntry()
	entry.AddFields(fields{
		"runtime_version": runtime.Version(),
		"arch":            runtime.GOARCH,
	})
	entry.Info("OK")

	// error/panic examples
	errorExamples()

	// AddField example
	entry = log.NewEntry()
	entry.AddField("uptime", time.Since(start))
	entry.Info("Shutting down.")
}

func errorExamples() {
	// Error and panic examples. You might use this in an HTTP handler for
	// errors, or as part of the middleware for panics.

	// numerator, denominator
	n, d := 10, 0

	// 'divide' panics, recovers, adds the callstack, and returns an error
	entry := log.NewEntry()
	if res, err := divide(n, d, entry); err != nil {
		entry.Error(err)
	} else {
		entry.Infof("%d/%d=%d", n, d, res)
	}

	// 'safeDivide' checks if d == 0. if so it adds the callstack and returns an error
	entry = log.NewEntry()
	if res, err := safeDivide(n, d, entry); err != nil {
		entry.Error(err)
	} else {
		entry.Infof("%d/%d=%d", n, d, res)
	}
}

func divide(n, d int, entry log.Entry) (res int, err error) {
	defer func() {
		perr := recover()
		if perr != nil {
			entry.AddCallstack()
			var ok bool
			err, ok = perr.(error)
			if ok {
				return
			}
			err = errors.New(fmt.Sprintf("%v", perr))
		}
	}()

	res = n / d
	return
}

func safeDivide(n, d int, entry log.Entry) (int, error) {
	if d == 0 {
		entry.AddCallstack()
		return 0, errors.New("d must not equal 0")
	}
	return n / d, nil
}

Outputs:

time="2016-03-04T02:29:30-06:00" level=info msg="Welcome!" 
time="2016-03-04T02:29:30-06:00" level=info msg=OK arch=amd64 runtime_version=go1.6 
time="2016-03-04T02:29:30-06:00" level=error msg="runtime error: integer divide by zero" callstack="logrjack_test/main.go:72, runtime/panic.go:426, runtime/panic.go:27, runtime/signal_windows.go:166, logrjack_test/main.go:82, logrjack_test/main.go:53, logrjack_test/main.go:36" 
time="2016-03-04T02:29:30-06:00" level=error msg="d must not equal 0" callstack="logrjack_test/main.go:88, logrjack_test/main.go:61, logrjack_test/main.go:36" 
time="2016-03-04T02:29:30-06:00" level=info msg="Shutting down." uptime=1.0001ms 

Output if d is changed to non-zero (the happy path):

time="2016-03-04T02:33:18-06:00" level=info msg="Welcome!" 
time="2016-03-04T02:33:18-06:00" level=info msg=OK arch=amd64 runtime_version=go1.6 
time="2016-03-04T02:33:18-06:00" level=info msg="10/5=2" 
time="2016-03-04T02:33:18-06:00" level=info msg="10/5=2" 
time="2016-03-04T02:33:18-06:00" level=info msg="Shutting down." uptime=1.0001ms 

Notes

This package is meant to output logfmt formatted text to a file and optionally stdout. It doesn't expose the hooks available in Logrus or extra features in Lumberjack.

Notable differences from Logrus:

  • Entry is an interface.
  • Instead of calling WithField and receiving *Entry, call AddField like above. The Logrus Entry is wrapped in an unexported type. The downside is you can't setup a base Entry to be passed to multiple routines which write their separate log entries from the same base. Call NewEntry and copy the values if you want this behavior.
  • A handy AddCallstack method, useful for logging errors and panics. It adds a key named callstack and is formatted dir/file.go:##, dir/file2.go:##. runtime/proc.go, http/server.go, and files which end in .s, such as runtime/asm_amd64.s, are omitted from the callstack. All other entries are included, including runtime/panic.go in a panic recovery.
  • AddField takes a map[string]interface{} so the interface can be implemented in a nested-vendor setup. You can create your own type as above to shorten the code.

Notable differences from Lumberjack:

  • If left unspecified, the default filename is <processpath>/logs/<processname>.log.

./vendor notes:

Why?

I got tired of copy-pasting this type of code all over the place. It's a convenience for myself, hopefully someone else will find it useful :)

License

MIT.

At the time of this writing both Logrus and Lumberjack are also licensed under MIT.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var FilterStackTrace = func(filename string) bool {
	return strings.HasSuffix(filename, ".s") ||
		strings.HasPrefix(filename, "http/server.go") ||
		strings.HasPrefix(filename, "runtime/proc.go") ||
		filename == "testing/testing.go"
}

FilterStackTrace is called by the StackTrace function to filter frames. This variable can be set to a custom function.

Functions

func Error

func Error(args ...interface{})

Error logs an Entry with a status of "error"

func Errorf

func Errorf(format string, args ...interface{})

Errorf logs an Entry with a status of "error"

func Fatal

func Fatal(args ...interface{})

Fatal logs an Entry with a status of "fatal" and exits the program with status code 1.

func Fatalf

func Fatalf(format string, args ...interface{})

Fatalf logs an Entry with a status of "fatal" and exits the program with status code 1.

func Info

func Info(args ...interface{})

Info logs an Entry with a status of "info"

func Infof

func Infof(format string, args ...interface{})

Infof logs an Entry with a status of "info"

func Setup

func Setup(settings Settings)

Setup initializes Logrus (structured logged) and Lumberjack (log rolling)

func Warn

func Warn(args ...interface{})

Warn logs an Entry with a status of "warn"

func Warnf

func Warnf(format string, args ...interface{})

Warnf logs an Entry with a status of "warn"

Types

type Entry

type Entry interface {
	// AddField adds a single field to the Entry.
	AddField(key string, value interface{})

	// AddFields adds a map of fields to the Entry.
	AddFields(fields map[string]interface{})

	// Info logs the Entry with a status of "info".
	Info(args ...interface{})
	// Infof logs the Entry with a status of "info".
	Infof(format string, args ...interface{})
	// Warn logs the Entry with a status of "warn".
	Warn(args ...interface{})
	// Warnf logs the Entry with a status of "warn".
	Warnf(format string, args ...interface{})
	// Error logs the Entry with a status of "error".
	Error(args ...interface{})
	// Errorf logs the Entry with a status of "error".
	Errorf(format string, args ...interface{})
	// Fatal logs the Entry with a status of "fatal" and calls os.Exit(1).
	Fatal(args ...interface{})
	// Fatalf logs the Entry with a status of "fatal" and calls os.Exit(1).
	Fatalf(format string, args ...interface{})

	// AddError adds a field "err" with the specified error.
	AddError(err error)

	String() string
}

Entry is the interface returned by NewEntry.

Use AddField or AddFields (opposed to Logrus' WithField) to add new fields to an entry.

To add source file and line information call AddCallstack.

Call the Info, Warn, Error, or Fatal methods to write the log entry.

func NewEntry

func NewEntry() Entry

NewEntry creates a new log Entry.

type Frame

type Frame interface {
	File() string
	Func() string
	Line() int
}

Frame contains information about a stack trace frame.

func StackTrace

func StackTrace(err error) []Frame

StackTrace returns the stack frames of an error created by github.com/pkg/errors. This function calls httplog.FilterStackTrace to filter frames.

type Settings

type Settings struct {
	// WriteStdout determines if the log will be written to Stdout. The default
	// is to only write to the log file. When running as a Windows Service make
	// sure not to write to Stdout.
	WriteStdout bool

	// Filename is the file to write logs to. Backup log files will be retained
	// in the same directory. It uses <processpath>/logs/<processname>.log if empty.
	Filename string `json:"filename" yaml:"filename"`

	// MaxSizeMB is the maximum size in megabytes of the log file before it gets
	// rotated. It defaults to 100 megabytes.
	MaxSizeMB int `json:"maxsize" yaml:"maxsize"`

	// MaxAgeDays is the maximum number of days to retain old log files based on the
	// timestamp encoded in their filename. Note that a day is defined as 24
	// hours and may not exactly correspond to calendar days due to daylight
	// savings, leap seconds, etc. The default is not to remove old log files
	// based on age.
	MaxAgeDays int `json:"maxage" yaml:"maxage"`

	// MaxBackups is the maximum number of old log files to retain. The default
	// is to retain all old log files (though MaxAgeDays may still cause them to get
	// deleted.)
	MaxBackups int `json:"maxbackups" yaml:"maxbackups"`

	// LocalTime determines if the time used for formatting the timestamps in
	// backup files is the computer's local time. The default is to use UTC
	// time.
	LocalTime bool `json:"localtime" yaml:"localtime"`
}

Settings specifies the options used to initialize Logrus and Lumberjack.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL