sherlog

package module
v0.0.0-...-a635de9 Latest Latest
Warning

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

Go to latest
Published: Mar 15, 2025 License: MIT Imports: 11 Imported by: 8

README

sherlog CodeFactor GoDoc Build Status Go Report Card

A simple logging library designed to be robust and performant. It's complete with exceptions and automatic stack traces. Creating an exception with a stack trace is about five to six times faster than in Java (Benchmarks at bottom of readme).

Quick Start

Requires go 1.10 or higher! Go get the package:

go get github.com/Nick-Anderssohn/sherlog
Adding to an Existing Project

You most likely are grabbing errors like this:

err := someFunc()
if err != nil {
    return err
}

And then you are probably logging the error somewhere higher up in your code:

log.Println(err)

If so, your error is being logged like this:

2018/08/25 19:28:37 your error message

To get levels and stack traces added, all you have to do is use the AsCritical, AsError, AsOpsError, AsWarning, AsInfo, and AsDebug functions. These functions graduate an error to a LeveledException, which creates a stack trace upon creation. For example, to give err the log level ERROR and give it a stack trace, all you have to do is change the code to this:

err := someFunc()
if err != nil {
    return sherlog.AsError(err)
}

There is no need to change the return type of your function, AsError and the others have a return type of error. You don't have to change whatever logging code you are already using:

log.Println(err)

Now, the error will automatically be logged like this:

2018/08/25 19:28:37  - ERROR - your error message:
	something.WhateverFuncCalledAsError(/home/nick/go/src/something/something.go:57)
	something.Blah(/home/nick/go/src/something/something.go:777)
	something.Wonkers(/home/nick/go/src/something/something.go:2361)

That's it! That is all you need to do to get stack traces and levels added to your existing project 🙂 In the future, I will add a gui to display, sort, search, and do whatever with your logs. So I recommend you also switch to my logger which is documented below.

Using sherlog.Logger

The sherlog.Logger interface is simple:

type Logger interface {
	Log(loggable Loggable) error
	Close()
}

sherlog offers a couple implementations of this. If you just want one log file, use sherlog.FileLogger or sherlog.RollingFileLogger. If you want different log files for different log levels/combinations of log levels, use sherlog.MultiFileLogger. Check out the GoDocs for those. I recommend having one singleton instance that you use for logging over your entire project. In the future, I will make an implementation of sherlog.Logger that automatically sends logs to a gui, so it will be easy to add to your project.

Log Levels

It is completely optional to use the default log levels I created. You can create your own by implementing this interface:

/**
An interface used to specify the log level on an exception/error.
LevelId is meant to be something along the lines of an enum, so
that we don't have to switch based off of the string value of the
log level. Label is the string representation.
 */
type Level interface {
	GetLevelId() int
	GetLabel() string
}

Of course, then you won't be able to use functions like AsError. You will have to manually create the error like this:

NewLeveledException("your error message", YourCustomeLogLevel)
Why use my log levels

However, I do believe the log levels I chose create a great logging system. Here are what the different levels are intended for:

CRITICAL

CRITICAL is the intended log level for panics that are caught in the recover function.

ERROR

ERROR is the intended log level for something that should never ever happen and for sure means there is a bug in your code.

OPS_ERROR

OPS_ERROR is the intended log level for an error that is known to be possible due to an operations issue. For example, failing to query a database should be an OpsError because it lets you know that your database is offline. It doesn't mean there is a bug in your code, but it is still something that needs to be fixed asap.

WARNING

WARNING is the intended log level for something that doesn't cause failure, but may be frowned upon or bad anyways. For example, use of a deprecated endpoint may be logged as a warning. Or, a slow query could be a warning. A warning should say, "Hey, this is bad, but not a failure."

INFO

INFO is the intended log level for something that you want logged purely to collect information or metrics.

DEBUG

DEBUG is for any debug messages you want logged. Ideally, you are not logging these in production.

Distinguish between ERROR and OPS_ERROR

It is especially important to distinguish between ERROR and OPS_ERROR. The goal is to limit things marked with ERROR to only be messages that 100% indicate a bug in the code. OPS_ERROR may indicate an ops issue like something being offline...If there is a case where an error could indicate either a bug in the code or an ops error, then choose ops error.

Benchmarks

All benchmarks ran on my desktop with Intel® Core™ i7-6700 CPU @ 3.40GHz × 8 running Ubuntu 18.04.1 LTS. The benchmark for getting a stack trace in go was:

goos: linux
goarch: amd64
pkg: sherlog
BenchmarkGetStackTrace-8   	 1000000	      1580 ns/op
PASS

The benchmark for getting a stack trace in Java was:

Benchmark                                Mode  Cnt     Score     Error  Units
StackTraceBenchmark.BenchmarkStackTrace  avgt   30  9197.803 ± 134.794  ns/op

The code for the java benchmark is here

GoDocs

