Documentation Index
Fetch the complete documentation index at: https://docs.go-mizu.dev/llms.txt
Use this file to discover all available pages before exploring further.
Mizu uses Go’s slog package for structured logging. Every request gets logged automatically, and you can add custom log messages anywhere in your handlers.
What is structured logging?
Traditional logging writes plain text:
2024-01-15 10:30:45 User 123 logged in from 192.168.1.1
Structured logging writes key-value pairs:
{"time":"2024-01-15T10:30:45Z","level":"INFO","msg":"user logged in","user_id":123,"ip":"192.168.1.1"}
Structured logs are easier to search, filter, and analyze with tools like Elasticsearch, Loki, or CloudWatch.
Built-in request logging
When you create a Mizu app, request logging is enabled by default:
app := mizu.New() // Logger middleware included
Each request produces a log entry like:
INFO request status=200 method=GET path=/users duration_ms=12 remote_ip=127.0.0.1
Logging in handlers
Access the logger from the context to add your own log messages:
func getUser(c *mizu.Ctx) error {
id := c.Param("id")
c.Logger().Info("fetching user", "user_id", id)
user, err := database.FindUser(id)
if err != nil {
c.Logger().Error("database error", "error", err, "user_id", id)
return err
}
c.Logger().Debug("user found", "user_id", id, "name", user.Name)
return c.JSON(200, user)
}
Log levels
| Level | Method | When to use |
|---|
| Debug | c.Logger().Debug() | Detailed info for debugging |
| Info | c.Logger().Info() | Normal operations |
| Warn | c.Logger().Warn() | Something unexpected but recoverable |
| Error | c.Logger().Error() | Something failed |
c.Logger().Debug("checking cache", "key", cacheKey)
c.Logger().Info("user logged in", "user_id", userID)
c.Logger().Warn("cache miss", "key", cacheKey)
c.Logger().Error("payment failed", "error", err, "order_id", orderID)
Configuring the logger
Logger middleware options
Configure the built-in request logger:
app.Use(mizu.Logger(mizu.LoggerOptions{
Mode: mizu.Dev, // Output format
Color: true, // Colored output
Logger: customLogger, // Custom slog.Logger
RequestIDHeader: "X-Request-Id", // Header name for request ID
UserAgent: true, // Include User-Agent in logs
Output: os.Stderr, // Where to write logs
}))
Log modes
| Mode | Output | Use case |
|---|
mizu.Auto | Text for terminals, JSON otherwise | Default - adapts automatically |
mizu.Dev | Human-readable text | Local development |
mizu.Prod | JSON | Production log aggregators |
// Development: colored text output
app.Use(mizu.Logger(mizu.LoggerOptions{
Mode: mizu.Dev,
Color: true,
}))
// Production: JSON for log aggregators
app.Use(mizu.Logger(mizu.LoggerOptions{
Mode: mizu.Prod,
}))
Custom logger
Replace the default logger with your own:
import "log/slog"
// Create a custom logger
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelDebug,
}))
// Set it on the app
app.SetLogger(logger)
All handlers and middleware will use this logger via c.Logger().
Request ID tracking
The logger middleware automatically generates or propagates a request ID for each request. This helps trace requests across services.
app.Use(mizu.Logger(mizu.LoggerOptions{
RequestIDHeader: "X-Request-Id", // Use this header
}))
The request ID is:
- Read from the incoming request header (if present)
- Generated automatically (if not present)
- Added to the response headers
- Included in all log entries
Example output
Development mode (text)
10:30:45 INFO request status=200 method=GET path=/users duration_ms=12 request_id=abc123
10:30:45 INFO fetching user user_id=42
10:30:45 INFO request status=200 method=GET path=/users/42 duration_ms=8 request_id=def456
Production mode (JSON)
{"time":"2024-01-15T10:30:45Z","level":"INFO","msg":"request","status":200,"method":"GET","path":"/users","duration_ms":12,"request_id":"abc123"}
Complete example
package main
import (
"github.com/go-mizu/mizu"
)
func main() {
app := mizu.New()
app.Get("/users/{id}", func(c *mizu.Ctx) error {
id := c.Param("id")
// Add context to your logs
c.Logger().Info("fetching user",
"user_id", id,
"method", c.Request().Method,
)
user := User{ID: id, Name: "Alice"}
return c.JSON(200, user)
})
app.Listen(":3000")
}
Summary
| Feature | How |
|---|
| Log in handler | c.Logger().Info("message", "key", value) |
| Log levels | Debug, Info, Warn, Error |
| Configure format | mizu.Logger(mizu.LoggerOptions{Mode: mizu.Prod}) |
| Custom logger | app.SetLogger(myLogger) |
| Request ID | Automatic with RequestIDHeader option |
Structured logging makes debugging easier and integrates well with modern observability tools.