func captureZapFieldsForRequest()

in internal/util/logging.go [117:169]


func captureZapFieldsForRequest(handler http.Handler, w http.ResponseWriter, req *http.Request) (string, []zap.Field) {
	resp := httpsnoop.CaptureMetrics(handler, w, req)

	domain, port, err := net.SplitHostPort(req.Host)
	if err != nil {
		domain = req.Host
	}
	if ip := net.ParseIP(domain); ip != nil && ip.To16() != nil && ip.To4() == nil {
		// For ECS, if the host part of an url is an IPv6, it must keep the brackets
		// when stored in `url.domain` (but not when stored in ip fields).
		domain = "[" + domain + "]"
	}
	sourceHost, _, err := net.SplitHostPort(req.RemoteAddr)
	if err != nil {
		sourceHost = req.RemoteAddr
	}
	fields := []zap.Field{
		// Request fields.
		zap.String("source.address", sourceHost),
		zap.String("http.request.method", req.Method),
		zap.String("url.path", req.URL.Path),
		zap.String("url.domain", domain),

		// Response fields.
		zap.Int("http.response.code", resp.Code),
		zap.Int64("http.response.body.bytes", resp.Written),
		zap.Int64("event.duration", resp.Duration.Nanoseconds()),
	}

	// Fields that are not always available.
	if ip := net.ParseIP(sourceHost); ip != nil {
		fields = append(fields, zap.String("source.ip", sourceHost))
	} else {
		fields = append(fields, zap.String("source.domain", sourceHost))
	}
	if referer := req.Referer(); referer != "" {
		fields = append(fields, zap.String("http.request.referer", referer))
	}
	if userAgent := req.UserAgent(); userAgent != "" {
		fields = append(fields, zap.String("user_agent.original", userAgent))
	}
	if query := req.URL.RawQuery; query != "" {
		fields = append(fields, zap.String("url.query", query))
	}
	if port != "" {
		if intPort, err := strconv.Atoi(port); err == nil && intPort != 0 {
			fields = append(fields, zap.Int("url.port", intPort))
		}
	}

	message := req.Method + " " + req.URL.Path + " " + req.Proto
	return message, fields
}