diff --git a/_examples/logging/request-logger/accesslog-template/main.go b/_examples/logging/request-logger/accesslog-template/main.go index 66b02dd46a..5401a067e6 100644 --- a/_examples/logging/request-logger/accesslog-template/main.go +++ b/_examples/logging/request-logger/accesslog-template/main.go @@ -20,17 +20,14 @@ func main() { ac.AddFields(func(ctx iris.Context, fields *accesslog.Fields) { fields.Set("IP", ctx.RemoteAddr()) }) + // 2. Use Template formatter's `Text` value - // to customize the look & feel of a log. - // You could also use its `Tmpl` field to - // set a *template.Template instance. + // to define a log line format. ac.SetFormatter(&accesslog.Template{ Text: `{{.Now.Format .TimeFormat}} {{.Path}} {{.Code}} {{.Fields.Get "IP" }} -`, +`, /* 2020-09-10 21:38:13 / 200 ::1 */ }) - // Example Output: - // 2020-09-10 21:38:13 / 200 ::1 - + // 3. Register the middleware. That's all. app.UseRouter(ac.Handler) app.Get("/", index) @@ -41,3 +38,26 @@ func main() { func index(ctx iris.Context) { ctx.WriteString("Index") } + +/* Use a custom *template.Template: + +// 2.1 The log line format: +text := `{{.Now.Format .TimeFormat}} {{.Path}} {{.Code}} {{.Fields.Get "IP" }} +` +// +// 2.2 Parse the template, optionally using custom Template Functions. +tmpl := template.Must(template.New("").Funcs(template.FuncMap{ + // Custom functions you may want to use inside "text", + // e.g. prefixFields .Fields "my_prefix" + // to get a slice of fields starts with "my_prefix" + // and later, in the template, loop through them and render their values. + // "key": func(input) string { return ... } +}).Parse(text)) +// +// 3. Use Template formatter's `Text` value +// or the `Tmpl` field to customize the look & feel of a log. +ac.SetFormatter(&accesslog.Template{ + Tmpl: tmpl, +}) + +*/ diff --git a/middleware/accesslog/accesslog.go b/middleware/accesslog/accesslog.go index a6e8036e9f..c0ada8854b 100644 --- a/middleware/accesslog/accesslog.go +++ b/middleware/accesslog/accesslog.go @@ -553,7 +553,7 @@ func (ac *AccessLog) Print(ctx *context.Context, latency time.Duration, timeForm log.Logger = ac log.Now = now log.TimeFormat = timeFormat - log.Timestamp = now.Unix() + log.Timestamp = now.UnixNano() / 1000000 log.Latency = latency log.Method = method log.Path = path diff --git a/middleware/accesslog/log.go b/middleware/accesslog/log.go index 3f68f2ff03..bc9792ee74 100644 --- a/middleware/accesslog/log.go +++ b/middleware/accesslog/log.go @@ -23,7 +23,7 @@ type Log struct { // TimeFormat selected to print the Time as string, // useful on Template Formatter. TimeFormat string `json:"-" yaml:"-" toml:"-"` - // Timestamp the Now's unix timestamp (seconds). + // Timestamp the Now's unix timestamp (milliseconds). Timestamp int64 `json:"timestamp"` // Request-Response latency. @@ -192,10 +192,12 @@ type Template struct { // Custom template source. // Use this or `Tmpl/TmplName` fields. Text string - // Custom template to use, overrides the `Text` field if not nil. + // Custom template funcs to used when `Text` is not empty. + Funcs template.FuncMap + + // Custom template to use, overrides the `Text` and `Funcs` fields. Tmpl *template.Template - // If not empty then this named template/block - // is response to hold the log result. + // If not empty then this named template/block renders the log line. TmplName string dest io.Writer @@ -206,12 +208,16 @@ type Template struct { // when this formatter is registered. func (f *Template) SetOutput(dest io.Writer) { if f.Tmpl == nil { + tmpl := template.New("") + text := f.Text - if f.Text == "" { + if text != "" { + tmpl.Funcs(f.Funcs) + } else { text = defaultTmplText } - f.Tmpl = template.Must(template.New("").Parse(text)) + f.Tmpl = template.Must(tmpl.Parse(text)) } f.dest = dest