logger

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Dec 19, 2022 License: MIT Imports: 18 Imported by: 2

README

Logger Logo

made-with-Go Go Report Card Maintainability Test codecov go.dev reference

✏️ Logger

A Go wrapper for Logrus, Errors, Mongo and Facebook Workplace giving you extremely detailed log reports. This package is designed to be used with github.com/ainsleyclark/errors for error reporting with codes, messages and more.

Overview

  • ✅ Log a wide variety of log levels.
  • ✅ Logs with custom errors featuring codes, messages and lifelines.
  • ✅ Beautiful middleware and formatters for entries (see screenshots below).
  • ✅ Facebook Workplace integration, any error marked as INTERNAL will be sent to WP.
  • ✅ Mongo integration, if specified log entries will be sent to a Mongo collection.

Why?

Detailed and verbose logging is important to any application or API. This package aims to make it easy for APIs to log errors to a central location, using a Logrus Hook.

Workplace

Installation

go get -u github.com/ainsleyclark/logger
Quick Start

Get started with the Logger by calling logger.New() and creating new options. The service is required, this is the name of your currently running app.

func QuickStart() error {
	err := logger.New(context.TODO(), logger.NewOptions().Service("service"))
	if err != nil {
		return err
	}

	logger.Trace("Trace Entry")
	logger.Debug("Debug Entry")
	logger.Info("Info Entry")
	logger.Warn("Warn Entry")
	logger.Error("Error Entry")
	logger.WithError(errors.NewInternal(errors.New("error"), "message", "op")).Error()
	logger.Fatal("Fatal Entry")

	return nil
}

Outputs:

Logger Entries

Fields

Fields allow you to log out key value pairs to the logger that will appear under data. The simplest way to use the logger is simply the package-level exported logger.

func Fields() {
	logger.WithFields(types.Fields{
		"animal": "walrus",
	}).Info("A walrus appears")
}

Errors

