go.dedis.ch/onet/v4@v4.0.0-pre1/log/loggers.go (about)

     1  package log
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  
     7  	ct "github.com/daviddengcn/go-colortext"
     8  	"golang.org/x/xerrors"
     9  )
    10  
    11  // LoggerInfo is a structure that should be used when creating a logger.
    12  // It contains parameters about how to log (with time, colors, ...) and
    13  // embeds the Logger interface, which should define how the logger should log.
    14  type LoggerInfo struct {
    15  	// These are information-debugging levels that can be turned on or off.
    16  	// Every logging greater than 'debugLvl' will be discarded . So you can
    17  	// Log at different levels and easily turn on or off the amount of logging
    18  	// generated by adjusting the 'debugLvl' variable.
    19  	DebugLvl int
    20  	// If 'showTime' is true, it will print the time for each line displayed
    21  	// by the logger.
    22  	ShowTime bool
    23  	// If 'AbsoluteFilePath' is true, it will print the absolute file path
    24  	// instead of the base.
    25  	AbsoluteFilePath bool
    26  	// If 'useColors' is true, logs will be colored (defaults to monochrome
    27  	// output). It also controls padding, since colorful output is higly
    28  	// correlated with humans who like their log lines padded.
    29  	UseColors bool
    30  	// If 'padding' is true, it will nicely pad the line that is written.
    31  	Padding bool
    32  }
    33  
    34  // Logger is the interface that specifies how loggers
    35  // will receive and display messages.
    36  type Logger interface {
    37  	Log(level int, msg string)
    38  	Close()
    39  	GetLoggerInfo() *LoggerInfo
    40  }
    41  
    42  const (
    43  	// DefaultStdDebugLvl is the default debug level for the standard logger
    44  	DefaultStdDebugLvl = 1
    45  	// DefaultStdShowTime is the default value for 'showTime' for the standard logger
    46  	DefaultStdShowTime = false
    47  	// DefaultStdAbsoluteFilePath is the default to show absolute path for the standard logger
    48  	DefaultStdAbsoluteFilePath = false
    49  	// DefaultStdUseColors is the default value for 'useColors' for the standard logger
    50  	DefaultStdUseColors = false
    51  	// DefaultStdPadding is the default value for 'padding' for the standard logger
    52  	DefaultStdPadding = true
    53  )
    54  
    55  var (
    56  	// concurrent access is protected by debugMut
    57  	loggers        = make(map[int]Logger)
    58  	loggersCounter int
    59  )
    60  
    61  // RegisterLogger will register a callback that will receive a copy of every
    62  // message, fully formatted. It returns the key assigned to the logger (used
    63  // to unregister the logger).
    64  func RegisterLogger(l Logger) int {
    65  	debugMut.Lock()
    66  	defer debugMut.Unlock()
    67  	key := loggersCounter
    68  	loggers[key] = l
    69  	loggersCounter++
    70  	return key
    71  }
    72  
    73  // UnregisterLogger takes the key it was assigned and returned by
    74  // 'RegisterLogger', closes the corresponding Logger and removes it from the
    75  // loggers.
    76  func UnregisterLogger(key int) {
    77  	debugMut.Lock()
    78  	defer debugMut.Unlock()
    79  	if l, ok := loggers[key]; ok {
    80  		l.Close()
    81  		delete(loggers, key)
    82  	}
    83  }
    84  
    85  type fileLogger struct {
    86  	lInfo *LoggerInfo
    87  	file  *os.File
    88  }
    89  
    90  func (fl *fileLogger) Log(level int, msg string) {
    91  	if _, err := fl.file.WriteString(msg); err != nil {
    92  		panic(err)
    93  	}
    94  }
    95  
    96  func (fl *fileLogger) Close() {
    97  	fl.file.Close()
    98  }
    99  
   100  func (fl *fileLogger) GetLoggerInfo() *LoggerInfo {
   101  	return fl.lInfo
   102  }
   103  
   104  // NewFileLogger creates a logger that writes into the file with
   105  // the given path and is using the given LoggerInfo.
   106  // It returns the logger.
   107  func NewFileLogger(lInfo *LoggerInfo, path string) (Logger, error) {
   108  	// Override file if it already exists.
   109  	file, err := os.Create(path)
   110  	if err != nil {
   111  		return nil, xerrors.Errorf("creating file: %v", err)
   112  	}
   113  	return &fileLogger{
   114  		lInfo: lInfo,
   115  		file:  file,
   116  	}, nil
   117  }
   118  
   119  type stdLogger struct {
   120  	lInfo *LoggerInfo
   121  }
   122  
   123  func (sl *stdLogger) Log(lvl int, msg string) {
   124  	if sl.lInfo.UseColors {
   125  		bright := lvl < 0
   126  		lvlAbs := lvl
   127  		if bright {
   128  			lvlAbs *= -1
   129  		}
   130  
   131  		switch lvl {
   132  		case lvlPrint:
   133  			ct.Foreground(ct.White, true)
   134  		case lvlInfo:
   135  			ct.Foreground(ct.White, true)
   136  		case lvlWarning:
   137  			ct.Foreground(ct.Green, true)
   138  		case lvlError:
   139  			ct.Foreground(ct.Red, false)
   140  		case lvlFatal:
   141  			ct.Foreground(ct.Red, true)
   142  		case lvlPanic:
   143  			ct.Foreground(ct.Red, true)
   144  		default:
   145  			if lvl != 0 {
   146  				if lvlAbs <= 5 {
   147  					colors := []ct.Color{ct.Yellow, ct.Cyan, ct.Green, ct.Blue, ct.Cyan}
   148  					ct.Foreground(colors[lvlAbs-1], bright)
   149  				}
   150  			}
   151  		}
   152  	}
   153  
   154  	if lvl < lvlInfo {
   155  		fmt.Fprint(stdErr, msg)
   156  	} else {
   157  		fmt.Fprint(stdOut, msg)
   158  	}
   159  
   160  	if sl.lInfo.UseColors {
   161  		ct.ResetColor()
   162  	}
   163  }
   164  
   165  func (sl *stdLogger) Close() {}
   166  
   167  func (sl *stdLogger) GetLoggerInfo() *LoggerInfo {
   168  	return sl.lInfo
   169  }
   170  
   171  // Not public + not taking a LoggerInfo as argument because we don't want
   172  // multiple stdLoggers.
   173  func newStdLogger() (Logger, error) {
   174  	lInfo := &LoggerInfo{
   175  		DebugLvl:         DefaultStdDebugLvl,
   176  		UseColors:        DefaultStdUseColors,
   177  		ShowTime:         DefaultStdShowTime,
   178  		AbsoluteFilePath: DefaultStdAbsoluteFilePath,
   179  		Padding:          DefaultStdPadding,
   180  	}
   181  	return &stdLogger{lInfo: lInfo}, nil
   182  }