See the auto-generated documentation here

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	/*Location holds the location that all timestamps/time related things will use.
	All timestamps and time-based logging will use this location.
	Defaults to UTC. Can set to a different zone from the IANA Time Zone database.
	For example, if you want pacific time, you can do:
		sherlog.Location, _ = time.LoadLocation("America/Los_Angeles")
	Wikipedia has a good list of IANA time zones: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones*/
	Location = time.UTC
)

Functions

func AsCritical

func AsCritical(values ...interface{}) error

AsCritical graduates a normal error to a LeveledException with error level CRITICAL. If err is already a LevelWrapper, then it's level will be changed to CRITICAL without overriding the stack trace. As of 1.7.0: if multiple values are passed in, then they will be concatenated before returning the error.

func AsDebug

func AsDebug(values ...interface{}) error

AsDebug graduates a normal error to a LeveledException with error level DEBUG. If err is already a LevelWrapper, then it's level will be changed to DEBUG without overriding the stack trace. As of 1.7.0: if multiple values are passed in, then they will be concatenated before returning the error.

func AsError

func AsError(values ...interface{}) error

AsError graduates a normal error to a LeveledException with error level ERROR. If err is already a LevelWrapper, then it's level will be changed to ERROR without overriding the stack trace. As of 1.7.0: if multiple values are passed in, then they will be concatenated before returning the error.

func AsInfo

func AsInfo(values ...interface{}) error

AsInfo graduates a normal error to a LeveledException with error level INFO. If err is already a LevelWrapper, then it's level will be changed to INFO without overriding the stack trace. As of 1.7.0: if multiple values are passed in, then they will be concatenated before returning the error.

func AsOpsError

func AsOpsError(values ...interface{}) error

AsOpsError graduates a normal error to a LeveledException with error level OPS_ERROR. If err is already a LevelWrapper, then it's level will be changed to OPS_ERROR without overriding the stack trace. As of 1.7.0: if multiple values are passed in, then they will be concatenated before returning the error.

func AsWarning

func AsWarning(values ...interface{}) error

AsWarning graduates a normal error to a LeveledException with error level WARNING. If err is already a LevelWrapper, then it's level will be changed to WARNING without overriding the stack trace. As of 1.7.0: if multiple values are passed in, then they will be concatenated before returning the error.

func NewCritical

func NewCritical(message string) error

NewCritical returns a new LeveledException with the level set to CRITICAL.

func NewDebug

func NewDebug(message string) error

NewDebug returns a new LeveledException with the level set to DEBUG.

func NewError

func NewError(message string) error

NewError returns a new LeveledException with the level set to ERROR.

func NewInfo

func NewInfo(message string) error

NewInfo returns a new LeveledException with the level set to INFO.

func NewLeveledException

func NewLeveledException(message string, level Level) error

NewLeveledException creates a new LeveledException. A stack trace is created immediately. Stack trace depth is limited to 64 by default.

The stack trace does not get converted to a string until GetStackTraceAsString is called. Waiting to do this until it actually gets logged vastly improves performance. I have noticed a performance of about 2000 ns/op for this function on my desktop with Intel® Core™ i7-6700 CPU @ 3.40GHz × 8 running Ubuntu 18.04.1. This is about 5x faster than creating an exception in Java.

func NewLeveledExceptionWithStackTraceSize

func NewLeveledExceptionWithStackTraceSize(message string, level Level, maxStackTraceDepth int) error

NewLeveledExceptionWithStackTraceSize creates a new LeveledException. A stack trace is created immediately. Stack trace depth is limited to maxStackTraceDepth.

The stack trace does not get converted to a string until GetStackTraceAsString is called. Waiting to do this until it actually gets logged vastly improves performance. I have noticed a performance of about 2000 ns/op for this function on my desktop with Intel® Core™ i7-6700 CPU @ 3.40GHz × 8 running Ubuntu 18.04.1. This is about 5x faster than creating an exception in Java.

func NewOpsError

func NewOpsError(message string) error

NewOpsError returns a new LeveledException with the level set to OPS_ERROR.

func NewStdException

func NewStdException(message string) error

NewStdException creates a new exception. A stack trace is created immediately. Stack trace depth is limited to 64 by default.

The stack trace does not get converted to a string until GetStackTraceAsString is called. Waiting to do this until it actually gets logged vastly improves performance. I have noticed a performance of about 1800 ns/op to 2000 ns/op for this function on my desktop with Intel® Core™ i7-6700 CPU @ 3.40GHz × 8 running Ubuntu 18.04.1. This is about 5x faster than creating an exception in Java.

func NewStdExceptionWithStackTraceSize

func NewStdExceptionWithStackTraceSize(message string, stackTraceNumLines int) error

NewStdExceptionWithStackTraceSize creates a new exception. A stack trace is created immediately. stackTraceNumLines allows you to limit the depth of the stack trace.