This package is designed to work with [github.com/ainsleyclark/errors][https://github.com/ainsleyclark/errors] as such the WithError function can be used to log deatiled and rich error data.

func WithError() {
	logger.WithError(errors.NewInternal(errors.New("error"), "message", "op")).Error()
}

Middleware

Middleware is provided out of the box in the form of a fire hook. Upon receiving a request from the API, calling logger.Firewill send the log entry to stdout with detailed request information and meta.

func Middleware(r *http.Request) {
	logger.Fire(logger.FireHook{
		Request:      r,
		Status:       http.StatusOK,
		Message:      "Message from API",
		Data:         map[string]any{},
		RequestTime:  time.Now(),
		ResponseTime: time.Now(),
		Latency:      100,
	})
}

Recipes

Simple

Creates a simple logger with stdout.

func Simple() error {
	opts := logger.NewOptions().
		Service("service").
		Prefix("prefix").
		DefaultStatus("status")

	err := logger.New(context.Background(), opts)
	if err != nil {
		return err
	}

	logger.Info("Hello from Logger!")

	return nil
}
WithWorkplace

Create a logger with Facebook Workplace integration. A token and a thread are required to send any error code that has been marked as errors.INTERNAL to thread ID passed.

func WithWorkplace() error {
	opts := logger.NewOptions().
		Service("api").
		WithWorkplaceNotifier("token", "thread", nil, nil)

	err := logger.New(context.Background(), opts)
	if err != nil {
		return err
	}

	logger.Info("Hello from Logger!")

	return nil
}
Workplace CallBack

You can pass a function to WithWorkplaceNotifier as the second argument which is a callback function to determine if the log entry should be sent to a thread, an example is below:

func WithWorkplaceReport() {
	// Don't send the message to Workplace if there is no error.
	workplaceCallBack := func(entry types.Entry) bool {
		if !entry.HasError() {
			return false
		}
		return true
	}

	_ = logger.NewOptions().
	Service("api").
	WithWorkplaceNotifier("token", "thread", workplaceCallBack, nil)

	// etc
}
Workplace Formatter

You can pass a function to WithWorkplaceNotifier as the third argument which is a callback function to write the message to Workplace. This is where you can customise the message easily and return a formatted string.

func WithWorkplaceReport() {
	// Format the message with the supplied arguments.
	workplaceCallBack := func(entry types.Entry) bool {
		if !entry.HasError() {
			return false
		}
		return true
	}

	_ = logger.NewOptions().
	Service("api").
	WithWorkplaceNotifier("token", "thread", workplaceCallBack, nil)

	// etc
}

WithSlack

Create a logger with Facebook Slack integration. A token and a channel are required to send any error code that has been marked as errors.INTERNAL to thread ID passed.

Note All formatting and callbacks are available with Slack. See above for more details.

func WithSlack() error {
	opts := logger.NewOptions().
		Service("api").
		WithSlackNotifier("token", "#channel", nil, nil)

	err := logger.New(context.Background(), opts)
	if err != nil {
		return err
	}

	logger.Info("Hello from Logger!")

	return nil
}
WithMongo

Create a logger with Mongo integration. All logs are sent to the collection passed using github.com/ainsleyclark/mogurs.

func WithMongo() error {
	clientOptions := options.Client().
		ApplyURI(os.Getenv("MONGO_CONNECTION")).
		SetServerAPIOptions(options.ServerAPI(options.ServerAPIVersion1))

	client, err := mongo.Connect(context.Background(), clientOptions)
	if err != nil {
		log.Fatalln(err)
	}

	opts := logger.NewOptions().
		Service("api").
		WithMongoCollection(client.Database("logs").Collection("col"))

	err = logger.New(context.Background(), opts)
	if err != nil {
		return err
	}

	logger.Info("Hello from Logger!")

	return nil
}
Mongo CallBack

You can pass a function to WithWorkplaceNotifier as the second argument which is a callback function to determine if the log entry should be stored within Mongo, an example is below:

func WithMongoReport() {
	// Don't send the message to Mongo if there is no error.
	mongoCallBack := func(entry types.Entry) bool {
		if !entry.HasError() {
			return false
		}
		return true
	}

	client, err := mongo.Connect(context.Background(), options.Client().ApplyURI(os.Getenv("MONGO_CONNECTION")))
	if err != nil {
		log.Fatalln(err)
	}

	_ = logger.NewOptions().
	Service("api").
	WithMongoCollection(client.Database("logs").Collection("col"), mongoCallBack)

	// etc
}
KitchenSink

Boostrap all Log integrations.

func KitchenSink() error {
	clientOptions := options.Client().
		ApplyURI(os.Getenv("MONGO_CONNECTION")).
		SetServerAPIOptions(options.ServerAPI(options.ServerAPIVersion1))

	client, err := mongo.Connect(context.Background(), clientOptions)
	if err != nil {
		log.Fatalln(err)
	}

	opts := logger.NewOptions().
		Service("service").
		Prefix("prefix").
		DefaultStatus("status").
		WithWorkplaceNotifier("token", "thread").
		WithSlackNotifier("token", "#channel").
		WithMongoCollection(client.Database("logs").Collection("col"))

	err = logger.New(context.Background(), opts)
	if err != nil {
		return err
	}

	logger.Info("Hello from Logger!")

	return nil
}

Contributing

Please feel free to make a pull request if you think something should be added to this package!

Credits

Shout out to the incredible Maria Letta for her excellent Gopher illustrations.

Licence

Code Copyright 2022 Errors. Code released under the MIT Licence.

Documentation

Index

Constants

View Source
const (
	// DefaultPrefix is the default prefix used when none
	// is set.
	DefaultPrefix = "LOGGER"
	// DefaultStatus is the default status used when none
	// is set.
	DefaultStatus = "LOG"
)

Variables

View Source
var (
	// L is an alias for the standard logrus Logger.
	L = logrus.New()
)

Functions

func Debug

func Debug(args ...any)

Debug logs a debug message with args.

func Error

func Error(args ...any)

Error logs an error message with args.

func Fatal

func Fatal(args ...any)

Fatal logs a fatal message with args.

func Fire

func Fire(f FireHook)

Fire fires a FireHook to Logrus from a http request.

func Info

func Info(args ...any)

Info logs ab info message with args.

func New

func New(ctx context.Context, opts ...*Options) error

New creates a new standard L and sets logging levels dependent on environment variables.

func Panic

func Panic(args ...any)

Panic logs a panic message with args.

func SetLevel

func SetLevel(level logrus.Level)

SetLevel sets the level of the L.

func SetLogger

func SetLogger(l *logrus.Logger)

SetLogger sets the application L.

func SetOutput

func SetOutput(writer io.Writer)

SetOutput sets the output of the L to an io.Writer, useful for testing.

func Trace

func Trace(args ...any)

Trace logs a trace message with args.

func Warn

func Warn(args ...any)

Warn logs a warn message with args.

func WithError

func WithError(err any) *logrus.Entry

WithError - Logs with a custom error.

func WithField

func WithField(key string, value any) *logrus.Entry

WithField logs with field, sets a new map containing "fields".

func WithFields

func WithFields(fields types.Fields) *logrus.Entry

WithFields logs with fields, sets a new map containing "fields".

Types

type Config

type Config struct {
	// contains filtered or unexported fields
}

Config defines the configuration needed for creating a new Logger.

func (*Config) Validate

func (c *Config) Validate() error

Validate ensures the configuration is sanity checked before creating a new Logger.

type FireHook

type FireHook struct {
	Request      *http.Request
	Status       int
	Message      string
	Data         any
	RequestTime  time.Time
	ResponseTime time.Time
	Latency      float64
}

FireHook represents the data needed to log out a message or data for http Requests.

type Options

type Options struct {
	// contains filtered or unexported fields
}

Options is the type used to configure a new config instance.

func NewOptions

func NewOptions() *Options

NewOptions creates an empty Options instance.

func (*Options) DefaultStatus

func (op *Options) DefaultStatus(status string) *Options

DefaultStatus is the status code for HTTP requests when none is set.

func (*Options) Prefix

func (op *Options) Prefix(prefix string) *Options

Prefix is the string written to the log before any message.

func (*Options) Service

func (op *Options) Service(service string) *Options

Service is used for Mongo logging, and general stdout logs. This name will correlate to the name of the Mongo database, if WithMongoCollection is called.

func (*Options) Version

func (op *Options) Version(version string) *Options

Version is the currently running version of the service or application.

func (*Options) WithMongoCollection

func (op *Options) WithMongoCollection(collection *mongo.Collection, fn types.ShouldReportFunc) *Options

WithMongoCollection allows for logging directly to Mongo.

func (*Options) WithSlackNotifier added in v0.1.0

func (op *Options) WithSlackNotifier(token, channel string, fn types.ShouldReportFunc, formatter types.FormatMessageFunc) *Options

WithSlackNotifier sends errors that have been marked as errors.INTERNAL to a Workplace thread.

func (*Options) WithWorkplaceNotifier

func (op *Options) WithWorkplaceNotifier(token, thread string, fn types.ShouldReportFunc, formatter types.FormatMessageFunc) *Options

WithWorkplaceNotifier sends errors that have been marked as errors.INTERNAL to a Workplace thread.

Directories

Path Synopsis
gen
internal

Jump to

Keyboard shortcuts

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