package log
import (
"bytes"
"io"
"log"
"regexp"
"strings"
)
type StdlibWriter struct {}
func (w StdlibWriter ) Write (p []byte ) (int , error ) {
log .Print (strings .TrimSpace (string (p )))
return len (p ), nil
}
type StdlibAdapter struct {
Logger
timestampKey string
fileKey string
messageKey string
prefix string
joinPrefixToMsg bool
}
type StdlibAdapterOption func (*StdlibAdapter )
func TimestampKey (key string ) StdlibAdapterOption {
return func (a *StdlibAdapter ) { a .timestampKey = key }
}
func FileKey (key string ) StdlibAdapterOption {
return func (a *StdlibAdapter ) { a .fileKey = key }
}
func MessageKey (key string ) StdlibAdapterOption {
return func (a *StdlibAdapter ) { a .messageKey = key }
}
func Prefix (prefix string , joinPrefixToMsg bool ) StdlibAdapterOption {
return func (a *StdlibAdapter ) { a .prefix = prefix ; a .joinPrefixToMsg = joinPrefixToMsg }
}
func NewStdlibAdapter (logger Logger , options ...StdlibAdapterOption ) io .Writer {
a := StdlibAdapter {
Logger : logger ,
timestampKey : "ts" ,
fileKey : "caller" ,
messageKey : "msg" ,
}
for _ , option := range options {
option (&a )
}
return a
}
func (a StdlibAdapter ) Write (p []byte ) (int , error ) {
p = a .handlePrefix (p )
result := subexps (p )
keyvals := []interface {}{}
var timestamp string
if date , ok := result ["date" ]; ok && date != "" {
timestamp = date
}
if time , ok := result ["time" ]; ok && time != "" {
if timestamp != "" {
timestamp += " "
}
timestamp += time
}
if timestamp != "" {
keyvals = append (keyvals , a .timestampKey , timestamp )
}
if file , ok := result ["file" ]; ok && file != "" {
keyvals = append (keyvals , a .fileKey , file )
}
if msg , ok := result ["msg" ]; ok {
msg = a .handleMessagePrefix (msg )
keyvals = append (keyvals , a .messageKey , msg )
}
if err := a .Logger .Log (keyvals ...); err != nil {
return 0 , err
}
return len (p ), nil
}
func (a StdlibAdapter ) handlePrefix (p []byte ) []byte {
if a .prefix != "" {
p = bytes .TrimPrefix (p , []byte (a .prefix ))
}
return p
}
func (a StdlibAdapter ) handleMessagePrefix (msg string ) string {
if a .prefix == "" {
return msg
}
msg = strings .TrimPrefix (msg , a .prefix )
if a .joinPrefixToMsg {
msg = a .prefix + msg
}
return msg
}
const (
logRegexpDate = `(?P<date>[0-9]{4}/[0-9]{2}/[0-9]{2})?[ ]?`
logRegexpTime = `(?P<time>[0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?)?[ ]?`
logRegexpFile = `(?P<file>.+?:[0-9]+)?`
logRegexpMsg = `(: )?(?P<msg>(?s:.*))`
)
var (
logRegexp = regexp .MustCompile (logRegexpDate + logRegexpTime + logRegexpFile + logRegexpMsg )
)
func subexps(line []byte ) map [string ]string {
m := logRegexp .FindSubmatch (line )
if len (m ) < len (logRegexp .SubexpNames ()) {
return map [string ]string {}
}
result := map [string ]string {}
for i , name := range logRegexp .SubexpNames () {
result [name ] = strings .TrimRight (string (m [i ]), "\n" )
}
return result
}
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .