Categorygithub.com/ainsleyclark/logger
modulepackage
0.1.0
Repository: https://github.com/ainsleyclark/logger.git
Documentation: pkg.go.dev

# 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.

# Packages

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Functions

Debug logs a debug message with args.
Error logs an error message with args.
Fatal logs a fatal message with args.
Fire fires a FireHook to Logrus from a http request.
Info logs ab info message with args.
New creates a new standard L and sets logging levels dependent on environment variables.
NewOptions creates an empty Options instance.
Panic logs a panic message with args.
SetLevel sets the level of the L.
SetLogger sets the application L.
SetOutput sets the output of the L to an io.Writer, useful for testing.
Trace logs a trace message with args.
Warn logs a warn message with args.
WithError - Logs with a custom error.
WithField logs with field, sets a new map containing "fields".
WithFields logs with fields, sets a new map containing "fields".

# Constants

DefaultPrefix is the default prefix used when none is set.
DefaultStatus is the default status used when none is set.

# Variables

L is an alias for the standard logrus Logger.

# Structs

No description provided by the author
FireHook represents the data needed to log out a message or data for http Requests.
Options is the type used to configure a new config instance.