The stack trace does not get converted to a string until GetStackTraceAsString is called. Waiting to do this until it actually gets logged vastly improves performance. I have noticed a performance of about 1800 ns/op to 2000 ns/op for this function on my desktop with Intel® Core™ i7-6700 CPU @ 3.40GHz × 8 running Ubuntu 18.04.1. This is about 5x faster than creating an exception in Java.

func NewWarning

func NewWarning(message string) error

NewWarning returns a new LeveledException with the level set to WARNING.

func PrependMsg

func PrependMsg(err error, msg string) error

prependMsg adds a message to your error:

timestamp - yourNewMsg
Caused by:
Your existing error....

Types

type FileLogger

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

FileLogger logs exceptions to a single file path. Writes are not buffered. Opens and closes per exception written.

func NewFileLogger

func NewFileLogger(logFilePath string) (*FileLogger, error)

NewFileLogger create a new FileLogger that will write to logFilePath. Will append to the file if it already exists. Will create it if it doesn't.

func (*FileLogger) Close

func (l *FileLogger) Close()

Close closes the file writer.

func (*FileLogger) Critical

func (l *FileLogger) Critical(values ...interface{}) error

Critical turns values into a *LeveledException with level CRITICAL and then calls the logger's Log function.

func (*FileLogger) Debug

func (l *FileLogger) Debug(values ...interface{}) error

Debug turns values into a *LeveledException with level DEBUG and then calls the logger's Log function.

func (*FileLogger) Error

func (l *FileLogger) Error(values ...interface{}) error

Error turns values into a *LeveledException with level ERROR and then calls the logger's Log function.

func (*FileLogger) Info

func (l *FileLogger) Info(values ...interface{}) error

Info turns values into a *LeveledException with level INFO and then calls the logger's Log function.

func (*FileLogger) Log

func (l *FileLogger) Log(errorsToLog ...interface{}) error

Log calls loggable's Log function. Is thread safe :) Non-sherlog errors get logged with only timestamp and message

func (*FileLogger) LogJson

func (l *FileLogger) LogJson(errToLog error) error

LogJson calls loggable's LogJson function. Is thread safe :) Non-sherlog errors get logged with only timestamp and message

func (*FileLogger) LogNoStack

func (l *FileLogger) LogNoStack(errToLog error) error

LogNoStack calls loggable's LogNoStack function. Is thread safe :) Non-sherlog errors get logged with only timestamp and message

func (*FileLogger) OpsError

func (l *FileLogger) OpsError(values ...interface{}) error

OpsError turns values into a *LeveledException with level OPS_ERROR and then calls the logger's Log function.

func (*FileLogger) Warn

func (l *FileLogger) Warn(values ...interface{}) error

Warn turns values into a *LeveledException with level WARNING and then calls the logger's Log function.

type JsonLoggable

type JsonLoggable interface {
	error
	LogAsJson(writer io.Writer) error
}

JsonLoggable should be implemented by something for it to be loggable by a Logger's LogJson function

type Level

type Level interface {
	GetLevelId() int
	GetLabel() string
}

Level is an interface used to specify the log level on an exception/error. LevelId is meant to be something along the lines of an enum, so that we don't have to switch based off of the string value of the log level. Label is the string representation.

type LevelEnum

type LevelEnum int

LevelEnum is the default enum sherlog offers that implements Level

const (
	/*
		CRITICAL is the intended log level for panics that are caught in the recover function.
	*/
	EnumCritical LevelEnum = iota

	/*
		ERROR is the intended log level for something that should never ever happen and for sure
		means there is a bug in your code.
	*/
	EnumError

	/*
		OPS_ERROR is the intended log level for an error that is known to be possible due to an operations issue.
		For example, failing to query a database should be an OpsError because it lets you know that your database is
		offline. It doesn't mean there is a bug in your code, but it is still something that needs to be fixed asap.
	*/
	EnumOpsError

	/*
		WARNING is the intended log level for something that doesn't cause failure, but may be frowned
		upon anyways. For example, use of a deprecated endpoint may be logged as a warning. A warning should say,
		"Hey, we don't want to be doing this. It works, but it is bad."
	*/
	EnumWarning

	/*
		INFO is the intended log level for something that you want logged purely to collect information or metrics.
	*/
	EnumInfo

	/*
		DEBUG is for any debug messages you want logged. Ideally, you are not logging these in production.
	*/
	EnumDebug
)

Default log level enums that implement Level. These are my recommended log levels, but you can create different ones simply by implementing the Level interface if you would like.

func (LevelEnum) GetLabel

func (le LevelEnum) GetLabel() string

GetLabel returns the text representation of the LevelEnum. For example, EnumError returns ERROR.

func (LevelEnum) GetLevelId

func (le LevelEnum) GetLevelId() int

GetLevelId returns the integer value of the LevelEnum.

type LevelWrapper

type LevelWrapper interface {
	GetLevel() Level
	SetLevel(level Level)
}

