@@ -18,55 +18,180 @@ import (
1818)
1919
2020// LoggerConfig defines the config for Logger middleware.
21+ //
22+ // # Configuration Examples
23+ //
24+ // ## Basic Usage with Default Settings
25+ //
26+ // e.Use(middleware.Logger())
27+ //
28+ // This uses the default JSON format that logs all common request/response details.
29+ //
30+ // ## Custom Simple Format
31+ //
32+ // e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
33+ // Format: "${time_rfc3339_nano} ${status} ${method} ${uri} ${latency_human}\n",
34+ // }))
35+ //
36+ // ## JSON Format with Custom Fields
37+ //
38+ // e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
39+ // Format: `{"timestamp":"${time_rfc3339_nano}","level":"info","remote_ip":"${remote_ip}",` +
40+ // `"method":"${method}","uri":"${uri}","status":${status},"latency":"${latency_human}",` +
41+ // `"user_agent":"${user_agent}","error":"${error}"}` + "\n",
42+ // }))
43+ //
44+ // ## Custom Time Format
45+ //
46+ // e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
47+ // Format: "${time_custom} ${method} ${uri} ${status}\n",
48+ // CustomTimeFormat: "2006-01-02 15:04:05",
49+ // }))
50+ //
51+ // ## Logging Headers and Parameters
52+ //
53+ // e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
54+ // Format: `{"time":"${time_rfc3339_nano}","method":"${method}","uri":"${uri}",` +
55+ // `"status":${status},"auth":"${header:Authorization}","user":"${query:user}",` +
56+ // `"form_data":"${form:action}","session":"${cookie:session_id}"}` + "\n",
57+ // }))
58+ //
59+ // ## Custom Output (File Logging)
60+ //
61+ // file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
62+ // if err != nil {
63+ // log.Fatal(err)
64+ // }
65+ // defer file.Close()
66+ //
67+ // e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
68+ // Output: file,
69+ // }))
70+ //
71+ // ## Custom Tag Function
72+ //
73+ // e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
74+ // Format: `{"time":"${time_rfc3339_nano}","user_id":"${custom}","method":"${method}"}` + "\n",
75+ // CustomTagFunc: func(c echo.Context, buf *bytes.Buffer) (int, error) {
76+ // userID := getUserIDFromContext(c) // Your custom logic
77+ // return buf.WriteString(strconv.Itoa(userID))
78+ // },
79+ // }))
80+ //
81+ // ## Conditional Logging (Skip Certain Requests)
82+ //
83+ // e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
84+ // Skipper: func(c echo.Context) bool {
85+ // // Skip logging for health check endpoints
86+ // return c.Request().URL.Path == "/health" || c.Request().URL.Path == "/metrics"
87+ // },
88+ // }))
89+ //
90+ // ## Integration with External Logging Service
91+ //
92+ // logBuffer := &SyncBuffer{} // Thread-safe buffer for external service
93+ //
94+ // e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
95+ // Format: `{"timestamp":"${time_rfc3339_nano}","service":"my-api","level":"info",` +
96+ // `"method":"${method}","uri":"${uri}","status":${status},"latency_ms":${latency},` +
97+ // `"remote_ip":"${remote_ip}","user_agent":"${user_agent}","error":"${error}"}` + "\n",
98+ // Output: logBuffer,
99+ // }))
100+ //
101+ // # Available Tags
102+ //
103+ // ## Time Tags
104+ // - time_unix: Unix timestamp (seconds)
105+ // - time_unix_milli: Unix timestamp (milliseconds)
106+ // - time_unix_micro: Unix timestamp (microseconds)
107+ // - time_unix_nano: Unix timestamp (nanoseconds)
108+ // - time_rfc3339: RFC3339 format (2006-01-02T15:04:05Z07:00)
109+ // - time_rfc3339_nano: RFC3339 with nanoseconds
110+ // - time_custom: Uses CustomTimeFormat field
111+ //
112+ // ## Request Information
113+ // - id: Request ID from X-Request-ID header
114+ // - remote_ip: Client IP address (respects proxy headers)
115+ // - uri: Full request URI with query parameters
116+ // - host: Host header value
117+ // - method: HTTP method (GET, POST, etc.)
118+ // - path: URL path without query parameters
119+ // - route: Echo route pattern (e.g., /users/:id)
120+ // - protocol: HTTP protocol version
121+ // - referer: Referer header value
122+ // - user_agent: User-Agent header value
123+ //
124+ // ## Response Information
125+ // - status: HTTP status code
126+ // - error: Error message if request failed
127+ // - latency: Request processing time in nanoseconds
128+ // - latency_human: Human-readable processing time
129+ // - bytes_in: Request body size in bytes
130+ // - bytes_out: Response body size in bytes
131+ //
132+ // ## Dynamic Tags
133+ // - header:<NAME>: Value of specific header (e.g., header:Authorization)
134+ // - query:<NAME>: Value of specific query parameter (e.g., query:user_id)
135+ // - form:<NAME>: Value of specific form field (e.g., form:username)
136+ // - cookie:<NAME>: Value of specific cookie (e.g., cookie:session_id)
137+ // - custom: Output from CustomTagFunc
138+ //
139+ // # Troubleshooting
140+ //
141+ // ## Common Issues
142+ //
143+ // 1. **Missing logs**: Check if Skipper function is filtering out requests
144+ // 2. **Invalid JSON**: Ensure CustomTagFunc outputs valid JSON content
145+ // 3. **Performance issues**: Consider using a buffered writer for high-traffic applications
146+ // 4. **File permission errors**: Ensure write permissions when logging to files
147+ //
148+ // ## Performance Tips
149+ //
150+ // - Use time_unix formats for better performance than time_rfc3339
151+ // - Minimize the number of dynamic tags (header:, query:, form:, cookie:)
152+ // - Use Skipper to exclude high-frequency, low-value requests (health checks, etc.)
153+ // - Consider async logging for very high-traffic applications
21154type LoggerConfig struct {
22155 // Skipper defines a function to skip middleware.
156+ // Use this to exclude certain requests from logging (e.g., health checks).
157+ //
158+ // Example:
159+ // Skipper: func(c echo.Context) bool {
160+ // return c.Request().URL.Path == "/health"
161+ // },
23162 Skipper Skipper
24163
25- // Tags to construct the logger format.
26- //
27- // - time_unix
28- // - time_unix_milli
29- // - time_unix_micro
30- // - time_unix_nano
31- // - time_rfc3339
32- // - time_rfc3339_nano
33- // - time_custom
34- // - id (Request ID)
35- // - remote_ip
36- // - uri
37- // - host
38- // - method
39- // - path
40- // - route
41- // - protocol
42- // - referer
43- // - user_agent
44- // - status
45- // - error
46- // - latency (In nanoseconds)
47- // - latency_human (Human readable)
48- // - bytes_in (Bytes received)
49- // - bytes_out (Bytes sent)
50- // - header:<NAME>
51- // - query:<NAME>
52- // - form:<NAME>
53- // - custom (see CustomTagFunc field)
54- //
55- // Example "${remote_ip} ${status}"
164+ // Format defines the logging format using template tags.
165+ // Tags are enclosed in ${} and replaced with actual values.
166+ // See the detailed tag documentation above for all available options.
56167 //
57- // Optional. Default value DefaultLoggerConfig.Format.
168+ // Default: JSON format with common fields
169+ // Example: "${time_rfc3339_nano} ${status} ${method} ${uri} ${latency_human}\n"
58170 Format string `yaml:"format"`
59171
60- // Optional. Default value DefaultLoggerConfig.CustomTimeFormat.
172+ // CustomTimeFormat specifies the time format used by ${time_custom} tag.
173+ // Uses Go's reference time: Mon Jan 2 15:04:05 MST 2006
174+ //
175+ // Default: "2006-01-02 15:04:05.00000"
176+ // Example: "2006-01-02 15:04:05" or "15:04:05.000"
61177 CustomTimeFormat string `yaml:"custom_time_format"`
62178
63- // CustomTagFunc is function called for `${custom}` tag to output user implemented text by writing it to buf.
64- // Make sure that outputted text creates valid JSON string with other logged tags.
65- // Optional.
179+ // CustomTagFunc is called when ${custom} tag is encountered.
180+ // Use this to add application-specific information to logs.
181+ // The function should write valid content for your log format.
182+ //
183+ // Example:
184+ // CustomTagFunc: func(c echo.Context, buf *bytes.Buffer) (int, error) {
185+ // userID := getUserFromContext(c)
186+ // return buf.WriteString(`"user_id":"` + userID + `"`)
187+ // },
66188 CustomTagFunc func (c echo.Context , buf * bytes.Buffer ) (int , error )
67189
68- // Output is a writer where logs in JSON format are written.
69- // Optional. Default value os.Stdout.
190+ // Output specifies where logs are written.
191+ // Can be any io.Writer: files, buffers, network connections, etc.
192+ //
193+ // Default: os.Stdout
194+ // Example: Custom file, syslog, or external logging service
70195 Output io.Writer
71196
72197 template * fasttemplate.Template
@@ -85,13 +210,55 @@ var DefaultLoggerConfig = LoggerConfig{
85210 colorer : color .New (),
86211}
87212
88- // Logger returns a middleware that logs HTTP requests.
213+ // Logger returns a middleware that logs HTTP requests using the default configuration.
214+ //
215+ // The default format logs requests as JSON with the following fields:
216+ // - time: RFC3339 nano timestamp
217+ // - id: Request ID from X-Request-ID header
218+ // - remote_ip: Client IP address
219+ // - host: Host header
220+ // - method: HTTP method
221+ // - uri: Request URI
222+ // - user_agent: User-Agent header
223+ // - status: HTTP status code
224+ // - error: Error message (if any)
225+ // - latency: Processing time in nanoseconds
226+ // - latency_human: Human-readable processing time
227+ // - bytes_in: Request body size
228+ // - bytes_out: Response body size
229+ //
230+ // Example output:
231+ //
232+ // {"time":"2023-01-15T10:30:45.123456789Z","id":"","remote_ip":"127.0.0.1",
233+ // "host":"localhost:8080","method":"GET","uri":"/users/123","user_agent":"curl/7.81.0",
234+ // "status":200,"error":"","latency":1234567,"latency_human":"1.234567ms",
235+ // "bytes_in":0,"bytes_out":42}
236+ //
237+ // For custom configurations, use LoggerWithConfig instead.
89238func Logger () echo.MiddlewareFunc {
90239 return LoggerWithConfig (DefaultLoggerConfig )
91240}
92241
93- // LoggerWithConfig returns a Logger middleware with config.
94- // See: `Logger()`.
242+ // LoggerWithConfig returns a Logger middleware with custom configuration.
243+ //
244+ // This function allows you to customize all aspects of request logging including:
245+ // - Log format and fields
246+ // - Output destination
247+ // - Time formatting
248+ // - Custom tags and logic
249+ // - Request filtering
250+ //
251+ // See LoggerConfig documentation for detailed configuration examples and options.
252+ //
253+ // Example:
254+ //
255+ // e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{
256+ // Format: "${time_rfc3339} ${status} ${method} ${uri} ${latency_human}\n",
257+ // Output: customLogWriter,
258+ // Skipper: func(c echo.Context) bool {
259+ // return c.Request().URL.Path == "/health"
260+ // },
261+ // }))
95262func LoggerWithConfig (config LoggerConfig ) echo.MiddlewareFunc {
96263 // Defaults
97264 if config .Skipper == nil {
0 commit comments