Hone logo
Hone
Problems

Go Web Server Access Logging

Building robust web applications requires understanding how users interact with your service. Access logging is a fundamental practice that records details of each incoming request, providing invaluable insights for debugging, security analysis, and performance monitoring. This challenge will guide you through implementing an effective access logging middleware for a Go web server.

Problem Description

Your task is to create a Go middleware function that intercepts incoming HTTP requests to a web server and logs relevant information about each request. This middleware should be integrated with a simple HTTP server to demonstrate its functionality.

Key Requirements:

  • Log Format: Each log entry should include:
    • Timestamp of the request (e.g., 2006-01-02 15:04:05)
    • HTTP Method (e.g., GET, POST)
    • Request URL (including path and query parameters)
    • Remote IP Address of the client
    • HTTP Status Code returned by the handler
    • Request Duration (time taken to process the request)
  • Middleware Structure: The logging functionality should be implemented as a Go HTTP middleware. This means it should accept an http.Handler and return a new http.Handler that wraps the original handler.
  • Output Destination: Log entries should be written to standard output (os.Stdout).
  • Integration: The middleware should be easily pluggable into a standard Go http.ServeMux or net/http server.

Expected Behavior:

When a request hits the server, the middleware should record the start time, pass the request to the next handler in the chain, record the end time and the status code from the response, calculate the duration, and then print the formatted log entry before returning the response to the client.

Edge Cases to Consider:

  • Requests that result in errors or panics (though for this challenge, we'll focus on successful responses and standard error handling).
  • Requests with unusual URL structures or methods.

Examples

Example 1: Simple GET Request

Input:
- A GET request to "/hello" with no query parameters.
- The server handler for "/hello" returns a 200 OK status and a simple "Hello, World!" body.

Expected Output (example, actual timestamp will vary):
2023-10-27 10:30:00 GET /hello - 192.168.1.100 200 15ms

Example 2: POST Request with Query Parameters

Input:
- A POST request to "/submit?id=123"
- The server handler for "/submit" returns a 201 Created status.

Expected Output (example, actual timestamp will vary):
2023-10-27 10:31:05 POST /submit?id=123 - 10.0.0.5 201 30ms

Example 3: Handler that takes longer to process

Input:
- A GET request to "/long-process"
- The server handler for "/long-process" simulates a delay (e.g., using time.Sleep) and returns a 200 OK status.

Expected Output (example, actual timestamp and duration will vary):
2023-10-27 10:35:15 GET /long-process - 172.16.0.1 200 500ms

Constraints

  • The Go version used should be Go 1.18 or later.
  • The solution should be a single Go file (main.go).
  • No external third-party logging libraries are allowed. Use only standard Go libraries.
  • Performance is important; the middleware should introduce minimal overhead.

Notes

  • Consider using time.Now() to capture timestamps and time.Since() to calculate durations.
  • The net/http package provides tools for accessing request details like r.Method, r.URL, and r.RemoteAddr.
  • To access the status code, you'll need a way to capture it from the http.ResponseWriter. A common pattern is to create a custom ResponseWriter that wraps the original and intercepts the WriteHeader method.
  • Think about how to chain your middleware with actual handler functions. The http.HandlerFunc type can be useful.
Loading editor...
go