logfrog

package module
v0.3.1 Latest Latest
Warning

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

Go to latest
Published: Jul 30, 2022 License: AGPL-3.0 Imports: 7 Imported by: 0

README

logfrog for golang

A opinionated logger with great flexibility

License

This project is licensed under AGPL-3.0. See the LICENSE file for more informations.

Usage

Overview of the log-flow:

logger.Log(...)
      |
  processors
      |
  handlers: handle( process -> format -> write )

In logfrog there are three different components: Formatter, Processor and Handler

  • a Processor modifies or mutates any given logrecord. It can either be globally for every record an logger produces or scoped inside an handler.
  • a Formatter used by handlers to transform an log-record into an sequence of bytes
  • a Handler handles what to do with an record; it can apply own mutations (via an seperate process chain), than formats it and finally writes it werever it wants the data to go (like into a file, send an email and so on). It also can decide if the record should be handed to the next handler, or if it was "consumed".
Getting started

Heres an simple example to get you started:

package main

import (
    "os"
    "codeark.it/Bithero-Agency-Go/logfrog-go"
    logfrog_handlers "codeark.it/Bithero-Agency-Go/logfrog-go/handlers"
)

func main() {
    // First we need an logger. We can create one with `NewLogger(name, level)`.
    // The name can be visible in the logs; the level is used to configure which logging calls
    // should actually be handled, and which one should be sorted out.
    logger := logfrog.NewLogger("main", logfrog.DEBUG)
    defer logger.Close()

    // Adds an handler so we actually can see the output... more on that later on
    logger->AddHandler(logfrog_handlers.NewStreamHandler(os.Stdout))

    // The logger supports a easy function for all available log levels (TRACE, DEBUG, INFO, WARN, ERROR, CRITICAL, FATAL).
    // Their signature is: Info(format string, args ...interface{}); as you see, they act a lot like fmt.Printf() .
    logger->Info("2 * 20 is %d", 2 * 20)

    // Since we set the logger in our constructor to debug level, this call will log nothing and not
    // even call the global processors!
    logger->Trace("this will not be processed")

    // If you want it a bit more complex you also could use the Log() method directly.
    // You might notice the zero as first argument; this is the 'skip'; it determines how many function calls
    // the caller-lookup should go up in order to find the function that called the logging function.
    // Zero means this function, one the caller of the current function and so on.
    logger->Log(0, logfrog.INFO, "2 * 20 is %d", 2 * 20)

    // Logfrog also allows for "fields" to be attached to an log entry:
    logger->InfoFields(logfrog.Fields{
        "animal": "cat",
        "color": "red",
    }, "2 * 20 is %d", 2 * 20)

    // Logfrog also has an generic method here as well:
    logger->LogFields(0, logFrog.INFO, logfrog.Fields{
        "animal": "cat",
        "color": "red",
    }, "2 * 20 is %d", 2 * 20)
}
Using & implementing Components

Components are processors, formatters and handlers in logfrog. Implementing them is a bit more work, see Implementing Components.

To use them, just use the AddHandler(), AddProcessor() and SetFormatter() functions:

import (
    logfrog_formatters "codeark.it/Bithero-Agency-Go/logfrog-go/formatters"
    logfrog_handlers "codeark.it/Bithero-Agency-Go/logfrog-go/handlers"
    logfrog_processors "codeark.it/Bithero-Agency-Go/logfrog-go/processors"
)

func main() {
    // ...

    // Adds an handler and lets the logger own it
    logger->AddHandler(logfrog_handlers.NewStreamHandler(os.Stdout))

    // Adds an handler an let both you and the logger own it
    handler := logfrog_handlers.NewStreamHandler(os.Stdout)
    handler.Ref()
    logger->AddHandler(handler)

    handler.Unref()     // give up your ownage share
    logger.Close()      // logger gives up his ownage on close
    // When the last ownage is gone, the component will be Close()-ed

    //-------------------------------------------------------------------

    // Adds an processor-function to the logger
    // The RuntimeVersionProcessor is an example if you can create semi-statefull processors
    logger->AddProcessorFn(logfrog_processors.RuntimeVersionProcessor("goVer"))

    // adds an lambda function as processor
    logger->AddProcessorFn(func (r *logfrog.LogRecord) *logfrog.LogRecord {
        return r
    })

    // ...
}

Documentation

Index

Constants

This section is empty.

Variables

View Source
var AllLogLevels = []LogLevel{TRACE, DEBUG, INFO, WARN, ERROR, CRITICAL, FATAL}

Functions

This section is empty.

Types

type BaseLogFormatter

type BaseLogFormatter struct {
	LogFormatter
	// contains filtered or unexported fields
}

func NewBaseLogFormatter

func NewBaseLogFormatter() *BaseLogFormatter

func (*BaseLogFormatter) Close

func (b *BaseLogFormatter) Close() error

func (*BaseLogFormatter) Ref

func (b *BaseLogFormatter) Ref()

func (*BaseLogFormatter) Unref

func (b *BaseLogFormatter) Unref() error

type BaseLogHandler

type BaseLogHandler struct {
	LogHandler
	// contains filtered or unexported fields
}

func NewBaseLogHandler

func NewBaseLogHandler() *BaseLogHandler

func (*BaseLogHandler) AddProcessor

func (b *BaseLogHandler) AddProcessor(processor LogProcessor) LogHandler

Add an processor object to the list of processors; calls Ref() on the processor to add

func (*BaseLogHandler) AddProcessorFn

func (b *BaseLogHandler) AddProcessorFn(fn LogProcessorFn) LogHandler

Add a processor function to the list of processors

func (*BaseLogHandler) Close

func (b *BaseLogHandler) Close() error

func (*BaseLogHandler) GetBubbling

func (b *BaseLogHandler) GetBubbling() bool

Returns the bubbling state of the handler: `true` when handled messages should not be consumed but be processed by the next handler instead; `false` when handled messages should be consumed

func (*BaseLogHandler) GetDefaultFormatter added in v0.3.0

func (b *BaseLogHandler) GetDefaultFormatter() (LogFormatter, LogFormatterFn)

Returns a tuple of the default formatter object and default formatter function. Will be used in ResetFormatter() and ResetFormatterFn() to restore the default formatter of an handler.

func (*BaseLogHandler) Handle

func (b *BaseLogHandler) Handle(r *LogRecord) (bool, error)

Handles the given logrecord. Returns a bool weather or not the record was consumed and any error that might araise.

func (*BaseLogHandler) LogLevels

func (b *BaseLogHandler) LogLevels() []LogLevel

func (*BaseLogHandler) OnClose

func (b *BaseLogHandler) OnClose() error

func (*BaseLogHandler) Ref

func (b *BaseLogHandler) Ref()

func (*BaseLogHandler) RemoveProcessor added in v0.3.0

func (b *BaseLogHandler) RemoveProcessor(processor LogProcessor) error

Remove a processor object from the list of processors If one is found, it is Unref() is called on it, and the potential error is returned.

Note: calling RemoveProcessor() with an processor that's NOT part of the list, is NOT an error!

func (*BaseLogHandler) RemoveProcessorFn added in v0.3.0

func (b *BaseLogHandler) RemoveProcessorFn(fn LogProcessorFn)

Remove a processor function from the list of processors

func (*BaseLogHandler) ResetFormatter added in v0.3.0

func (b *BaseLogHandler) ResetFormatter() error

Reset the formatter object to the default one. If the previous formatter was an formatter object, Unref() is called on it.

func (*BaseLogHandler) ResetFormatterFn added in v0.3.0

func (b *BaseLogHandler) ResetFormatterFn() error

Resets the formatter function to the default one. If the previous formatter was an formatter object, Unref() is called on it.

Note: this function is effectivly the

func (*BaseLogHandler) SetBubbling

func (b *BaseLogHandler) SetBubbling(bubble bool) LogHandler

Sets the bubbling state of the handler: `true` when handled messages should not be consumed but be processed by the next handler instead; `false` when handled messages should be consumed

func (*BaseLogHandler) SetFormatter

func (b *BaseLogHandler) SetFormatter(formatter LogFormatter) LogHandler

Sets the formatter object. Note: when an formatter is already set, it is reset and potential errors are handed to panic().

func (*BaseLogHandler) SetFormatterFn

func (b *BaseLogHandler) SetFormatterFn(fn LogFormatterFn) LogHandler

Sets the formatter function. Note: when an formatter is already set, it is reset and potential errors are handed to panic().

func (*BaseLogHandler) ShouldHandlePost

func (b *BaseLogHandler) ShouldHandlePost(*LogRecord) bool

Returns true if the given logrecord should be handled; called AFTER all handler-local processors where run on the logrecord. Will NOT be called if the logrecord's loglevel is NONE after the process step.

This default implementation returns always `true`.

func (*BaseLogHandler) ShouldHandlePre