LevelWrapper is something that holds a modifiable log level.

type LeveledException

type LeveledException struct {
	// If we really really wanted to, we could save about 100 ns/op in the constructor if we changed
	// the embedded StdException into a pointer/not-embedded field (so stdException *StdException)
	StdException
	// contains filtered or unexported fields
}

LeveledException is an exception with a level such as ERROR or WARNING. StdException is embedded. Implements error, LevelWrapper, Loggable, StackTraceWrapper, and LeveledLoggable.

func (*LeveledException) Error

func (le *LeveledException) Error() string

Error returns the message and stack trace in a string formatted like this:

LEVEL - message:
	sherlog.exampleFunc(exampleFile.go:18)
	sherlog.exampleFunc2(exampleFile2.go:46)
	sherlog.exampleFunc3(exampleFile2.go:177)

Leaves out the timestamp so that LeveledException will print nicely with log.Println

func (*LeveledException) GetLevel

func (le *LeveledException) GetLevel() Level

GetLevel returns the level.

func (*LeveledException) Log

func (le *LeveledException) Log(writer io.Writer) error

Log writes to the writer a string formatted as:

yyyy-mm-dd hh:mm:ss - LEVEL - message:
	sherlog.exampleFunc(exampleFile.go:18)
	sherlog.exampleFunc2(exampleFile2.go:46)
	sherlog.exampleFunc3(exampleFile2.go:177)

Returns the string that was logged or an error if there was one.

func (*LeveledException) LogAsJson

func (le *LeveledException) LogAsJson(writer io.Writer) error

LogAsJson packages up the exception's info into json and writes it to writer.

The json is formatted like this

{
   "Level":"INFO",
   "Message":"I'm informative!",
   "StackTrace":[
	  {
		 "FunctionName":"github.com/Nick-Anderssohn/sherlog.TestLogJson",
		 "File":"/home/nick/go/src/github.com/Nick-Anderssohn/sherlog/scratch_test.go",
		 "Line":68
	  },
	  {
		 "FunctionName":"testing.tRunner",
		 "File":"/usr/local/go/src/testing/testing.go",
		 "Line":777
	  },
	  {
		 "FunctionName":"runtime.goexit",
		 "File":"/usr/local/go/src/runtime/asm_amd64.s",
		 "Line":2361
	  }
   ],
   "StackTraceStr":"\tgithub.com/Nick-Anderssohn/sherlog.TestLogJson(/home/nick/go/src/github.com/Nick-Anderssohn/sherlog/scratch_test.go:68)\n\ttesting.tRunner(/usr/local/go/src/testing/testing.go:777)\n\truntime.goexit(/usr/local/go/src/runtime/asm_amd64.s:2361)\n",
   "Time":"2018-10-03 07:51:14"
}

Returns an error if there was one.

func (*LeveledException) LogNoStack

func (le *LeveledException) LogNoStack(writer io.Writer) error

LogNoStack writes to the writer a string formatted as:

yyyy-mm-dd hh:mm:ss - LEVEL - message

Note that it does not have the stack trace. Returns the string that was logged or an error if there was one.

func (*LeveledException) SetLevel

func (le *LeveledException) SetLevel(level Level)

SetLevel sets the level.

func (*LeveledException) ToJsonBytes

func (le *LeveledException) ToJsonBytes() ([]byte, error)

ToJsonBytes returns the bytes for a json blob that looks like this:

{
   "Level":"INFO",
   "Message":"I'm informative!",
   "StackTrace":[
	  {
		 "FunctionName":"github.com/Nick-Anderssohn/sherlog.TestLogJson",
		 "File":"/home/nick/go/src/github.com/Nick-Anderssohn/sherlog/scratch_test.go",
		 "Line":68
	  },
	  {
		 "FunctionName":"testing.tRunner",
		 "File":"/usr/local/go/src/testing/testing.go",
		 "Line":777
	  },
	  {
		 "FunctionName":"runtime.goexit",
		 "File":"/usr/local/go/src/runtime/asm_amd64.s",
		 "Line":2361
	  }
   ],
   "StackTraceStr":"\tgithub.com/Nick-Anderssohn/sherlog.TestLogJson(/home/nick/go/src/github.com/Nick-Anderssohn/sherlog/scratch_test.go:68)\n\ttesting.tRunner(/usr/local/go/src/testing/testing.go:777)\n\truntime.goexit(/usr/local/go/src/runtime/asm_amd64.s:2361)\n",
   "Time":"2018-10-03 07:51:14"
}

func (*LeveledException) ToJsonMap

func (le *LeveledException) ToJsonMap() map[string]interface{}

ToJsonMap creates a map[string]interface{} that, when compiled to json, looks like this:

