apilog

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Aug 28, 2024 License: MIT Imports: 14 Imported by: 0

README

Go version CI Status

APILog

Write leveled log to multiple writer/output at once. Leverage the usage of context to improve decoupling between each part of system.

Getting Started

// set console/terminal writer to listen to all logs level DEBUG, INFO, WARNING, ERROR
//  console writer, write logs to local terminal/console
cns := apilog.NewConsoleWriter(apilog.DebugLevel)	

// use predefined zap as the backend
wr := apilog.NewZapLogger(cns)
//  or use this if you want to use slog under the hood instead
//    wr := logger.NewSlogLogger(cns)

// call Init before using any other API
wr.Init(3 * time.Second) // you may give longer or shorter timeout/deadline

// info level log message that include contextual data 'hello':'world'
wr.Inf("INFO message", apilog.String("hello", "world"))
//  terminal: 2024-08-28T07:57:14.259+0700    INFO    INFO message    {"hello": "world"}
//  json: {"level":"INFO","time":"2024-08-28T07:59:13+07:00","msg":"INFO message","hello":"world"}

// debug level log message
wr.Dbg("DEBUG message")
//  terminal: 2024-08-28T07:57:14.259+0700    DEBUG   DEBUG message
//  json: {"level":"DEBUG","time":"2024-08-28T07:59:13+07:00","msg":"DEBUG message"}

// SHOULD be called before program exit to make sure any pending logs in buffer properly flushed by each Writer
wr.Flush(2 * time.Second) // you may give longer or shorter timeout/deadline

Contextual Data

// give contextual data that will be passed down to subsequent call
wr = wr.With(log.String("app_env", "local"))
wr.Wrn("warning log")
//  terminal: 2024-08-28T08:04:26.599+0700    WARN    WARNING log     {"app_env": "local"}
//  json: {"level":"WARN","time":"2024-08-28T08:05:13+07:00","msg":"WARNING log","app_env":"local"}

wr = wr.With(log.Num("ram", 2)) // this will also accumulate previous contextual data
wr.Inf("look how many ram i have")
//  terminal: 2024-08-28T08:04:26.599+0700    INFO    look how many ram i have        {"app_env": "local", "ram": 2}
//  json: {"level":"INFO","time":"2024-08-28T08:05:13+07:00","msg":"look how many ram i have","app_env":"local","ram":2}

Leveled Log

cns := log.NewConsoleWriter(log.ErrorLevel)
wr := log.NewZapLogger(cns)
wr.Init(3 * time.Second)

// won't print, less than error
wr.Dbg("DEBUG message")

// won't print, less than error
wr.Inf("INFO message")

// won't print, less than error
wr.Wrn("warning log")

// printed, higher or equal than error
wr.Err("oops!!")
//  terminal: 2023-09-22T13:38:39.784+0700    ERROR   oops!!
//  json: {"level":"ERROR","time":"2024-08-28T08:35:43+07:00","msg":"oops!!"}

// never forget to flush before exiting
wr.Flush(1 * time.Second)

Log is prioritized in these order:

  1. Error Err: (Error) print only in log level Error
  2. Warning Wrn: (Warning, Error) print in log level Warning, Error
  3. Info Inf: (Info, Warning, Error) print in log level Info, Warning, Error
  4. Debug Dbg: (Debug, Info, Warning, Error) print in all log level

Logger with Context

// put the logger wr to context with 'log.WithCtx'
ctx := log.WithCtx(context.Background(), wr)
printFromCtx(ctx) // pass logger contained context

