311 lines
9.6 KiB
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
|
|
} |