{
   "Level":"INFO",
   "Message":"I'm informative!",
   "StackTrace":[
	  {
		 "FunctionName":"github.com/Nick-Anderssohn/sherlog.TestLogJson",
		 "File":"/home/nick/go/src/github.com/Nick-Anderssohn/sherlog/scratch_test.go",
		 "Line":68
	  },
	  {
		 "FunctionName":"testing.tRunner",
		 "File":"/usr/local/go/src/testing/testing.go",
		 "Line":777
	  },
	  {
		 "FunctionName":"runtime.goexit",
		 "File":"/usr/local/go/src/runtime/asm_amd64.s",
		 "Line":2361
	  }
   ],
   "StackTraceStr":"\tgithub.com/Nick-Anderssohn/sherlog.TestLogJson(/home/nick/go/src/github.com/Nick-Anderssohn/sherlog/scratch_test.go:68)\n\ttesting.tRunner(/usr/local/go/src/testing/testing.go:777)\n\truntime.goexit(/usr/local/go/src/runtime/asm_amd64.s:2361)\n",
   "Time":"2018-10-03 07:51:14"
}

type LeveledLoggable

type LeveledLoggable interface {
	Loggable
	GetLevel() Level
}

LeveledLoggable is a Loggable that also has a log level attached to it.

type Loggable

type Loggable interface {
	error
	Log(writer io.Writer) error
}

Loggable should be implemented by something for it to be loggable by a Logger's Log function

type LoggableWithNoStackOption

type LoggableWithNoStackOption interface {
	Loggable
	LogNoStack(writer io.Writer) error
}

LoggableWithNoStackOption should be implemented by something for it to be loggable by a Logger's LogNoStack function

type Logger

type Logger interface {
	Log(errorsToLog ...interface{}) error
	Close()
	LogNoStack(errToLog error) error
	LogJson(errToLog error) error
	Critical(values ...interface{}) error
	Error(values ...interface{}) error
	OpsError(values ...interface{}) error
	Warn(values ...interface{}) error
	Info(values ...interface{}) error
	Debug(values ...interface{}) error
}

Logger is an interface representing a Logger that can call all of a Loggable's log functions.

type MultiFileLogger

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

MultiFileLogger logs to multiple files based off of level. If you provide the same path for multiple log levels, then they will be logged to that same file with no problems.

Is thread safe :)

func CreateDefaultMultiFileLogger

func CreateDefaultMultiFileLogger(criticalPath, errorPath, warningPath, infoPath, debugPath, defaultPath string) (*MultiFileLogger, error)

CreateDefaultMultiFileLogger creates a MultiFileLogger setup to use the default Levels that this package provides.

func NewMultiFileLogger

func NewMultiFileLogger(paths map[Level]string, defaultLogPath string) (*MultiFileLogger, error)

NewMultiFileLogger returns a new file logger. Will log to different files based off of the paths given for each log level. If you want some log levels to be logged to the same file, just pass in the same path for those levels. defaultLogPath is the file to log to if a Loggable is provided that does not have a level.

func NewMultiFileLoggerRoleNightly

func NewMultiFileLoggerRoleNightly(paths map[Level]string, defaultLogPath string) (*MultiFileLogger, error)

NewMultiFileLoggerRoleNightly returns a new MultiFileLogger. Logs will roll daily (at midnight).

func NewMultiFileLoggerRollOnDuration

func NewMultiFileLoggerRollOnDuration(paths map[Level]string, defaultLogPath string, duration time.Duration) (*MultiFileLogger, error)

NewMultiFileLoggerRollOnDuration returns a new MultiFileLogger. Logs will roll every duration.

func NewMultiFileLoggerWithSizeBaseRollingLogs

func NewMultiFileLoggerWithSizeBaseRollingLogs(paths map[Level]string, defaultLogPath string, maxLogMessagesPerLogFile int) (*MultiFileLogger, error)

NewMultiFileLoggerWithSizeBaseRollingLogs returns a new MultiFileLogger. Logs will roll when they maxLogMessagesPerLogFile

func (*MultiFileLogger) Close

func (mfl *MultiFileLogger) Close()

Close closes all loggers.

func (*MultiFileLogger) Critical

func (mfl *MultiFileLogger) Critical(values ...interface{}) error

Critical turns values into a *LeveledException with level CRITICAL and then calls the logger's Log function.

func (*MultiFileLogger) Debug

func (mfl *MultiFileLogger) Debug(values ...interface{}) error

Debug turns values into a *LeveledException with level DEBUG and then calls the logger's Log function.

func (*MultiFileLogger) Error

func (mfl *MultiFileLogger) Error(values ...interface{}) error

Error turns values into a *LeveledException with level ERROR and then calls the logger's Log function.

func (*MultiFileLogger) ErrorIsLoggable

func (mfl *MultiFileLogger) ErrorIsLoggable(err error) bool

ErrorIsLoggable checks if an error is loggable by MultiFileLogger

func (*MultiFileLogger) Info

func (mfl *MultiFileLogger) Info(values ...interface{}) error

Info turns values into a *LeveledException with level INFO and then calls the logger's Log function.

