qmp-testing-suite/golang-producer-consumer/vendor/gitlab-app.eng.qops.net/reporting-framework/ripsaw-logger-golang/logger-human.go

117 lines
2.4 KiB
Go
Executable File

package ripsawlogger
import (
"encoding/json"
"errors"
"fmt"
"time"
)
var (
// A simple syntax that displays the timestamp and the message field. Can
// be useful when the exact format of the log entry is not known, or when
// entries of various formats are recorded.
MessageFormat = HumanSyntax{
String: "%s: %s",
Tokens: []string{
"_timestamp",
"message",
},
}
// This represents Common Log Format, similar to how HTTP and nginx record
// access logs. Defined here for convenience.
CommonLogFormat = HumanSyntax{
String: "%s %s %s [%s] \"%s %s HTTP/%s\" %d %d",
Tokens: []string{
"host",
"rfc931",
"username",
"_timestamp",
"method",
"url",
"httpVersion",
"statusCode",
"bytes",
},
}
)
type HumanLoggerLevel struct {
Color string
Syntax HumanSyntax
}
type HumanSyntax struct {
String string
Tokens []string
}
func (syntax HumanSyntax) Format(entry LogEntry) string {
// if we have no syntax string, just try to pull a message
if syntax.String == "" {
if msg, ok := entry.Contents["message"]; ok {
stringified, _ := json.Marshal(msg)
return string(stringified)
}
// just format the JSON I guess
stringified, _ := json.Marshal(entry.Contents)
return string(stringified)
}
// gather tokens
values := make([]interface{}, 0, len(syntax.Tokens))
for _, token := range syntax.Tokens {
var resolvedToken interface{} = "-"
if value, err := syntax.extract(token, entry); err == nil {
resolvedToken = value
}
values = append(values, resolvedToken)
}
return fmt.Sprintf(syntax.String, values...)
}
func (syntax HumanSyntax) extract(path string, entry LogEntry) (interface{}, error) {
switch path {
case "_timestamp":
if entry.Time.IsZero() {
return time.Now().Format(time.RFC3339Nano), nil
} else {
return entry.Time.Format(time.RFC3339Nano), nil
}
case "_level":
return entry.Level, nil
default:
if value, ok := entry.Contents[path]; ok {
return value, nil
}
}
return "", errors.New("Token not found")
}
type humanLogger map[string]HumanLoggerLevel
// Creates a logger that formats log data in a human-readable way, and can be configured
// on a per-log-level basis.
func NewHumanLogger(cfg map[string]HumanLoggerLevel) Logger {
return humanLogger(cfg)
}
func (sl humanLogger) Log(entry LogEntry) {
if cfg, ok := sl[entry.Level]; ok {
fmt.Printf("[%s] %s\n", entry.Level, cfg.Syntax.Format(entry))
}
}
func (sl humanLogger) Flush() {
// ¯\_(ツ)_/¯
}