1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
|
package log
import (
"fmt"
"io"
"os"
"runtime"
"strconv"
"sync"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
)
// scream so user fixes it
const warnImbalancedKey = "FIX_IMBALANCED_PAIRS"
const warnImbalancedPairs = warnImbalancedKey + " => "
const singleArgKey = "_"
func badKeyAtIndex(i int) string {
return "BAD_KEY_AT_INDEX_" + strconv.Itoa(i)
}
// DefaultLogLog is the default log for this package.
var DefaultLog Logger
// Suppress supresses logging and is useful to supress output in
// in unit tests.
//
// Example
// log.Suppress(true)
// defer log.suppress(false)
func Suppress(quiet bool) {
silent = quiet
}
var silent bool
// internalLog is the logger used by logxi itself
var InternalLog Logger
type loggerMap struct {
sync.Mutex
loggers map[string]Logger
}
var loggers = &loggerMap{
loggers: map[string]Logger{},
}
func (lm *loggerMap) set(name string, logger Logger) {
lm.loggers[name] = logger
}
// The assignment character between key-value pairs
var AssignmentChar = ": "
// Separator is the separator to use between key value pairs
//var Separator = "{~}"
var Separator = " "
const ltsvAssignmentChar = ":"
const ltsvSeparator = "\t"
// logxiEnabledMap maps log name patterns to levels
var logxiNameLevelMap map[string]int
// logxiFormat is the formatter kind to create
var logxiFormat string
var colorableStdout io.Writer
var defaultContextLines = 2
var defaultFormat string
var defaultLevel int
var defaultLogxiEnv string
var defaultLogxiFormatEnv string
var defaultMaxCol = 80
var defaultPretty = false
var defaultLogxiColorsEnv string
var defaultTimeFormat string
var disableCallstack bool
var disableCheckKeys bool
var disableColors bool
var home string
var isPretty bool
var isTerminal bool
var isWindows = runtime.GOOS == "windows"
var pkgMutex sync.Mutex
var pool = NewBufferPool()
var timeFormat string
var wd string
var pid = os.Getpid()
var pidStr = strconv.Itoa(os.Getpid())
// KeyMapping is the key map used to print built-in log entry fields.
type KeyMapping struct {
Level string
Message string
Name string
PID string
Time string
CallStack string
}
// KeyMap is the key map to use when printing log statements.
var KeyMap = &KeyMapping{
Level: "_l",
Message: "_m",
Name: "_n",
PID: "_p",
Time: "_t",
CallStack: "_c",
}
var logxiKeys []string
func setDefaults(isTerminal bool) {
var err error
contextLines = defaultContextLines
wd, err = os.Getwd()
if err != nil {
InternalLog.Error("Could not get working directory")
}
logxiKeys = []string{KeyMap.Level, KeyMap.Message, KeyMap.Name, KeyMap.Time, KeyMap.CallStack, KeyMap.PID}
if isTerminal {
defaultLogxiEnv = "*=WRN"
defaultLogxiFormatEnv = "happy,fit,maxcol=80,t=15:04:05.000000,context=-1"
defaultFormat = FormatHappy
defaultLevel = LevelWarn
defaultTimeFormat = "15:04:05.000000"
} else {
defaultLogxiEnv = "*=ERR"
defaultLogxiFormatEnv = "JSON,t=2006-01-02T15:04:05-0700"
defaultFormat = FormatJSON
defaultLevel = LevelError
defaultTimeFormat = "2006-01-02T15:04:05-0700"
disableColors = true
}
if isWindows {
home = os.Getenv("HOMEPATH")
if os.Getenv("ConEmuANSI") == "ON" {
defaultLogxiColorsEnv = "key=cyan+h,value,misc=blue+h,source=yellow,TRC,DBG,WRN=yellow+h,INF=green+h,ERR=red+h"
} else {
colorableStdout = NewConcurrentWriter(colorable.NewColorableStdout())
defaultLogxiColorsEnv = "ERR=red,misc=cyan,key=cyan"
}
// DefaultScheme is a color scheme optimized for dark background
// but works well with light backgrounds
} else {
home = os.Getenv("HOME")
term := os.Getenv("TERM")
if term == "xterm-256color" {
defaultLogxiColorsEnv = "key=cyan+h,value,misc=blue,source=88,TRC,DBG,WRN=yellow,INF=green+h,ERR=red+h,message=magenta+h"
} else {
defaultLogxiColorsEnv = "key=cyan+h,value,misc=blue,source=magenta,TRC,DBG,WRN=yellow,INF=green,ERR=red+h"
}
}
}
func isReservedKey(k interface{}) (bool, error) {
key, ok := k.(string)
if !ok {
return false, fmt.Errorf("Key is not a string")
}
// check if reserved
for _, key2 := range logxiKeys {
if key == key2 {
return true, nil
}
}
return false, nil
}
func init() {
colorableStdout = NewConcurrentWriter(os.Stdout)
isTerminal = isatty.IsTerminal(os.Stdout.Fd())
// the internal logger to report errors
if isTerminal {
InternalLog = NewLogger3(NewConcurrentWriter(os.Stdout), "__logxi", NewTextFormatter("__logxi"))
} else {
InternalLog = NewLogger3(NewConcurrentWriter(os.Stdout), "__logxi", NewJSONFormatter("__logxi"))
}
InternalLog.SetLevel(LevelError)
setDefaults(isTerminal)
RegisterFormatFactory(FormatHappy, formatFactory)
RegisterFormatFactory(FormatText, formatFactory)
RegisterFormatFactory(FormatJSON, formatFactory)
ProcessEnv(readFromEnviron())
// package logger for users
DefaultLog = New("~")
}
|