1package log 2 3import ( 4 "bytes" 5 "fmt" 6 7 log "github.com/sirupsen/logrus" 8) 9 10func forNil(v interface{}, otherwise interface{}) interface{} { 11 if v == nil { 12 return otherwise 13 } 14 15 return v 16} 17 18// combinedAccessLogFormatter formats logs into a format similar to the combined access log format 19// See https://httpd.apache.org/docs/1.3/logs.html#combined 20type combinedAccessLogFormatter struct { 21 clock clock 22} 23 24// Format renders a single log entry. 25func (f *combinedAccessLogFormatter) Format(entry *log.Entry) ([]byte, error) { 26 host := forNil(entry.Data[httpHostField], "-") 27 remoteAddr := forNil(entry.Data[httpRemoteIPField], "") 28 method := forNil(entry.Data[httpRequestMethodField], "") 29 uri := forNil(entry.Data[httpURIField], "") 30 proto := forNil(entry.Data[httpProtoField], "") 31 status := forNil(entry.Data[httpResponseStatusCodeField], 0) 32 written := forNil(entry.Data[httpResponseSizeField], 0) 33 referer := forNil(entry.Data[httpRequestReferrerField], "") 34 userAgent := forNil(entry.Data[httpUserAgentField], "") 35 duration := forNil(entry.Data[requestDurationField], 0) 36 37 now := f.clock.Now().Format("2006/01/02:15:04:05 -0700") 38 39 requestLine := fmt.Sprintf("%s %s %s", method, uri, proto) 40 41 buf := &bytes.Buffer{} 42 _, err := fmt.Fprintf(buf, "%s %s - - [%s] %q %d %d %q %q %d\n", 43 host, remoteAddr, now, requestLine, 44 status, written, referer, userAgent, duration, 45 ) 46 47 return buf.Bytes(), err 48} 49 50// newCombinedcombinedAccessLogFormatter returns a new formatter for combined access logs. 51func newCombinedcombinedAccessLogFormatter() log.Formatter { 52 return &combinedAccessLogFormatter{clock: &realClock{}} 53} 54