package logger import ( "fmt" "runtime" "time" "github.com/acmacalister/skittles" ) // Level of logging, lower number means more verbose logging, higher more terse type Level int const ( // DebugLevel is for messages that are intended for purposes debugging only DebugLevel Level = iota // InfoLevel is for standard log messages InfoLevel // ErrorLevel is for error message to indicate something has gone wrong ErrorLevel // FatalLevel is for error message that log and kill the program with an os.exit(1) FatalLevel ) // Formatter is the base interface for formatting logging messages before writing them out type Formatter interface { Timestamp(Level, time.Time) string // format the timestamp string Content(Level, string) string // format content string (color for terminal, etc) } // DefaultFormatter writes a simple structure timestamp and the message per log line type DefaultFormatter struct { format string } // NewDefaultFormatter creates the standard log formatter // format is the time format to use for timestamp formatting func NewDefaultFormatter(format string) Formatter { return &DefaultFormatter{ format: format, } } // Timestamp formats a log line timestamp with a brackets around them func (f *DefaultFormatter) Timestamp(l Level, d time.Time) string { if f.format == "" { return "" } return fmt.Sprintf("[%s]: ", d.Format(f.format)) } // Content just writes the log line straight to the sources func (f *DefaultFormatter) Content(l Level, c string) string { return c } // TerminalFormatter is setup for colored output type TerminalFormatter struct { format string supportsColor bool } // UIFormatter is used for streaming logs to UI type UIFormatter struct { format string supportsColor bool } // NewTerminalFormatter creates a Terminal formatter for colored output // format is the time format to use for timestamp formatting func NewTerminalFormatter(format string) Formatter { supportsColor := (runtime.GOOS != "windows") return &TerminalFormatter{ format: format, supportsColor: supportsColor, } } func NewUIFormatter(format string) Formatter { supportsColor := (runtime.GOOS != "windows") return &UIFormatter{ format: format, supportsColor: supportsColor, } } // Timestamp uses formatting that is tview-specific for UI func (f *UIFormatter) Timestamp(l Level, d time.Time) string { t := "" dateStr := "[" + d.Format(f.format) + "] " switch l { case InfoLevel: t = "[#00ffff]INFO[white]" case ErrorLevel: t = "[red]ERROR[white]" case DebugLevel: t = "[yellow]DEBUG[white]" case FatalLevel: t = "[red]FATAL[white]" } return t + dateStr } func (f *UIFormatter) Content(l Level, c string) string { return c } // Timestamp returns the log level with a matching color to the log type func (f *TerminalFormatter) Timestamp(l Level, d time.Time) string { t := "" dateStr := "[" + d.Format(f.format) + "] " switch l { case InfoLevel: t = f.output("INFO", skittles.Cyan) case ErrorLevel: t = f.output("ERROR", skittles.Red) case DebugLevel: t = f.output("DEBUG", skittles.Yellow) case FatalLevel: t = f.output("FATAL", skittles.Red) } return t + dateStr } // Content just writes the log line straight to the sources func (f *TerminalFormatter) Content(l Level, c string) string { return c } func (f *TerminalFormatter) output(msg string, colorFunc func(interface{}) string) string { if f.supportsColor { return colorFunc(msg) } return msg }