open-vault/helper/logformat/vault.go

175 lines
3.9 KiB
Go
Raw Normal View History

2016-08-19 20:45:17 +00:00
package logformat
import (
"encoding/json"
"fmt"
"io"
"os"
2016-09-01 20:14:21 +00:00
"strings"
2016-08-19 20:45:17 +00:00
"sync"
"time"
log "github.com/mgutz/logxi/v1"
)
const (
styledefault = iota
stylejson
)
2016-09-01 20:14:21 +00:00
// NewVaultLogger creates a new logger with the specified level and a Vault
// formatter
2016-08-19 20:45:17 +00:00
func NewVaultLogger(level int) log.Logger {
logger := log.New("vault")
2016-09-01 20:14:21 +00:00
return setLevelFormatter(logger, level, createVaultFormatter())
2016-08-19 20:45:17 +00:00
}
2016-09-01 20:14:21 +00:00
// NewVaultLoggerWithWriter creates a new logger with the specified level and
// writer and a Vault formatter
2016-08-19 20:45:17 +00:00
func NewVaultLoggerWithWriter(w io.Writer, level int) log.Logger {
logger := log.NewLogger(w, "vault")
2016-09-01 20:14:21 +00:00
return setLevelFormatter(logger, level, createVaultFormatter())
}
// Sets the level and formatter on the log, which must be a DefaultLogger
func setLevelFormatter(logger log.Logger, level int, formatter log.Formatter) log.Logger {
2016-08-19 20:45:17 +00:00
logger.(*log.DefaultLogger).SetLevel(level)
2016-09-01 20:14:21 +00:00
logger.(*log.DefaultLogger).SetFormatter(formatter)
2016-08-19 20:45:17 +00:00
return logger
}
2016-09-01 20:14:21 +00:00
// Creates a formatter, checking env vars for the style
2016-08-19 20:45:17 +00:00
func createVaultFormatter() log.Formatter {
2016-09-01 20:14:21 +00:00
ret := &vaultFormatter{
Mutex: &sync.Mutex{},
}
logFormat := os.Getenv("VAULT_LOG_FORMAT")
if logFormat == "" {
logFormat = os.Getenv("LOGXI_FORMAT")
}
switch strings.ToLower(logFormat) {
case "json", "vault_json", "vault-json", "vaultjson":
2016-08-19 20:45:17 +00:00
ret.style = stylejson
default:
ret.style = styledefault
}
return ret
}
2016-09-01 20:14:21 +00:00
// Thread safe formatter
2016-08-19 20:45:17 +00:00
type vaultFormatter struct {
2016-09-01 20:14:21 +00:00
*sync.Mutex
style int
module string
2016-08-19 20:45:17 +00:00
}
func (v *vaultFormatter) Format(writer io.Writer, level int, msg string, args []interface{}) {
v.Lock()
defer v.Unlock()
switch v.style {
case stylejson:
v.formatJSON(writer, level, msg, args)
default:
v.formatDefault(writer, level, msg, args)
}
}
func (v *vaultFormatter) formatDefault(writer io.Writer, level int, msg string, args []interface{}) {
2016-09-01 20:14:21 +00:00
// Write a trailing newline
2016-08-19 20:45:17 +00:00
defer writer.Write([]byte("\n"))
writer.Write([]byte(time.Now().Local().Format("2006/01/02 15:04:05.000000")))
switch level {
2016-09-01 20:14:21 +00:00
case log.LevelCritical:
writer.Write([]byte(" [CRIT ] "))
2016-08-19 20:45:17 +00:00
case log.LevelError:
2016-09-01 20:14:21 +00:00
writer.Write([]byte(" [ERROR] "))
2016-08-19 20:45:17 +00:00
case log.LevelWarn:
2016-09-01 20:14:21 +00:00
writer.Write([]byte(" [WARN ] "))
2016-08-19 20:45:17 +00:00
case log.LevelInfo:
2016-09-01 20:14:21 +00:00
writer.Write([]byte(" [INFO ] "))
2016-08-19 20:45:17 +00:00
case log.LevelDebug:
2016-09-01 20:14:21 +00:00
writer.Write([]byte(" [DEBUG] "))
2016-08-19 20:45:17 +00:00
case log.LevelTrace:
2016-09-01 20:14:21 +00:00
writer.Write([]byte(" [TRACE] "))
2016-08-19 20:45:17 +00:00
default:
2016-09-01 20:14:21 +00:00
writer.Write([]byte(" [ALL ] "))
}
if v.module != "" {
writer.Write([]byte(fmt.Sprintf("(%s) ", v.module)))
2016-08-19 20:45:17 +00:00
}
writer.Write([]byte(msg))
if args != nil && len(args) > 0 {
if len(args)%2 != 0 {
args = append(args, "[unknown!]")
}
2016-09-01 20:14:21 +00:00
writer.Write([]byte(":"))
2016-08-19 20:45:17 +00:00
for i := 0; i < len(args); i = i + 2 {
2016-09-01 20:14:21 +00:00
var quote string
switch args[i+1].(type) {
case string:
if strings.ContainsRune(args[i+1].(string), ' ') {
quote = `"`
}
}
writer.Write([]byte(fmt.Sprintf(" %s=%s%v%s", args[i], quote, args[i+1], quote)))
2016-08-19 20:45:17 +00:00
}
}
}
func (v *vaultFormatter) formatJSON(writer io.Writer, level int, msg string, args []interface{}) {
2016-09-01 20:14:21 +00:00
vals := map[string]interface{}{
"@message": msg,
"@timestamp": time.Now().Format("2006-01-02T15:04:05.000000Z07:00"),
2016-08-19 20:45:17 +00:00
}
2016-09-01 20:14:21 +00:00
var levelStr string
2016-08-19 20:45:17 +00:00
switch level {
2016-09-01 20:14:21 +00:00
case log.LevelCritical:
levelStr = "critical"
2016-08-19 20:45:17 +00:00
case log.LevelError:
2016-09-01 20:14:21 +00:00
levelStr = "error"
2016-08-19 20:45:17 +00:00
case log.LevelWarn:
2016-09-01 20:14:21 +00:00
levelStr = "warn"
2016-08-19 20:45:17 +00:00
case log.LevelInfo:
2016-09-01 20:14:21 +00:00
levelStr = "info"
2016-08-19 20:45:17 +00:00
case log.LevelDebug:
2016-09-01 20:14:21 +00:00
levelStr = "debug"
2016-08-19 20:45:17 +00:00
case log.LevelTrace:
2016-09-01 20:14:21 +00:00
levelStr = "trace"
2016-08-19 20:45:17 +00:00
default:
2016-09-01 20:14:21 +00:00
levelStr = "all"
}
vals["@level"] = levelStr
if v.module != "" {
vals["@module"] = v.module
2016-08-19 20:45:17 +00:00
}
if args != nil && len(args) > 0 {
if len(args)%2 != 0 {
args = append(args, "[unknown!]")
}
for i := 0; i < len(args); i = i + 2 {
if _, ok := args[i].(string); !ok {
// As this is the logging function not much we can do here
// without injecting into logs...
continue
}
2016-09-01 20:14:21 +00:00
vals[args[i].(string)] = args[i+1]
2016-08-19 20:45:17 +00:00
}
}
enc := json.NewEncoder(writer)
2016-09-01 20:14:21 +00:00
enc.Encode(vals)
2016-08-19 20:45:17 +00:00
}