func (*MultiFileLogger) Log

func (mfl *MultiFileLogger) Log(errToLog error) error

Log logs the error. If not a sherlog error, will just be logged with a timestamp and message.

Is thread safe :)

func (*MultiFileLogger) LogJson

func (mfl *MultiFileLogger) LogJson(errToLog error) error

LogJson logs the error as a json blob. If not a sherlog error, will just include message.

Is thread safe :)

func (*MultiFileLogger) LogNoStack

func (mfl *MultiFileLogger) LogNoStack(errToLog error) error

LogNoStack logs the error without the stack trace.

Is thread safe :)

func (*MultiFileLogger) OpsError

func (mfl *MultiFileLogger) OpsError(values ...interface{}) error

OpsError turns values into a *LeveledException with level OPS_ERROR and then calls the logger's Log function.

func (*MultiFileLogger) Warn

func (mfl *MultiFileLogger) Warn(values ...interface{}) error

Warn turns values into a *LeveledException with level WARNING and then calls the logger's Log function.

type PolyLogger

type PolyLogger struct {
	Loggers []Logger
	// contains filtered or unexported fields
}

PolyLogger is a simple container for multiple loggers. Will call all of the loggers' log functions every time something needs to be logged.

func NewPolyLogger

func NewPolyLogger(loggers []Logger) *PolyLogger

NewPolyLogger creates a new PolyLogger. loggers are all the loggers that will be used during logging. If a logger fails when logging something, log.Println will be used to log the error that the logger returned. Returns a new PolyLogger.

func NewPolyLoggerWithHandleLoggerFail

func NewPolyLoggerWithHandleLoggerFail(loggers []Logger, handleLoggerFail func(error)) *PolyLogger

NewPolyLoggerWithHandleLoggerFail creates a new PolyLogger. loggers are all the loggers that will be used during logging. handleLoggerFail is run whenever one of those loggers returns an error while logging something (indicating that it failed to log the message). Returns a new PolyLogger

func (*PolyLogger) Close

func (p *PolyLogger) Close()

Close asynchronously runs all loggers' Close functions.

func (*PolyLogger) Critical

func (p *PolyLogger) Critical(values ...interface{}) error

Critical turns values into a *LeveledException with level CRITICAL and then calls the logger's Log function.

func (*PolyLogger) Debug

func (p *PolyLogger) Debug(values ...interface{}) error

Debug turns values into a *LeveledException with level DEBUG and then calls the logger's Log function.

func (*PolyLogger) Error

func (p *PolyLogger) Error(values ...interface{}) error

Error turns values into a *LeveledException with level ERROR and then calls the logger's Log function.

func (*PolyLogger) Info

func (p *PolyLogger) Info(values ...interface{}) error

Info turns values into a *LeveledException with level INFO and then calls the logger's Log function.

func (*PolyLogger) Log

func (p *PolyLogger) Log(errorsToLog ...interface{}) error

Log asynchronously runs all logger's Log functions. Handles any errors in the logging process with handleLoggerFail. Will always return nil.

func (*PolyLogger) LogJson

func (p *PolyLogger) LogJson(errToLog error) error

LogJson asynchronously runs all logger's LogJson functions. Will ignore any Loggers that are not RobustLoggers. Handles any errors in the logging process with handleLoggerFail. Will always return nil.

func (*PolyLogger) LogNoStack

func (p *PolyLogger) LogNoStack(errToLog error) error

LogNoStack asynchronously runs all logger's LogNoStack functions. Will ignore any Loggers that are not RobustLoggers. Handles any errors in the logging process with handleLoggerFail. Will always return nil.

func (*PolyLogger) OpsError

func (p *PolyLogger) OpsError(values ...interface{}) error

OpsError turns values into a *LeveledException with level OPS_ERROR and then calls the logger's Log function.

func (*PolyLogger) Warn

func (p *PolyLogger) Warn(values ...interface{}) error

Warn turns values into a *LeveledException with level WARNING and then calls the logger's Log function.

type RollingFileLogger

type RollingFileLogger struct {
	FileLogger
	// contains filtered or unexported fields
}

RollingFileLogger is a logger that will automatically start a new log file after a certain amount of time

func NewCustomRollingFileLogger

func NewCustomRollingFileLogger(logFilePath string, duration time.Duration) (*RollingFileLogger, error)

NewCustomRollingFileLogger is a logger that rolls every duration. Starts timer upon instantiation

func NewNightlyRollingFileLogger

func NewNightlyRollingFileLogger(logFilePath string) (*RollingFileLogger, error)

NewNightlyRollingFileLogger is a logger that rolls at midnight.

func (*RollingFileLogger) Close

func (rfl *RollingFileLogger) Close()

Close closes the file writer.

func (*RollingFileLogger) Critical

func (rfl *RollingFileLogger) Critical(values ...interface{}) error

Critical turns values into a *LeveledException with level CRITICAL and then calls the logger's Log function.

func (*RollingFileLogger) Debug

func (rfl *RollingFileLogger) Debug(values ...interface{}) error

Debug turns values into a *LeveledException with level DEBUG and then calls the logger's Log function.

func (*RollingFileLogger) Error

func (rfl *RollingFileLogger) Error(values ...interface{}) error

Error turns values into a *LeveledException with level ERROR and then calls the logger's Log function.

func (*RollingFileLogger) Info

func (rfl *RollingFileLogger) Info(values ...interface{}) error

Info turns values into a *LeveledException with level INFO and then calls the logger's Log function.

func (*RollingFileLogger) OpsError

func (rfl *RollingFileLogger) OpsError(values ...interface{}) error

OpsError turns values into a *LeveledException with level OPS_ERROR and then calls the logger's Log function.

func (*RollingFileLogger) Warn

func (rfl *RollingFileLogger) Warn(values ...interface{}) error

Warn turns values into a *LeveledException with level WARNING and then calls the logger's Log function.

type SizeBasedRollingFileLogger

type SizeBasedRollingFileLogger struct {
	RollingFileLogger
	// contains filtered or unexported fields
}

SizeBasedRollingFileLogger is a logger that rolls files when they hit a certain number of log messages.

func NewRollingFileLoggerWithSizeLimit

func NewRollingFileLoggerWithSizeLimit(logFilePath string, numMessagesPerFile int) (*SizeBasedRollingFileLogger, error)

NewRollingFileLoggerWithSizeLimit creates logs that roll when numMessagesPerFile is hit.

func (*SizeBasedRollingFileLogger) Critical

func (rfl *SizeBasedRollingFileLogger) Critical(values ...interface{}) error

Critical turns values into a *LeveledException with level CRITICAL and then calls the logger's Log function.

func (*SizeBasedRollingFileLogger) Debug

func (rfl *SizeBasedRollingFileLogger) Debug(values ...interface{}) error

Debug turns values into a *LeveledException with level DEBUG and then calls the logger's Log function.

func (*SizeBasedRollingFileLogger) Error

func (rfl *SizeBasedRollingFileLogger) Error(values ...interface{}) error

Error turns values into a *LeveledException with level ERROR and then calls the logger's Log function.

func (*SizeBasedRollingFileLogger) Info

func (rfl *SizeBasedRollingFileLogger) Info(values ...interface{}) error

Info turns values into a *LeveledException with level INFO and then calls the logger's Log function.

func (*SizeBasedRollingFileLogger) Log

func (rfl *SizeBasedRollingFileLogger) Log(errorsToLog ...interface{}) error

Log calls loggable's Log function. Is thread safe :)

func (*SizeBasedRollingFileLogger) LogJson

func (rfl *SizeBasedRollingFileLogger) LogJson(errToLog error) error

LogJson calls loggable's LogJson function. Is thread safe :)

func (*SizeBasedRollingFileLogger) LogNoStack

func (rfl *SizeBasedRollingFileLogger) LogNoStack(errToLog error) error

LogNoStack calls loggable's LogNoStack function. Is thread safe :)

func (*SizeBasedRollingFileLogger) OpsError

func (rfl *SizeBasedRollingFileLogger) OpsError(values ...interface{}) error

OpsError turns values into a *LeveledException with level OPS_ERROR and then calls the logger's Log function.

func (*SizeBasedRollingFileLogger) Warn

func (rfl *SizeBasedRollingFileLogger) Warn(values ...interface{}) error

Warn turns values into a *LeveledException with level WARNING and then calls the logger's Log function.

type StackTraceEntry

type StackTraceEntry struct {
	FunctionName string
	File         string
	Line         int
}

StackTraceEntry holds information about a single function call.

func (*StackTraceEntry) String

func (ste *StackTraceEntry) String() string

String converts a StackTraceEntry to its string representation

type StdException

type StdException struct {

	// NonLoggedMsg can be optionally used to attach a secondary message that won't be logged.
	NonLoggedMsg string
	// contains filtered or unexported fields
}

StdException is the most basic exception that sherlog offers. Implements error, Loggable, and StackTraceWrapper.

func (*StdException) Error

func (se *StdException) Error() string

Error returns the message and stack trace in a string formatted like this:

message:
	sherlog.exampleFunc(exampleFile.go:18)
	sherlog.exampleFunc2(exampleFile2.go:46)
	sherlog.exampleFunc3(exampleFile2.go:177)

Leaves out the timestamp so that StdException will print nicely with log.Println

func (*StdException) GetMessage

func (se *StdException) GetMessage() string

func (*StdException) GetStackTrace

func (se *StdException) GetStackTrace() []*StackTraceEntry

GetStackTrace returns the stack trace as slice of *StackTraceEntry.

func (*StdException) GetStackTraceAsString

func (se *StdException) GetStackTraceAsString() string

