github.com/jd-ly/cmd@v1.0.10/logger/handlers.go (about)

     1  package logger
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  )
     7  
     8  type LevelFilterHandler struct {
     9  	Level LogLevel
    10  	h     LogHandler
    11  }
    12  
    13  // Filters out records which do not match the level
    14  // Uses the `log15.FilterHandler` to perform this task
    15  func LevelHandler(lvl LogLevel, h LogHandler) LogHandler {
    16  	return &LevelFilterHandler{lvl, h}
    17  }
    18  
    19  // The implementation of the Log
    20  func (h LevelFilterHandler) Log(r *Record) error {
    21  	if r.Level == h.Level {
    22  		return h.h.Log(r)
    23  	}
    24  	return nil
    25  }
    26  
    27  // Filters out records which do not match the level
    28  // Uses the `log15.FilterHandler` to perform this task
    29  func MinLevelHandler(lvl LogLevel, h LogHandler) LogHandler {
    30  	return FilterHandler(func(r *Record) (pass bool) {
    31  		return r.Level <= lvl
    32  	}, h)
    33  }
    34  
    35  // Filters out records which match the level
    36  // Uses the `log15.FilterHandler` to perform this task
    37  func NotLevelHandler(lvl LogLevel, h LogHandler) LogHandler {
    38  	return FilterHandler(func(r *Record) (pass bool) {
    39  		return r.Level != lvl
    40  	}, h)
    41  }
    42  
    43  func CallerFileHandler(h LogHandler) LogHandler {
    44  	return FuncHandler(func(r *Record) error {
    45  		r.Context.Add("caller", fmt.Sprint(r.Call))
    46  		return h.Log(r)
    47  	})
    48  }
    49  
    50  // Adds in a context called `caller` to the record (contains file name and line number like `foo.go:12`)
    51  // Uses the `log15.CallerFuncHandler` to perform this task
    52  func CallerFuncHandler(h LogHandler) LogHandler {
    53  	return CallerFuncHandler(h)
    54  }
    55  
    56  // Filters out records which match the key value pair
    57  // Uses the `log15.MatchFilterHandler` to perform this task
    58  func MatchHandler(key string, value interface{}, h LogHandler) LogHandler {
    59  	return MatchFilterHandler(key, value, h)
    60  }
    61  
    62  // MatchFilterHandler returns a Handler that only writes records
    63  // to the wrapped Handler if the given key in the logged
    64  // context matches the value. For example, to only log records
    65  // from your ui package:
    66  //
    67  //    log.MatchFilterHandler("pkg", "app/ui", log.StdoutHandler)
    68  //
    69  func MatchFilterHandler(key string, value interface{}, h LogHandler) LogHandler {
    70  	return FilterHandler(func(r *Record) (pass bool) {
    71  		return r.Context[key] == value
    72  	}, h)
    73  }
    74  
    75  // If match then A handler is called otherwise B handler is called
    76  func MatchAbHandler(key string, value interface{}, a, b LogHandler) LogHandler {
    77  	return FuncHandler(func(r *Record) error {
    78  		if r.Context[key] == value {
    79  			return a.Log(r)
    80  		} else if b != nil {
    81  			return b.Log(r)
    82  		}
    83  
    84  		return nil
    85  	})
    86  }
    87  
    88  // The nil handler is used if logging for a specific request needs to be turned off
    89  func NilHandler() LogHandler {
    90  	return FuncHandler(func(r *Record) error {
    91  		return nil
    92  	})
    93  }
    94  
    95  // Match all values in map to log
    96  func MatchMapHandler(matchMap map[string]interface{}, a LogHandler) LogHandler {
    97  	return matchMapHandler(matchMap, false, a)
    98  }
    99  
   100  // Match !(Match all values in map to log) The inverse of MatchMapHandler
   101  func NotMatchMapHandler(matchMap map[string]interface{}, a LogHandler) LogHandler {
   102  	return matchMapHandler(matchMap, true, a)
   103  }
   104  
   105  // Rather then chaining multiple filter handlers, process all here
   106  func matchMapHandler(matchMap map[string]interface{}, inverse bool, a LogHandler) LogHandler {
   107  	return FuncHandler(func(r *Record) error {
   108  		matchCount := 0
   109  		for k, v := range matchMap {
   110  			value, found := r.Context[k]
   111  			if !found {
   112  				return nil
   113  			}
   114  			// Test for two failure cases
   115  			if value == v && inverse || value != v && !inverse {
   116  				return nil
   117  			} else {
   118  				matchCount++
   119  			}
   120  		}
   121  		if matchCount != len(matchMap) {
   122  			return nil
   123  		}
   124  		return a.Log(r)
   125  	})
   126  }
   127  
   128  // Filters out records which do not match the key value pair
   129  // Uses the `log15.FilterHandler` to perform this task
   130  func NotMatchHandler(key string, value interface{}, h LogHandler) LogHandler {
   131  	return FilterHandler(func(r *Record) (pass bool) {
   132  		return r.Context[key] != value
   133  	}, h)
   134  }
   135  
   136  func MultiHandler(hs ...LogHandler) LogHandler {
   137  	return FuncHandler(func(r *Record) error {
   138  		for _, h := range hs {
   139  			// what to do about failures?
   140  			h.Log(r)
   141  		}
   142  		return nil
   143  	})
   144  }
   145  
   146  // StreamHandler writes log records to an io.Writer
   147  // with the given format. StreamHandler can be used
   148  // to easily begin writing log records to other
   149  // outputs.
   150  //
   151  // StreamHandler wraps itself with LazyHandler and SyncHandler
   152  // to evaluate Lazy objects and perform safe concurrent writes.
   153  func StreamHandler(wr io.Writer, fmtr LogFormat) LogHandler {
   154  	h := FuncHandler(func(r *Record) error {
   155  		_, err := wr.Write(fmtr.Format(r))
   156  		return err
   157  	})
   158  	return LazyHandler(SyncHandler(h))
   159  }
   160  
   161  // Filter handler
   162  func FilterHandler(fn func(r *Record) bool, h LogHandler) LogHandler {
   163  	return FuncHandler(func(r *Record) error {
   164  		if fn(r) {
   165  			return h.Log(r)
   166  		}
   167  		return nil
   168  	})
   169  }
   170  
   171  // List log handler handles a list of LogHandlers
   172  type ListLogHandler struct {
   173  	handlers []LogHandler
   174  }
   175  
   176  // Create a new list of log handlers
   177  func NewListLogHandler(h1, h2 LogHandler) *ListLogHandler {
   178  	ll := &ListLogHandler{handlers: []LogHandler{h1, h2}}
   179  	return ll
   180  }
   181  
   182  // Log the record
   183  func (ll *ListLogHandler) Log(r *Record) (err error) {
   184  	for _, handler := range ll.handlers {
   185  		if err == nil {
   186  			err = handler.Log(r)
   187  		} else {
   188  			handler.Log(r)
   189  		}
   190  	}
   191  	return
   192  }
   193  
   194  // Add another log handler
   195  func (ll *ListLogHandler) Add(h LogHandler) {
   196  	if h != nil {
   197  		ll.handlers = append(ll.handlers, h)
   198  	}
   199  }
   200  
   201  // Remove a log handler
   202  func (ll *ListLogHandler) Del(h LogHandler) {
   203  	if h != nil {
   204  		for i, handler := range ll.handlers {
   205  			if handler == h {
   206  				ll.handlers = append(ll.handlers[:i], ll.handlers[i+1:]...)
   207  			}
   208  		}
   209  	}
   210  }