| package log |
| |
| import ( |
| "os" |
| "strconv" |
| "strings" |
| ) |
| |
| var contextLines int |
| |
| // Configuration comes from environment or external services like |
| // consul, etcd. |
| type Configuration struct { |
| Format string `json:"format"` |
| Colors string `json:"colors"` |
| Levels string `json:"levels"` |
| } |
| |
| func readFromEnviron() *Configuration { |
| conf := &Configuration{} |
| |
| var envOrDefault = func(name, val string) string { |
| result := os.Getenv(name) |
| if result == "" { |
| result = val |
| } |
| return result |
| } |
| |
| conf.Levels = envOrDefault("LOGXI", defaultLogxiEnv) |
| conf.Format = envOrDefault("LOGXI_FORMAT", defaultLogxiFormatEnv) |
| conf.Colors = envOrDefault("LOGXI_COLORS", defaultLogxiColorsEnv) |
| return conf |
| } |
| |
| // ProcessEnv (re)processes environment. |
| func ProcessEnv(env *Configuration) { |
| // TODO: allow reading from etcd |
| |
| ProcessLogxiEnv(env.Levels) |
| ProcessLogxiColorsEnv(env.Colors) |
| ProcessLogxiFormatEnv(env.Format) |
| } |
| |
| // ProcessLogxiFormatEnv parses LOGXI_FORMAT |
| func ProcessLogxiFormatEnv(env string) { |
| logxiFormat = env |
| m := parseKVList(logxiFormat, ",") |
| formatterFormat := "" |
| tFormat := "" |
| for key, value := range m { |
| switch key { |
| default: |
| formatterFormat = key |
| case "t": |
| tFormat = value |
| case "pretty": |
| isPretty = value != "false" && value != "0" |
| case "maxcol": |
| col, err := strconv.Atoi(value) |
| if err == nil { |
| maxCol = col |
| } else { |
| maxCol = defaultMaxCol |
| } |
| case "context": |
| lines, err := strconv.Atoi(value) |
| if err == nil { |
| contextLines = lines |
| } else { |
| contextLines = defaultContextLines |
| } |
| case "LTSV": |
| formatterFormat = "text" |
| AssignmentChar = ltsvAssignmentChar |
| Separator = ltsvSeparator |
| } |
| } |
| if formatterFormat == "" || formatterCreators[formatterFormat] == nil { |
| formatterFormat = defaultFormat |
| } |
| logxiFormat = formatterFormat |
| if tFormat == "" { |
| tFormat = defaultTimeFormat |
| } |
| timeFormat = tFormat |
| } |
| |
| // ProcessLogxiEnv parses LOGXI variable |
| func ProcessLogxiEnv(env string) { |
| logxiEnable := env |
| if logxiEnable == "" { |
| logxiEnable = defaultLogxiEnv |
| } |
| |
| logxiNameLevelMap = map[string]int{} |
| m := parseKVList(logxiEnable, ",") |
| if m == nil { |
| logxiNameLevelMap["*"] = defaultLevel |
| } |
| for key, value := range m { |
| if strings.HasPrefix(key, "-") { |
| // LOGXI=*,-foo => disable foo |
| logxiNameLevelMap[key[1:]] = LevelOff |
| } else if value == "" { |
| // LOGXI=* => default to all |
| logxiNameLevelMap[key] = LevelAll |
| } else { |
| // LOGXI=*=ERR => use user-specified level |
| level := LevelAtoi[value] |
| if level == 0 { |
| InternalLog.Error("Unknown level in LOGXI environment variable", "key", key, "value", value, "LOGXI", env) |
| level = defaultLevel |
| } |
| logxiNameLevelMap[key] = level |
| } |
| } |
| |
| // must always have global default, otherwise errs may get eaten up |
| if _, ok := logxiNameLevelMap["*"]; !ok { |
| logxiNameLevelMap["*"] = LevelError |
| } |
| } |
| |
| func getLogLevel(name string) int { |
| var wildcardLevel int |
| var result int |
| |
| for k, v := range logxiNameLevelMap { |
| if k == name { |
| result = v |
| } else if k == "*" { |
| wildcardLevel = v |
| } else if strings.HasPrefix(k, "*") && strings.HasSuffix(name, k[1:]) { |
| result = v |
| } else if strings.HasSuffix(k, "*") && strings.HasPrefix(name, k[:len(k)-1]) { |
| result = v |
| } |
| } |
| |
| if result == LevelOff { |
| return LevelOff |
| } |
| |
| if result > 0 { |
| return result |
| } |
| |
| if wildcardLevel > 0 { |
| return wildcardLevel |
| } |
| |
| return LevelOff |
| } |
| |
| // ProcessLogxiColorsEnv parases LOGXI_COLORS |
| func ProcessLogxiColorsEnv(env string) { |
| colors := env |
| if colors == "" { |
| colors = defaultLogxiColorsEnv |
| } else if colors == "*=off" { |
| // disable all colors |
| disableColors = true |
| } |
| theme = parseTheme(colors) |
| } |