123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081 |
- // Package logutils augments the standard log package with levels.
- package logutils
- import (
- "bytes"
- "io"
- "sync"
- )
- type LogLevel string
- // LevelFilter is an io.Writer that can be used with a logger that
- // will filter out log messages that aren't at least a certain level.
- //
- // Once the filter is in use somewhere, it is not safe to modify
- // the structure.
- type LevelFilter struct {
- // Levels is the list of log levels, in increasing order of
- // severity. Example might be: {"DEBUG", "WARN", "ERROR"}.
- Levels []LogLevel
- // MinLevel is the minimum level allowed through
- MinLevel LogLevel
- // The underlying io.Writer where log messages that pass the filter
- // will be set.
- Writer io.Writer
- badLevels map[LogLevel]struct{}
- once sync.Once
- }
- // Check will check a given line if it would be included in the level
- // filter.
- func (f *LevelFilter) Check(line []byte) bool {
- f.once.Do(f.init)
- // Check for a log level
- var level LogLevel
- x := bytes.IndexByte(line, '[')
- if x >= 0 {
- y := bytes.IndexByte(line[x:], ']')
- if y >= 0 {
- level = LogLevel(line[x+1 : x+y])
- }
- }
- _, ok := f.badLevels[level]
- return !ok
- }
- func (f *LevelFilter) Write(p []byte) (n int, err error) {
- // Note in general that io.Writer can receive any byte sequence
- // to write, but the "log" package always guarantees that we only
- // get a single line. We use that as a slight optimization within
- // this method, assuming we're dealing with a single, complete line
- // of log data.
- if !f.Check(p) {
- return len(p), nil
- }
- return f.Writer.Write(p)
- }
- // SetMinLevel is used to update the minimum log level
- func (f *LevelFilter) SetMinLevel(min LogLevel) {
- f.MinLevel = min
- f.init()
- }
- func (f *LevelFilter) init() {
- badLevels := make(map[LogLevel]struct{})
- for _, level := range f.Levels {
- if level == f.MinLevel {
- break
- }
- badLevels[level] = struct{}{}
- }
- f.badLevels = badLevels
- }
|