2020-04-29 20:51:32 +00:00
|
|
|
package logger
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2020-06-15 22:00:37 +00:00
|
|
|
"runtime"
|
2020-04-29 20:51:32 +00:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/acmacalister/skittles"
|
|
|
|
)
|
|
|
|
|
2020-07-23 23:36:31 +00:00
|
|
|
// Level of logging, lower number means more verbose logging, higher more terse
|
2020-04-29 20:51:32 +00:00
|
|
|
type Level int
|
|
|
|
|
|
|
|
const (
|
|
|
|
// DebugLevel is for messages that are intended for purposes debugging only
|
2020-07-23 23:36:31 +00:00
|
|
|
DebugLevel Level = iota
|
|
|
|
|
|
|
|
// InfoLevel is for standard log messages
|
|
|
|
InfoLevel
|
2020-04-29 20:51:32 +00:00
|
|
|
|
2020-07-23 23:36:31 +00:00
|
|
|
// ErrorLevel is for error message to indicate something has gone wrong
|
2020-04-29 20:51:32 +00:00
|
|
|
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 {
|
2020-06-15 22:00:37 +00:00
|
|
|
format string
|
|
|
|
supportsColor bool
|
2020-04-29 20:51:32 +00:00
|
|
|
}
|
|
|
|
|
2020-07-29 22:48:27 +00:00
|
|
|
// UIFormatter is used for streaming logs to UI
|
|
|
|
type UIFormatter struct {
|
|
|
|
format string
|
|
|
|
supportsColor bool
|
|
|
|
}
|
|
|
|
|
2020-04-29 20:51:32 +00:00
|
|
|
// NewTerminalFormatter creates a Terminal formatter for colored output
|
|
|
|
// format is the time format to use for timestamp formatting
|
|
|
|
func NewTerminalFormatter(format string) Formatter {
|
2020-06-15 22:00:37 +00:00
|
|
|
supportsColor := (runtime.GOOS != "windows")
|
2020-04-29 20:51:32 +00:00
|
|
|
return &TerminalFormatter{
|
2020-06-15 22:00:37 +00:00
|
|
|
format: format,
|
|
|
|
supportsColor: supportsColor,
|
2020-04-29 20:51:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-29 22:48:27 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2020-04-29 20:51:32 +00:00
|
|
|
// Timestamp returns the log level with a matching color to the log type
|
|
|
|
func (f *TerminalFormatter) Timestamp(l Level, d time.Time) string {
|
|
|
|
t := ""
|
2020-07-29 22:48:27 +00:00
|
|
|
dateStr := "[" + d.Format(f.format) + "] "
|
2020-04-29 20:51:32 +00:00
|
|
|
switch l {
|
|
|
|
case InfoLevel:
|
2020-06-30 17:53:19 +00:00
|
|
|
t = f.output("INFO", skittles.Cyan)
|
2020-04-29 20:51:32 +00:00
|
|
|
case ErrorLevel:
|
2020-06-30 17:53:19 +00:00
|
|
|
t = f.output("ERROR", skittles.Red)
|
2020-04-29 20:51:32 +00:00
|
|
|
case DebugLevel:
|
2020-06-30 17:53:19 +00:00
|
|
|
t = f.output("DEBUG", skittles.Yellow)
|
2020-04-29 20:51:32 +00:00
|
|
|
case FatalLevel:
|
2020-06-30 17:53:19 +00:00
|
|
|
t = f.output("FATAL", skittles.Red)
|
2020-04-29 20:51:32 +00:00
|
|
|
}
|
2020-06-30 17:53:19 +00:00
|
|
|
return t + dateStr
|
2020-04-29 20:51:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Content just writes the log line straight to the sources
|
|
|
|
func (f *TerminalFormatter) Content(l Level, c string) string {
|
|
|
|
return c
|
|
|
|
}
|
2020-06-15 22:00:37 +00:00
|
|
|
|
|
|
|
func (f *TerminalFormatter) output(msg string, colorFunc func(interface{}) string) string {
|
|
|
|
if f.supportsColor {
|
|
|
|
return colorFunc(msg)
|
|
|
|
}
|
|
|
|
return msg
|
|
|
|
}
|