func (b *BaseLogHandler) ShouldHandlePre(*LogRecord) bool

Returns true if the given logrecord should be handled; called BEFORE all handler-local processors where run on the logrecord. Will recieve records with an loglevel to NONE.

This default implementation returns always `true`.

func (*BaseLogHandler) Unref

func (b *BaseLogHandler) Unref() error

type BaseLogProcessor

type BaseLogProcessor struct {
	LogProcessor
	// contains filtered or unexported fields
}

func NewBaseLogProcessor

func NewBaseLogProcessor() *BaseLogProcessor

func (*BaseLogProcessor) Close

func (b *BaseLogProcessor) Close() error

func (*BaseLogProcessor) Ref

func (b *BaseLogProcessor) Ref()

func (*BaseLogProcessor) Unref

func (b *BaseLogProcessor) Unref() error

type ErrHandlerCloseFailure

type ErrHandlerCloseFailure struct {
	ProcessorCloseErrors []ErrorSource
	FormatterCloseError  *ErrorSource
	HandlerOnCloseError  *ErrorSource
}

func (*ErrHandlerCloseFailure) Error

func (e *ErrHandlerCloseFailure) Error() string

type ErrLoggerCloseFailure

type ErrLoggerCloseFailure struct {
	ProcessorCloseErrors []ErrorSource
	HandlerCloseErrors   []ErrorSource
}

func (*ErrLoggerCloseFailure) Error

func (e *ErrLoggerCloseFailure) Error() string

type ErrorSource

type ErrorSource struct {
	// fully-quallified name of the source object
	Source string
	Error  error
}

type Fields

type Fields map[string]interface{}

type LogCaller

type LogCaller struct {
	File     string `json:"file"`
	Line     int    `json:"line"`
	Funcname string `json:"funcname,omitempty"`
}

type LogFormatter

type LogFormatter interface {
	Close() error
	Ref()
	Unref() error
	Format(*LogRecord) ([]byte, error)
}

type LogFormatterFn

type LogFormatterFn func(*LogRecord) ([]byte, error)

type LogHandler

type LogHandler interface {
	// Call this to properly close the handler.
	// Co NOT overwritte this if you are not knowing what you are doing; use OnClose() instead!
	Close() error

	// Can be implemented by extenders to be called when closing and not interfere with the basic handler's
	// closing mecanism
	OnClose() error

	// Increases the reference count by one
	Ref()

	// Decreases the reference count by one; if zero or lower, this function calls Close() to close this handler
	// and returns it's result
	Unref() error

	// Returns all levels the handler is interested in; including NONE dosn't affect anything
	LogLevels() []LogLevel

	// Returns true if the given record should be handled; called *before* handler-local processors are run.
	// Will recieve records with a loglevel of NONE to allow handler-local processor to make it valid again.
	ShouldHandlePre(*LogRecord) bool

	// Returns true if the given record should be handled; called *after* handler-local processors are run.
	// Will *not* recieve records with a loglevel of NONE.
	ShouldHandlePost(*LogRecord) bool

	// Handles an log record, returns true if the record was handled
	// and should not be handled by other handlers
	Handle(*LogRecord) (bool, error)

	// Writes an formatted logrecord.
	Write([]byte) error

	// Sets if the handler allows handled records to bubble
	SetBubbling(bool) LogHandler

	// Returns true if the handler allows handled records to bubble
	GetBubbling() bool

	// Sets the formatter to an formatting function
	SetFormatterFn(LogFormatterFn) LogHandler

	// Sets the formatter to an formatter object and calls Ref() on it
	SetFormatter(LogFormatter) LogHandler

	// Resets the formatter function to the default one.
	// If the previous formatter was an formatter object, Unref() is called on it.
	ResetFormatterFn() error

	// Reset the formatter object to the default one.
	// If the previous formatter was an formatter object, Unref() is called on it.
	ResetFormatter() error

	// Adds an processor function to run for just this handler
	AddProcessorFn(LogProcessorFn) LogHandler

	// Adds an processor object to run for just this handler and calls Ref() on it
	AddProcessor(LogProcessor) LogHandler

	// Remove a processor function from the list of processors
	RemoveProcessorFn(fn LogProcessorFn)

	// Remove a processor object from the list of processors
	// If one is found, it is Unref() is called on it, and the potential error is returned.
	//
	// Note: calling RemoveProcessor() with an processor that's NOT part of the list, is NOT an error!
	RemoveProcessor(processor LogProcessor) error

	// Returns a tuple of the default formatter object and default formatter function.
	// Will be used in ResetFormatter() and ResetFormatterFn() to restore the default formatter of an handler.
	GetDefaultFormatter() (LogFormatter, LogFormatterFn)
}

