Log system
Goffee's log system is based on the standard log package. It provides a simple interface for logging messages at different severity levels, with support for file output, optional terminal output with ANSI color codes, configurable minimum log levels, and automatic log rotation backed by lumberjack.
Configuration
The log system is configured using environment variables in your .env or .env-dev file:
LOG_STDOUT_ENABLE=true # Set to true to also print logs to the terminal
LOG_LEVEL=debug # Minimum log level: debug, info, warning, error
Log levels
The available log levels are:
debug- Detailed debug information (cyan colored in terminal)info- General informational messages (blue colored in terminal)warning- Warning messages (yellow colored in terminal)error- Error messages (red colored in terminal)
When a minimum level is set, messages below that level are silently discarded. For example, if LOG_LEVEL=warning, both debug and info messages will not be written.
Using the logger
To use the logger in your application, access it via the context in your controllers:
package controllers
import (
"git.smarteching.com/goffee/core/v2"
)
func SampleController(c *core.Context) *core.Response {
loggr := c.GetLogger()
loggr.Debug("This is a debug message")
loggr.Info("This is an info message")
loggr.Warning("This is a warning message")
loggr.Error("This is an error message")
return c.Response.Json(`{"message": "check the logs"}`)
}
Terminal output with colors
When LOG_STDOUT_ENABLE=true is set, log messages are printed to the terminal in addition to the log file. Each severity level is color-coded for easy visual scanning:
DEBUGmessages appear with a cyan prefixINFOmessages appear with a blue prefixWARNINGmessages appear with a yellow prefixERRORmessages appear with a red prefix
The log file always contains plain text without ANSI color codes, making it safe to use with log processing tools.
Log file location and rotation
The log destination (the file path) and the log rotation behaviour are not
configured in main.go. Instead they live in your app's config/ package, alongside the
other feature toggles (config/queue.go, config/gorm.go, ...), in a dedicated
config/log.go file. main.go only wires that config in with a single call.
Goffee ships a rotating file driver, logger.LogRotatingFileDriver, built on top of
lumberjack. It bounds the log file by rotating
it once it reaches a maximum size, keeping a limited number of backups, deleting backups
older than a set number of days, and optionally gzip-compressing the rotated files.
Configure it in config/log.go
Create a config/log.go that returns a core.LogConfig. This is the single source of truth
for where logs are written and how they rotate:
package config
import "git.smarteching.com/goffee/core/v2"
// Retrieve the main config for the logs
func GetLogConfig() core.LogConfig {
return core.LogConfig{
Filename: "logs/app.log", // Path of the log file (relative to the app root)
MaxSize: 10, // Megabytes before rotating
MaxBackups: 3, // Maximum number of backup files to keep
MaxAge: 28, // Days to retain old backups
Compress: true, // Compress backups with gzip (.gz)
LocalTime: false, // Use local time for rotation timestamps
}
}
Filename is resolved relative to the application root (base path) unless it is already an
absolute path.
Wire it in main.go
main.go contains nothing about file paths or rotation — just this single call, which
installs a LogRotatingFileDriver using the values from config/log.go:
// Handle the logs (rotation is configured in config/log.go)
app.SetLogConfig(config.GetLogConfig())
App.SetLogConfig is a convenience shortcut over the lower-level App.SetLogsDriver. If
you prefer to build the driver by hand, the equivalent is:
app.SetLogsDriver(&logger.LogRotatingFileDriver{
Config: logger.LogRotationConfig{
Filename: path.Join(basePath, "logs/app.log"),
MaxSize: 10,
MaxBackups: 3,
MaxAge: 28,
Compress: true,
},
})
Rotation parameters
| Parameter | Meaning | Notes |
|---|---|---|
Filename | Path of the active log file. | Backups are written next to it, e.g. app-2026-01-02T15-04-05.000.log. |
MaxSize | Maximum size in megabytes before the file is rotated. | 0 uses lumberjack's default of 100. |
MaxBackups | Maximum number of old log files to retain. | 0 keeps all backups. |
MaxAge | Maximum number of days to retain old log files. | 0 keeps them forever. |
Compress | Gzip rotated files (.gz) when true. | Saves disk space at a small CPU cost. |
LocalTime | Use local time for the rotation timestamps. | When false (default), UTC is used. |
Rotation is performed lazily: lumberjack rotates on the next write once the active file
exceeds MaxSize. A freshly created file is not rotated until the threshold is crossed by
an actual write, so a single huge burst can briefly exceed the limit.
Legacy file driver
If you need a plain file with no rotation — for a quick prototype, or when an external
log processor handles rotation for you — the legacy logger.LogFileDriver still exists. You
would pass the file path directly, bypassing config/log.go:
app.SetLogsDriver(&logger.LogFileDriver{
FilePath: path.Join(basePath, "logs/app.log"),
})
This driver does not honour the rotation settings in config/log.go. New apps should
prefer LogRotatingFileDriver via app.SetLogConfig(config.GetLogConfig()).