aboutsummaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
authorsillyguodong <33891828+sillyguodong@users.noreply.github.com>2023-03-10 23:54:32 +0800
committerGitHub <noreply@github.com>2023-03-10 09:54:32 -0600
commit5155ec35c571de8df62318df78c78cebc20e1aa0 (patch)
tree637594f6e7459bfdc625f8dac679d050838a4750 /modules
parentcf29ee6dd290525635a0e1b823506e81f845b978 (diff)
downloadgitea-5155ec35c571de8df62318df78c78cebc20e1aa0.tar.gz
gitea-5155ec35c571de8df62318df78c78cebc20e1aa0.zip
Parse external request id from request headers, and print it in access log (#22906)
Close: #22890. --- ### Configure in .ini file: ```ini [log] REQUEST_ID_HEADERS = X-Request-ID, X-Trace-Id ``` ### Params in Request Header ``` X-Trace-ID: trace-id-1q2w3e4r ``` ![image](https://user-images.githubusercontent.com/33891828/218665296-8fd19a0f-ada6-4236-8bdb-f99201c703e8.png) ### Log output: ![image](https://user-images.githubusercontent.com/33891828/218665225-cc242a57-4ffc-449a-a1f6-f45ded0ead60.png)
Diffstat (limited to 'modules')
-rw-r--r--modules/context/access_log.go34
-rw-r--r--modules/setting/log.go2
2 files changed, 36 insertions, 0 deletions
diff --git a/modules/context/access_log.go b/modules/context/access_log.go
index 1aaba9dc2d..515682b64b 100644
--- a/modules/context/access_log.go
+++ b/modules/context/access_log.go
@@ -6,7 +6,9 @@ package context
import (
"bytes"
"context"
+ "fmt"
"net/http"
+ "strings"
"text/template"
"time"
@@ -20,13 +22,39 @@ type routerLoggerOptions struct {
Start *time.Time
ResponseWriter http.ResponseWriter
Ctx map[string]interface{}
+ RequestID *string
}
var signedUserNameStringPointerKey interface{} = "signedUserNameStringPointerKey"
+const keyOfRequestIDInTemplate = ".RequestID"
+
+// According to:
+// TraceId: A valid trace identifier is a 16-byte array with at least one non-zero byte
+// MD5 output is 16 or 32 bytes: md5-bytes is 16, md5-hex is 32
+// SHA1: similar, SHA1-bytes is 20, SHA1-hex is 40.
+// UUID is 128-bit, 32 hex chars, 36 ASCII chars with 4 dashes
+// So, we accept a Request ID with a maximum character length of 40
+const maxRequestIDByteLength = 40
+
+func parseRequestIDFromRequestHeader(req *http.Request) string {
+ requestID := "-"
+ for _, key := range setting.Log.RequestIDHeaders {
+ if req.Header.Get(key) != "" {
+ requestID = req.Header.Get(key)
+ break
+ }
+ }
+ if len(requestID) > maxRequestIDByteLength {
+ requestID = fmt.Sprintf("%s...", requestID[:maxRequestIDByteLength])
+ }
+ return requestID
+}
+
// AccessLogger returns a middleware to log access logger
func AccessLogger() func(http.Handler) http.Handler {
logger := log.GetLogger("access")
+ needRequestID := len(setting.Log.RequestIDHeaders) > 0 && strings.Contains(setting.Log.AccessLogTemplate, keyOfRequestIDInTemplate)
logTemplate, _ := template.New("log").Parse(setting.Log.AccessLogTemplate)
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
@@ -34,6 +62,11 @@ func AccessLogger() func(http.Handler) http.Handler {
identity := "-"
r := req.WithContext(context.WithValue(req.Context(), signedUserNameStringPointerKey, &identity))
+ var requestID string
+ if needRequestID {
+ requestID = parseRequestIDFromRequestHeader(req)
+ }
+
next.ServeHTTP(w, r)
rw := w.(ResponseWriter)
@@ -47,6 +80,7 @@ func AccessLogger() func(http.Handler) http.Handler {
"RemoteAddr": req.RemoteAddr,
"Req": req,
},
+ RequestID: &requestID,
})
if err != nil {
log.Error("Could not set up chi access logger: %v", err.Error())
diff --git a/modules/setting/log.go b/modules/setting/log.go
index 5448650aad..dabdb543ab 100644
--- a/modules/setting/log.go
+++ b/modules/setting/log.go
@@ -38,6 +38,7 @@ var Log struct {
EnableAccessLog bool
AccessLogTemplate string
BufferLength int64
+ RequestIDHeaders []string
}
// GetLogDescriptions returns a race safe set of descriptions
@@ -153,6 +154,7 @@ func loadLogFrom(rootCfg ConfigProvider) {
Log.AccessLogTemplate = sec.Key("ACCESS_LOG_TEMPLATE").MustString(
`{{.Ctx.RemoteAddr}} - {{.Identity}} {{.Start.Format "[02/Jan/2006:15:04:05 -0700]" }} "{{.Ctx.Req.Method}} {{.Ctx.Req.URL.RequestURI}} {{.Ctx.Req.Proto}}" {{.ResponseWriter.Status}} {{.ResponseWriter.Size}} "{{.Ctx.Req.Referer}}\" \"{{.Ctx.Req.UserAgent}}"`,
)
+ Log.RequestIDHeaders = sec.Key("REQUEST_ID_HEADERS").Strings(",")
// the `MustString` updates the default value, and `log.ACCESS` is used by `generateNamedLogger("access")` later
_ = rootCfg.Section("log").Key("ACCESS").MustString("file")