mirror of
https://github.com/astaxie/beego.git
synced 2024-11-22 13:10:54 +00:00
Merge pull request #2863 from gadelkareem/develop
Add JSON or Apache access log formatting option to config: AccessLogsFormat = JSON_FORMAT or APACHE_FORMAT ref #2738
This commit is contained in:
commit
b7eb3963f5
@ -67,6 +67,7 @@ func oldMap() map[string]interface{} {
|
|||||||
m["BConfig.WebConfig.Session.SessionDomain"] = BConfig.WebConfig.Session.SessionDomain
|
m["BConfig.WebConfig.Session.SessionDomain"] = BConfig.WebConfig.Session.SessionDomain
|
||||||
m["BConfig.WebConfig.Session.SessionDisableHTTPOnly"] = BConfig.WebConfig.Session.SessionDisableHTTPOnly
|
m["BConfig.WebConfig.Session.SessionDisableHTTPOnly"] = BConfig.WebConfig.Session.SessionDisableHTTPOnly
|
||||||
m["BConfig.Log.AccessLogs"] = BConfig.Log.AccessLogs
|
m["BConfig.Log.AccessLogs"] = BConfig.Log.AccessLogs
|
||||||
|
m["BConfig.Log.AccessLogsFormat"] = BConfig.Log.AccessLogsFormat
|
||||||
m["BConfig.Log.FileLineNum"] = BConfig.Log.FileLineNum
|
m["BConfig.Log.FileLineNum"] = BConfig.Log.FileLineNum
|
||||||
m["BConfig.Log.Outputs"] = BConfig.Log.Outputs
|
m["BConfig.Log.Outputs"] = BConfig.Log.Outputs
|
||||||
return m
|
return m
|
||||||
|
@ -106,6 +106,7 @@ type SessionConfig struct {
|
|||||||
// LogConfig holds Log related config
|
// LogConfig holds Log related config
|
||||||
type LogConfig struct {
|
type LogConfig struct {
|
||||||
AccessLogs bool
|
AccessLogs bool
|
||||||
|
AccessLogsFormat string //access log format: JSON_FORMAT, APACHE_FORMAT or empty string
|
||||||
FileLineNum bool
|
FileLineNum bool
|
||||||
Outputs map[string]string // Store Adaptor : config
|
Outputs map[string]string // Store Adaptor : config
|
||||||
}
|
}
|
||||||
@ -246,6 +247,7 @@ func newBConfig() *Config {
|
|||||||
},
|
},
|
||||||
Log: LogConfig{
|
Log: LogConfig{
|
||||||
AccessLogs: false,
|
AccessLogs: false,
|
||||||
|
AccessLogsFormat: "",
|
||||||
FileLineNum: true,
|
FileLineNum: true,
|
||||||
Outputs: map[string]string{"console": ""},
|
Outputs: map[string]string{"console": ""},
|
||||||
},
|
},
|
||||||
|
84
logs/accesslog.go
Normal file
84
logs/accesslog.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
// Copyright 2014 beego Author. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package logs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
apacheFormatPattern = "%s - - [%s] \"%s %d %d\" %f %s %s\n"
|
||||||
|
apacheFormat = "APACHE_FORMAT"
|
||||||
|
jsonFormat = "JSON_FORMAT"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AccessLogRecord struct {
|
||||||
|
RemoteAddr string `json:"remote_addr"`
|
||||||
|
RequestTime time.Time `json:"request_time"`
|
||||||
|
RequestMethod string `json:"request_method"`
|
||||||
|
Request string `json:"request"`
|
||||||
|
ServerProtocol string `json:"server_protocol"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
BodyBytesSent int64 `json:"body_bytes_sent"`
|
||||||
|
ElapsedTime time.Duration `json:"elapsed_time"`
|
||||||
|
HttpReferrer string `json:"http_referrer"`
|
||||||
|
HttpUserAgent string `json:"http_user_agent"`
|
||||||
|
RemoteUser string `json:"remote_user"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *AccessLogRecord) json() ([]byte, error) {
|
||||||
|
buffer := &bytes.Buffer{}
|
||||||
|
encoder := json.NewEncoder(buffer)
|
||||||
|
disableEscapeHTML(encoder)
|
||||||
|
|
||||||
|
err := encoder.Encode(r)
|
||||||
|
return buffer.Bytes(), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func disableEscapeHTML(i interface{}) {
|
||||||
|
e, ok := i.(interface {
|
||||||
|
SetEscapeHTML(bool)
|
||||||
|
});
|
||||||
|
if ok {
|
||||||
|
e.SetEscapeHTML(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AccessLog(r *AccessLogRecord, format string) {
|
||||||
|
var msg string
|
||||||
|
|
||||||
|
switch format {
|
||||||
|
|
||||||
|
case apacheFormat:
|
||||||
|
timeFormatted := r.RequestTime.Format("02/Jan/2006 03:04:05")
|
||||||
|
msg = fmt.Sprintf(apacheFormatPattern, r.RemoteAddr, timeFormatted, r.Request, r.Status, r.BodyBytesSent,
|
||||||
|
r.ElapsedTime.Seconds(), r.HttpReferrer, r.HttpUserAgent)
|
||||||
|
case jsonFormat:
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
jsonData, err := r.json()
|
||||||
|
if err != nil {
|
||||||
|
msg = fmt.Sprintf(`{"Error": "%s"}`, err)
|
||||||
|
} else {
|
||||||
|
msg = string(jsonData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
beeLogger.Debug(msg)
|
||||||
|
}
|
68
router.go
68
router.go
@ -43,7 +43,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
routerTypeBeego = iota
|
routerTypeBeego = iota
|
||||||
routerTypeRESTFul
|
routerTypeRESTFul
|
||||||
routerTypeHandler
|
routerTypeHandler
|
||||||
)
|
)
|
||||||
@ -874,17 +874,20 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Admin:
|
Admin:
|
||||||
//admin module record QPS
|
//admin module record QPS
|
||||||
|
|
||||||
|
statusCode := context.ResponseWriter.Status
|
||||||
|
if statusCode == 0 {
|
||||||
|
statusCode = 200
|
||||||
|
}
|
||||||
|
|
||||||
if BConfig.Listen.EnableAdmin {
|
if BConfig.Listen.EnableAdmin {
|
||||||
timeDur := time.Since(startTime)
|
timeDur := time.Since(startTime)
|
||||||
pattern := ""
|
pattern := ""
|
||||||
if routerInfo != nil {
|
if routerInfo != nil {
|
||||||
pattern = routerInfo.pattern
|
pattern = routerInfo.pattern
|
||||||
}
|
}
|
||||||
statusCode := context.ResponseWriter.Status
|
|
||||||
if statusCode == 0 {
|
|
||||||
statusCode = 200
|
|
||||||
}
|
|
||||||
if FilterMonitorFunc(r.Method, r.URL.Path, timeDur, pattern, statusCode) {
|
if FilterMonitorFunc(r.Method, r.URL.Path, timeDur, pattern, statusCode) {
|
||||||
if runRouter != nil {
|
if runRouter != nil {
|
||||||
go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, runRouter.Name(), timeDur)
|
go toolbox.StatisticsMap.AddStatistics(r.Method, r.URL.Path, runRouter.Name(), timeDur)
|
||||||
@ -898,36 +901,47 @@ Admin:
|
|||||||
timeDur := time.Since(startTime)
|
timeDur := time.Since(startTime)
|
||||||
var devInfo string
|
var devInfo string
|
||||||
|
|
||||||
statusCode := context.ResponseWriter.Status
|
|
||||||
if statusCode == 0 {
|
|
||||||
statusCode = 200
|
|
||||||
}
|
|
||||||
|
|
||||||
iswin := (runtime.GOOS == "windows")
|
iswin := (runtime.GOOS == "windows")
|
||||||
statusColor := logs.ColorByStatus(iswin, statusCode)
|
statusColor := logs.ColorByStatus(iswin, statusCode)
|
||||||
methodColor := logs.ColorByMethod(iswin, r.Method)
|
methodColor := logs.ColorByMethod(iswin, r.Method)
|
||||||
resetColor := logs.ColorByMethod(iswin, "")
|
resetColor := logs.ColorByMethod(iswin, "")
|
||||||
|
if BConfig.Log.AccessLogsFormat != "" {
|
||||||
if findRouter {
|
record := &logs.AccessLogRecord{
|
||||||
if routerInfo != nil {
|
RemoteAddr: context.Input.IP(),
|
||||||
devInfo = fmt.Sprintf("|%15s|%s %3d %s|%13s|%8s|%s %-7s %s %-3s r:%s", context.Input.IP(), statusColor, statusCode,
|
RequestTime: startTime,
|
||||||
resetColor, timeDur.String(), "match", methodColor, r.Method, resetColor, r.URL.Path,
|
RequestMethod: r.Method,
|
||||||
routerInfo.pattern)
|
Request: fmt.Sprintf("%s %s %s", r.Method, r.RequestURI, r.Proto),
|
||||||
|
ServerProtocol: r.Proto,
|
||||||
|
Host: r.Host,
|
||||||
|
Status: statusCode,
|
||||||
|
ElapsedTime: timeDur,
|
||||||
|
HttpReferrer: r.Header.Get("Referer"),
|
||||||
|
HttpUserAgent: r.Header.Get("User-Agent"),
|
||||||
|
RemoteUser: r.Header.Get("Remote-User"),
|
||||||
|
BodyBytesSent: 0, //@todo this one is missing!
|
||||||
|
}
|
||||||
|
logs.AccessLog(record, BConfig.Log.AccessLogsFormat)
|
||||||
|
}else {
|
||||||
|
if findRouter {
|
||||||
|
if routerInfo != nil {
|
||||||
|
devInfo = fmt.Sprintf("|%15s|%s %3d %s|%13s|%8s|%s %-7s %s %-3s r:%s", context.Input.IP(), statusColor, statusCode,
|
||||||
|
resetColor, timeDur.String(), "match", methodColor, r.Method, resetColor, r.URL.Path,
|
||||||
|
routerInfo.pattern)
|
||||||
|
} else {
|
||||||
|
devInfo = fmt.Sprintf("|%15s|%s %3d %s|%13s|%8s|%s %-7s %s %-3s", context.Input.IP(), statusColor, statusCode, resetColor,
|
||||||
|
timeDur.String(), "match", methodColor, r.Method, resetColor, r.URL.Path)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
devInfo = fmt.Sprintf("|%15s|%s %3d %s|%13s|%8s|%s %-7s %s %-3s", context.Input.IP(), statusColor, statusCode, resetColor,
|
devInfo = fmt.Sprintf("|%15s|%s %3d %s|%13s|%8s|%s %-7s %s %-3s", context.Input.IP(), statusColor, statusCode, resetColor,
|
||||||
timeDur.String(), "match", methodColor, r.Method, resetColor, r.URL.Path)
|
timeDur.String(), "nomatch", methodColor, r.Method, resetColor, r.URL.Path)
|
||||||
|
}
|
||||||
|
if iswin {
|
||||||
|
logs.W32Debug(devInfo)
|
||||||
|
} else {
|
||||||
|
logs.Debug(devInfo)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
devInfo = fmt.Sprintf("|%15s|%s %3d %s|%13s|%8s|%s %-7s %s %-3s", context.Input.IP(), statusColor, statusCode, resetColor,
|
|
||||||
timeDur.String(), "nomatch", methodColor, r.Method, resetColor, r.URL.Path)
|
|
||||||
}
|
|
||||||
if iswin {
|
|
||||||
logs.W32Debug(devInfo)
|
|
||||||
} else {
|
|
||||||
logs.Debug(devInfo)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call WriteHeader if status code has been set changed
|
// Call WriteHeader if status code has been set changed
|
||||||
if context.Output.Status != 0 {
|
if context.Output.Status != 0 {
|
||||||
context.ResponseWriter.WriteHeader(context.Output.Status)
|
context.ResponseWriter.WriteHeader(context.Output.Status)
|
||||||
|
Loading…
Reference in New Issue
Block a user