type LogLevel

type LogLevel int
const (
	TRACE LogLevel = iota
	DEBUG
	INFO
	WARN
	ERROR
	CRITICAL
	FATAL
	NONE // Meta-LogLevel used to allow processors to "discard" records
)

func (LogLevel) String

func (l LogLevel) String() string

type LogProcessor

type LogProcessor interface {
	Close() error
	Ref()
	Unref() error
	Process(*LogRecord) *LogRecord
}

type LogProcessorFn

type LogProcessorFn func(*LogRecord) *LogRecord

type LogRecord

type LogRecord struct {
	Source  string     `json:"source,omitempty"`
	Created time.Time  `json:"created_at"`
	Level   LogLevel   `json:"lvl"`
	Message string     `json:"msg"`
	Caller  *LogCaller `json:"caller,omitempty"`
	Fields  Fields     `json:"fields"`
}

func NewLogRecord

func NewLogRecord(skip int, created time.Time, level LogLevel, message string, fields Fields) *LogRecord

func (*LogRecord) Clone

func (r *LogRecord) Clone() *LogRecord

type Logger

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

func NewLogger

func NewLogger(name string, level LogLevel) *Logger

func (*Logger) AddHandler

func (l *Logger) AddHandler(handler LogHandler)

func (*Logger) AddProcessor

func (l *Logger) AddProcessor(p LogProcessor)

func (*Logger) AddProcessorFn

func (l *Logger) AddProcessorFn(fn LogProcessorFn)

Adds an processor to modify/enhance log-entries before they are send to each handler

func (*Logger) Close

func (l *Logger) Close() error

Closing a logger means we unref all handlers

func (*Logger) Critical

func (l *Logger) Critical(format string, v ...interface{})

func (*Logger) CriticalFields

func (l *Logger) CriticalFields(fields Fields, format string, v ...interface{})

func (*Logger) Debug

func (l *Logger) Debug(format string, v ...interface{})

func (*Logger) DebugFields

func (l *Logger) DebugFields(fields Fields, format string, v ...interface{})

func (*Logger) Error

func (l *Logger) Error(format string, v ...interface{})

func (*Logger) ErrorFields

func (l *Logger) ErrorFields(fields Fields, format string, v ...interface{})

func (*Logger) Fatal

func (l *Logger) Fatal(format string, v ...interface{})

func (*Logger) FatalFields

func (l *Logger) FatalFields(fields Fields, format string, v ...interface{})

func (*Logger) GetLevel

func (l *Logger) GetLevel() LogLevel

func (*Logger) GetName

func (l *Logger) GetName() string

func (*Logger) Info

func (l *Logger) Info(format string, v ...interface{})

func (*Logger) InfoFields

func (l *Logger) InfoFields(fields Fields, format string, v ...interface{})

func (*Logger) IsCritical

func (l *Logger) IsCritical() bool

func (*Logger) IsDebug

func (l *Logger) IsDebug() bool

func (*Logger) IsError

func (l *Logger) IsError() bool

func (*Logger) IsFatal

func (l *Logger) IsFatal() bool

func (*Logger) IsInfo

func (l *Logger) IsInfo() bool

func (*Logger) IsTrace

func (l *Logger) IsTrace() bool

func (*Logger) Log

func (l *Logger) Log(skip int, level LogLevel, format string, v ...interface{})

func (*Logger) LogFields

func (l *Logger) LogFields(skip int, level LogLevel, fields Fields, format string, v ...interface{})

func (*Logger) RemoveHandler added in v0.3.0

func (l *Logger) RemoveHandler(handler LogHandler) error

func (*Logger) RemoveProcessor added in v0.3.0

func (l *Logger) RemoveProcessor(p LogProcessor) error

func (*Logger) RemoveProcessorFn added in v0.3.0

func (l *Logger) RemoveProcessorFn(fn LogProcessorFn)

Removes an processor function previously added by AddProcessorFn

func (*Logger) Trace

func (l *Logger) Trace(format string, v ...interface{})

func (*Logger) TraceFields

func (l *Logger) TraceFields(fields Fields, format string, v ...interface{})

func (*Logger) Warn

func (l *Logger) Warn(format string, v ...interface{})

func (*Logger) WarnFields

func (l *Logger) WarnFields(fields Fields, format string, v ...interface{})

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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