logfrog-go/handler.go

311 lines
9.6 KiB
Go

package logfrog
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 BaseLogHandler struct {
LogHandler
bubbles bool
refs int
processors []LogProcessor
processorFuncs []LogProcessorFn
formatter LogFormatter
formatterFn LogFormatterFn
}
func defaultFormatter(lr *LogRecord) ([]byte, error) {
return []byte(lr.Message), nil
}
func NewBaseLogHandler() *BaseLogHandler {
return &BaseLogHandler{
bubbles: true,
refs: 0,
processors: []LogProcessor{},
processorFuncs: []LogProcessorFn{},
formatter: nil,
formatterFn: defaultFormatter,
}
}
func (b *BaseLogHandler) Close() error {
herr := &ErrHandlerCloseFailure{}
// first close all internal things!
for _, processor := range b.processors {
err := processor.Unref()
if err != nil {
herr.addProcessorError(processor, err)
}
}
if b.formatter != nil {
err := b.formatter.Unref()
if err != nil {
herr.setFormatterError(b.formatter, err)
}
}
// then close itself...
err := b.LogHandler.OnClose()
if err != nil {
herr.setHandlerError(b.LogHandler, err)
}
if herr.containsErrors() {
return herr
}
return nil
}
func (b *BaseLogHandler) OnClose() error {
// default close dosnt need anything to close
return nil
}
func (b *BaseLogHandler) Ref() {
b.refs++
}
func (b *BaseLogHandler) Unref() error {
b.refs--
if b.refs <= 0 {
return b.LogHandler.Close()
}
return nil
}
func (b *BaseLogHandler) LogLevels() []LogLevel {
return AllLogLevels
}
// 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 (b *BaseLogHandler) ShouldHandlePre(*LogRecord) bool {
// the base handler should handle all records
return true
}
// 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 (b *BaseLogHandler) ShouldHandlePost(*LogRecord) bool {
// the base handler should handle all records
return true
}
// Handles the given logrecord. Returns a bool weather or not the record was consumed and any error
// that might araise.
func (b *BaseLogHandler) Handle(r *LogRecord) (bool, error) {
if !b.LogHandler.ShouldHandlePre(r) {
return false, nil
}
if len(b.processorFuncs) > 0 {
for _, fn := range b.processorFuncs {
lr := fn(r)
if lr != nil {
r = lr
}
}
}
if r.Level == NONE {
return false, nil
}
if !b.LogHandler.ShouldHandlePost(r) {
return false, nil
}
value, err := b.formatterFn(r)
if err != nil {
return false, err
}
err = b.LogHandler.Write(value)
if err != nil {
return false, err
}
return !b.bubbles, nil
}
// 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 (b *BaseLogHandler) SetBubbling(bubble bool) LogHandler {
b.bubbles = bubble
return b
}
// 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 (b *BaseLogHandler) GetBubbling() bool {
return b.bubbles
}
// Sets the formatter function.
// Note: when an formatter is already set, it is reset and potential errors are handed to panic().
func (b *BaseLogHandler) SetFormatterFn(fn LogFormatterFn) LogHandler {
b.formatterFn = fn
if b.formatter != nil {
err := b.formatter.Unref()
b.formatter = nil
panic(err)
}
return b
}
// 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 (b *BaseLogHandler) ResetFormatterFn() error {
oldFormatter := b.formatter
b.formatter, b.formatterFn = b.LogHandler.GetDefaultFormatter()
if oldFormatter != nil {
return b.formatter.Unref()
}
return nil
}
// Sets the formatter object.
// Note: when an formatter is already set, it is reset and potential errors are handed to panic().
func (b *BaseLogHandler) SetFormatter(formatter LogFormatter) LogHandler {
oldFormatter := b.formatter
b.Ref()
b.formatter = formatter
b.formatterFn = formatter.Format
if oldFormatter != nil {
panic(oldFormatter.Unref())
}
return b
}
// Reset the formatter object to the default one.
// If the previous formatter was an formatter object, Unref() is called on it.
func (b *BaseLogHandler) ResetFormatter() error {
oldFormatter := b.formatter
b.formatter, b.formatterFn = b.LogHandler.GetDefaultFormatter()
if oldFormatter != nil {
return oldFormatter.Unref()
}
return nil
}
// Add an processor object to the list of processors; calls Ref() on the processor to add
func (b *BaseLogHandler) AddProcessor(processor LogProcessor) LogHandler {
processor.Ref()
b.processors = append(b.processors, processor)
b.processorFuncs = append(b.processorFuncs, processor.Process)
return b
}
// 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 (b *BaseLogHandler) RemoveProcessor(processor LogProcessor) error {
var wasRemoved bool
b.processors, wasRemoved = deleteFromWithFlag(b.processors, processor)
if !wasRemoved {
return nil
}
b.processorFuncs = deleteFrom(b.processorFuncs, processor.Process)
return processor.Unref()
}
// Add a processor function to the list of processors
func (b *BaseLogHandler) AddProcessorFn(fn LogProcessorFn) LogHandler {
b.processorFuncs = append(b.processorFuncs, fn)
return b
}
// Remove a processor function from the list of processors
func (b *BaseLogHandler) RemoveProcessorFn(fn LogProcessorFn) {
b.processorFuncs = deleteFrom(b.processorFuncs, fn)
}
// 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 (b *BaseLogHandler) GetDefaultFormatter() (LogFormatter, LogFormatterFn) {
return nil, defaultFormatter
}