func printFromCtx(ctx context.Context) {
    // grab logger from context
    wr := log.FromCtx(ctx)
    // note that even if there is no logger inside context
    // this won't cause any panic and just return nop-logger
    // that will never write any logs
	
    wr.Inf("my information")
    //  terminal: 2024-08-28T08:41:56.087+0700    INFO    my information
    //  json: {"level":"INFO","time":"2024-08-28T08:41:24+07:00","msg":"my information"}
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewObserverWriter

func NewObserverWriter(lvl Level, out Output) (Writer, *ObservedLog)

NewObserverWriter return new Writer implementer that write logs to memory and also return ObservedLog to help assert and check logged Log(s).

func WithCtx

func WithCtx(ctx context.Context, w Logger) context.Context

WithCtx return a copy of ctx with given logger attached.

Types

type Config

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

Config required object that holds any necessary data used by each log output implementation

func NewConfig

func NewConfig(opts ...ConfigOpt) *Config

NewConfig return new Config after applying given options.

type ConfigOpt

type ConfigOpt func(*Config)

ConfigOpt options for Config. Not recommended to be used directly.

func WithFileAge

func WithFileAge(age int) ConfigOpt

WithFileAge set maximum number of days to retain old log files based on the timestamp encoded in their filename

func WithFileMaxBackup

func WithFileMaxBackup(max int) ConfigOpt

WithFileMaxBackup set maximum number of old log files to retain before got removed.

func WithFilePath

func WithFilePath(p string) ConfigOpt

WithFilePath set target readable directory + local file which the log data will be written.

func WithFileSize

func WithFileSize(size int) ConfigOpt

WithFileSize set maximum file log size in megabytes before got rotated.

func WithNRAppName

func WithNRAppName(name string) ConfigOpt

WithNRAppName set new relic application name.

func WithNRLicense

func WithNRLicense(lic string) ConfigOpt

WithNRLicense set new relic license.

type FileConfig

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

FileConfig specific config for file as the log output

type Level

type Level int8

A Level is a logging priority. Higher levels are more important.

const (
	// DebugLevel most verbose logs, and are usually disabled in production.
	DebugLevel Level = iota
	// InfoLevel is the default logging priority.
	InfoLevel
	// WarnLevel logs are more important than Info, but don't need individual
	// human review.
	WarnLevel
	// ErrorLevel logs are high-priority. If an application is running smoothly,
	// it shouldn't generate any error-level logs.
	ErrorLevel
)

func ParseLevel

func ParseLevel(lvl string) Level

ParseLevel parses a level based on the lower-case representation of the log level.

type Log

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

Log object that holds data for each field inserted to each log message. How Logger implementer is treating this object should read the field typ and follow the guideline from Type and each of the supported types.

func Any

func Any(k string, any any) Log

Any constructs a Log with the given key and value. This set the type to AnyType.

func Bool

func Bool(k string, b bool) Log

Bool constructs a Log with the given key and value. This set the type to BoolType.

func Error

func Error(err error) Log

Error constructs a Log with the given err value and 'error' as the key. This set the type to ErrorType.

func Float

func Float(k string, f float64) Log

Float constructs a Log with the given key and value. This set the type to FloatType.

func Num

func Num(k string, num int) Log

Num constructs a Log with the given key and value. This set the type to NumType.

func String

func String(k, v string) Log

String constructs a Log with the given key and value. This set the type to StringType.

type Logger

type Logger interface {
	// Init do initialization and should be called at very first before
	// any other functions.
	Init(dur time.Duration)
	// Flush do clean up task that make sure any leftover logs written properly
	// to the destination by the Log therefor this should be called at very
	// last after other functions e.g. when gracefully shutting down server.
	Flush(dur time.Duration)
	// With add given Log(s) as structured context.
	With(pr ...Log) Logger
	// Group create new group or namespace with given key and Log(s) as the
	// content. In JSON, this is like creating new object using given key and
	// Log(s) as the fields.
	//
	// Ref(s):
	//  - https://pkg.go.dev/go.uber.org/zap#Namespace
	//  - https://pkg.go.dev/golang.org/x/exp/slog#Group
	Group(key string, pr ...Log) Logger
	// Dbg logs a message at DebugLevel.
	Dbg(msg string, pr ...Log)
	// Inf logs a message at InfoLevel.
	Inf(msg string, pr ...Log)
	// Wrn logs a message at WarnLevel.
	Wrn(msg string, pr ...Log)
	// Err logs a message at ErrorLevel.
	Err(msg string, pr ...Log)
}

Logger unified front-end to log.

func FromCtx

func FromCtx(ctx context.Context) Logger

FromCtx return the singleton Logger associated with given ctx. If no logger is associated, the default logger is returned, otherwise if no logger exist in the context, no-op logger will be returned instead.

func NewNop

func NewNop() Logger

NewNop returns a no-op Logger. Do nothing and never writes out any logs.

func NewSlogLogger

func NewSlogLogger(wr ...Writer) Logger

NewSlogLogger return Logger implementer that use stdlib slog as the backend.

func NewZapLogger

func NewZapLogger(wr ...Writer) Logger

NewZapLogger return Logger implementer that use zap as the backend.

type NRConfig

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

NRConfig specific config for new relic as the log output

type ObservedLog

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

ObservedLog is a concurrency-safe, ordered collection of observed Log(s).

func (*ObservedLog) All

func (o *ObservedLog) All() []loggedLog

All returns a copy of all the observed logs.

func (*ObservedLog) Flush

func (o *ObservedLog) Flush(_ time.Duration)

func (*ObservedLog) Len

func (o *ObservedLog) Len() int

Len returns the number of items in the collection.

func (*ObservedLog) Level

func (o *ObservedLog) Level() Level

func (*ObservedLog) Output

func (o *ObservedLog) Output() Output

func (*ObservedLog) TakeAll

func (o *ObservedLog) TakeAll() []loggedLog

TakeAll returns a copy of all the observed logs, and truncates the observed slice.

func (*ObservedLog) Wait

func (o *ObservedLog) Wait(_ time.Duration)

func (*ObservedLog) Write

func (o *ObservedLog) Write(p []byte) (n int, err error)

func (*ObservedLog) Writer

func (o *ObservedLog) Writer() io.Writer

type Output

type Output int8

Output define currently supported target output for logging.

const (
	CONSOLE  Output = iota // CONSOLE target log output to console/terminal
	NEWRELIC               // NEWRELIC target log output directly to new relic via newrelic client sdk
	FILE                   // FILE target log output to local file
)

type Type

type Type uint8

Type indicates how the Logger implementer should treat each Log.

const (
	// StringType use field str string of Log as the value.
	StringType Type = iota
	// NumType use field num int of Log as the value.
	NumType
	// FloatType use field flt float64 of Log as the value.
	FloatType
	// BoolType use field b bool of Log as the value.
	BoolType
	// AnyType use field any interface of Log as the value.
	AnyType
	// ErrorType use field err from error interface of Log as the value.
	ErrorType
)

type Writer

type Writer interface {
	// Writer return where and how the implementer should write the logs.
	Writer() io.Writer
	// Output define the Output type.
	Output() Output
	// Level define the logs level.
	Level() Level
	// Wait in case the implementer need some delay or preparation before can write any logs.
	Wait(dur time.Duration)
	// Flush any necessary clean up task that will be run by Producer at the last order.
	Flush(dur time.Duration)
}

Writer unified log writer that's responsible where the log from Logger should be written to.

func NewConsoleWriter

func NewConsoleWriter(lvl Level) Writer

NewConsoleWriter return Writer implementer that write logs to os.Stdout and set given lvl as the log Level.

func NewFileWriter

func NewFileWriter(lvl Level, cnf *Config) Writer

NewFileWriter return Writer implementer that write logs to designated file based on the given Config and set given lvl as the log Level.

func NewNewrelicWriter

func NewNewrelicWriter(lvl Level, cnf *Config) Writer

NewNewrelicWriter return Writer implementer that ingest logs directly to newrelic server by given Config and set given Level as the log level.

Jump to

Keyboard shortcuts

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