// Log lines have this form: // Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... // where the fields are defined as follows: // L A single character, representing the log level (eg 'I' for INFO) // mm The month (zero padded; ie May is '05') // dd The day (zero padded) // hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds // threadid The space-padded thread ID as returned by GetTID() // file The file name // line The line number // msg The user-supplied message func (f *GlogFormatter) Format(context log.LogContext) []byte { res := &bytes.Buffer{} file := context.File slash := len(file) - 1 for ; slash >= 0; slash-- { if file[slash] == filepath.Separator { break } } if slash >= 0 { file = file[slash+1:] } _, month, day := context.Time.Date() hour, minute, second := context.Time.Clock() f.tmp[0] = log.UcShortestSeverityStrings[log.SeverityToIndex(context.Severity)][0] log.TwoDigits(&f.tmp, 1, int(month)) log.TwoDigits(&f.tmp, 3, day) f.tmp[5] = ' ' log.TwoDigits(&f.tmp, 6, hour) f.tmp[8] = ':' log.TwoDigits(&f.tmp, 9, minute) f.tmp[11] = ':' log.TwoDigits(&f.tmp, 12, second) f.tmp[14] = '.' log.NDigits(&f.tmp, 6, 15, context.Time.Nanosecond()/1000) f.tmp[21] = ' ' log.NDigits(&f.tmp, 5, 22, context.Pid) f.tmp[27] = ' ' res.Write(f.tmp[:28]) res.WriteString(file) f.tmp[0] = ':' n := log.Itoa(&f.tmp, 1, context.Line) f.tmp[n+1] = ']' f.tmp[n+2] = ' ' res.Write(f.tmp[:n+3]) message := "" if context.Format != nil { message = fmt.Sprintf(*context.Format, context.Args...) } else { message = fmt.Sprint(context.Args...) } res.WriteString(message) l := len(message) if l > 0 && message[l-1] != '\n' { res.WriteRune('\n') } return res.Bytes() }
// Format formats a LogContext into the GELF format. func (f *GELFFormatter) Format(context log.LogContext) []byte { file := context.File if len(file) == 0 { file = "???" } else { slash := len(file) - 1 for ; slash >= 0; slash-- { if file[slash] == filepath.Separator { break } } if slash >= 0 { file = file[slash+1:] } } e := Extra{ "_file": file, "_line": context.Line, "_severity": log.LcSeverityStrings[log.SeverityToIndex(context.Severity)], "_facility": f.appname + "." + context.Function, } var args []interface{} for _, v := range context.Args { switch t := v.(type) { case Extra: for key, value := range t { e[key] = value } case *http.Request: header := make(map[string]interface{}) // Copy header for key, value := range t.Header { // Don't copy auth. Don't want this in logs. // Note: If you add more auth schemes then you have to update // this code to remove those too. if strings.EqualFold(key, "authorization") { continue } header[key] = value } e["_request_method"] = t.Method // We have to use RequestURI because URL may be // modified by routes. e["_request_url"] = t.RequestURI //t.URL.String(), e["_request_host"] = t.Host e["_request_remote_addr"] = t.RemoteAddr e["_request_header"] = header default: args = append(args, v) } } message := "" if context.Format != nil { message = fmt.Sprintf(*context.Format, args...) } else { message = fmt.Sprint(args...) } gf := gelf{ Version: "1.1", Host: f.hostname, Short: message, //Full: message, TimeUnix: time.Now().Unix(), Level: 6, // info Extra: e, } buf, _ := json.Marshal(&gf) buf = append(buf, '\n') return buf }
//SeverityToString converts the Severity to human readable string func SeverityToString(s factorlog.Severity) string { return factorlog.CapSeverityStrings[factorlog.SeverityToIndex(s)] }