GetStackTraceAsString returns the stack trace in a string formatted as:

sherlog.exampleFunc(exampleFile.go:18)
sherlog.exampleFunc2(exampleFile2.go:46)
sherlog.exampleFunc3(exampleFile2.go:177)

Uses the cached stack trace string if one is available. If it has to convert the stack trace to a string, it will cache it for later.

func (*StdException) Log

func (se *StdException) Log(writer io.Writer) error

Log writes to the writer a string formatted as:

yyyy-mm-dd hh:mm:ss - message:
	sherlog.exampleFunc(exampleFile.go:18)
	sherlog.exampleFunc2(exampleFile2.go:46)
	sherlog.exampleFunc3(exampleFile2.go:177)

Returns the string that was logged or an error if there was one.

func (*StdException) LogAsJson

func (se *StdException) LogAsJson(writer io.Writer) error

LogAsJson packages up the exception's info into json and writes it to writer.

The json is formatted like this

{
   "Message":"I'm informative!",
   "StackTrace":[
	  {
		 "FunctionName":"github.com/Nick-Anderssohn/sherlog.TestLogJson",
		 "File":"/home/nick/go/src/github.com/Nick-Anderssohn/sherlog/scratch_test.go",
		 "Line":68
	  },
	  {
		 "FunctionName":"testing.tRunner",
		 "File":"/usr/local/go/src/testing/testing.go",
		 "Line":777
	  },
	  {
		 "FunctionName":"runtime.goexit",
		 "File":"/usr/local/go/src/runtime/asm_amd64.s",
		 "Line":2361
	  }
   ],
   "StackTraceStr":"\tgithub.com/Nick-Anderssohn/sherlog.TestLogJson(/home/nick/go/src/github.com/Nick-Anderssohn/sherlog/scratch_test.go:68)\n\ttesting.tRunner(/usr/local/go/src/testing/testing.go:777)\n\truntime.goexit(/usr/local/go/src/runtime/asm_amd64.s:2361)\n",
   "Time":"2018-10-03 07:51:14"
}

Returns an error if there was one.

func (*StdException) LogNoStack

func (se *StdException) LogNoStack(writer io.Writer) error

LogNoStack writes to the writer a string formatted as:

yyyy-mm-dd hh:mm:ss - message

Note that it does not have the stack trace. Returns the string that was logged or an error if there was one.

func (*StdException) ToJsonBytes

func (se *StdException) ToJsonBytes() ([]byte, error)

ToJsonBytes returns the bytes for a json blob that looks like this:

{
   "Message":"I'm informative!",
   "StackTrace":[
	  {
		 "FunctionName":"github.com/Nick-Anderssohn/sherlog.TestLogJson",
		 "File":"/home/nick/go/src/github.com/Nick-Anderssohn/sherlog/scratch_test.go",
		 "Line":68
	  },
	  {
		 "FunctionName":"testing.tRunner",
		 "File":"/usr/local/go/src/testing/testing.go",
		 "Line":777
	  },
	  {
		 "FunctionName":"runtime.goexit",
		 "File":"/usr/local/go/src/runtime/asm_amd64.s",
		 "Line":2361
	  }
   ],
   "StackTraceStr":"\tgithub.com/Nick-Anderssohn/sherlog.TestLogJson(/home/nick/go/src/github.com/Nick-Anderssohn/sherlog/scratch_test.go:68)\n\ttesting.tRunner(/usr/local/go/src/testing/testing.go:777)\n\truntime.goexit(/usr/local/go/src/runtime/asm_amd64.s:2361)\n",
   "Time":"2018-10-03 07:51:14"
}

func (*StdException) ToJsonMap

func (se *StdException) ToJsonMap() map[string]interface{}

ToJsonMap creates a map[string]interface{} that, when compiled to json, looks like this:

{
   "Message":"I'm informative!",
   "StackTrace":[
	  {
		 "FunctionName":"github.com/Nick-Anderssohn/sherlog.TestLogJson",
		 "File":"/home/nick/go/src/github.com/Nick-Anderssohn/sherlog/scratch_test.go",
		 "Line":68
	  },
	  {
		 "FunctionName":"testing.tRunner",
		 "File":"/usr/local/go/src/testing/testing.go",
		 "Line":777
	  },
	  {
		 "FunctionName":"runtime.goexit",
		 "File":"/usr/local/go/src/runtime/asm_amd64.s",
		 "Line":2361
	  }
   ],
   "StackTraceStr":"\tgithub.com/Nick-Anderssohn/sherlog.TestLogJson(/home/nick/go/src/github.com/Nick-Anderssohn/sherlog/scratch_test.go:68)\n\ttesting.tRunner(/usr/local/go/src/testing/testing.go:777)\n\truntime.goexit(/usr/local/go/src/runtime/asm_amd64.s:2361)\n",
   "Time":"2018-10-03 07:51:14"
}

Jump to

Keyboard shortcuts

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