structured-error-logger
logger is a structured error logger that integrates well with github.com/rohanthewiz/serr. logger.LogErr will write out all the context stored in the SErr.
SKILL.md
| Name | structured-error-logger |
| Description | logger is a structured error logger that integrates well with github.com/rohanthewiz/serr. logger.LogErr will write out all the context stored in the SErr. |
name: structured-error-logger description: "logger is a structured error logger that integrates well with github.com/rohanthewiz/serr. logger.LogErr will write out all the context stored in the SErr."
Logger Package
A structured logging package for Go that wraps logrus with enhanced support for github.com/rohanthewiz/serr structured errors.
Installation
import "github.com/rohanthewiz/logger"
Initialization
Initialize the logger at application startup:
logger.InitLog(logger.LogConfig{
Formatter: "json", // "json" or "text"
LogLevel: "debug", // "debug" | "info" | "warn" | "error"
})
defer logger.CloseLog() // Ensure all async logs are flushed
Core Functions
Basic Logging with Key-Value Pairs
The Log function accepts a level, message, and optional key-value pairs:
logger.Log("info", "Conveying some info", "attribute1", "value1", "attribute2", "value2")
// => {"attribute1":"value1","attribute2":"value2","level":"info","msg":"Conveying some info","time":"..."}
Convenience Wrappers
Use wrapper functions for cleaner code:
logger.Info("Simple info message", "key1", "value1", "key2", "value2")
logger.Debug("Simple debug message", "key1", "value1")
logger.Warn("Simple warning message", "key1", "value1")
logger.Error("Simple error message", "key1", "value1")
Formatted Logging
Printf-style formatting is available:
logger.F("Number: %d String: %s", 42, "test") // log info-level message
logger.InfoF("Info message with %s and %d", "string", 123)
logger.DebugF("Debug message with %.2f", 3.14159)
logger.WarnF("Warning: %s occurred %d times", "event", 5)
logger.ErrorF("Error code: %x", 255)
Error Logging with SErr Integration
The key feature of this package is its awareness of github.com/rohanthewiz/serr structured errors. When logging errors, use LogErr or its alias Err:
Standard Error Logging
err := errors.New("This is the original error")
// Log a standard error - message will be err.Error()
logger.LogErr(err)
// => {"level":"error","msg":"This is the original error","time":"..."}
// With additional context
logger.LogErr(err, "info", "message2", "key1", "value1", "key2", "value2")
// => {"info":"message2","key1":"value1","key2":"value2","level":"error","msg":"This is the original error","time":"..."}
// Shorter form using Err
logger.Err(err, "message2", "key1", "value1")
SErr Structured Error Logging
When logging a serr.SErr, all embedded context is automatically extracted and included in the log output:
ser := serr.New("This is the original error", "errFld1", "errVal1", "errFld2", "errVal2")
// All SErr fields are extracted and logged
logger.Err(ser)
// => {"errFld1":"errVal1","errFld2":"errVal2","error":"This is the original error",
// "function":"package.Function","level":"error","location":"file.go:40",
// "msg":"This is the original error","time":"..."}
// Add additional context at log time
logger.Err(ser, "error", "Err: from my point of view")
// => {"errFld1":"errVal1","errFld2":"errVal2","error":"Err: from my point of view",
// "function":"package.Function","level":"error","location":"file.go:40",
// "msg":"This is the original error","time":"..."}
// Combine SErr fields with additional key-value pairs
logger.Err(ser, "info", "message2", "key1", "value1", "key2", "value2")
Key Behavior Notes
LogErrandErrautomatically append caller context (function name and location)- All attributes stored in a
serr.SErrare unpacked into log fields - Multiple values for the same attribute are joined with
-> UserMsgandUserMsgSeveritykeys are excluded (reserved for UI)- Logging a
nilerror logs an info message about the nil error instead
Async Logging
For non-blocking logging:
logger.LogAsync("info", "An Async message")
logger.LogAsync("error", "An Async error message", "key1", "value1")
// Shorter form
logger.Async("info", "An Async message")
Configuration Options
type LogConfig struct {
EnvPrefix string // Prefix for all log messages
Formatter string // "text" | "json"
LogLevel string // "debug" | "info" | "warn" | "error"
LogChanSize int // Buffer size for async logs (default: 2000)
TeamsLogCfg TeamsLogCfg // Microsoft Teams integration
SlackAPICfg SlackAPICfg // Slack integration
LogChanCfg LogChanCfg // Send text-formatted logs to a string channel
}
Microsoft Teams Integration
logger.InitLog(logger.LogConfig{
Formatter: "json",
LogLevel: "debug",
TeamsLogCfg: logger.TeamsLogCfg{
Enabled: true,
Endpoint: "https://your-teams-webhook-url",
LogLevel: "warn", // Only log warn and above to Teams
},
})
Slack Integration
logger.InitLog(logger.LogConfig{
Formatter: "json",
LogLevel: "debug",
SlackAPICfg: logger.SlackAPICfg{
Enabled: true,
Token: "xoxb-your-token",
Channel: "C086K...",
LogLevel: "warn",
UseBlocks: true, // Rich block formatting
},
})
LogChan Hook (Send Logs to a Channel)
Route logrus-text-formatted log lines to a chan string for custom processing
(e.g. forwarding to a UI, writing to a database, or bridging to another system).
// Create a buffered channel to receive log messages
logCh := make(chan string, 100)
logger.InitLog(logger.LogConfig{
Formatter: "text",
LogLevel: "debug",
LogChanCfg: logger.LogChanCfg{
Enabled: true,
Ch: logCh,
LogLevel: "warn", // Only send warn and above to the channel
},
})
defer logger.CloseLog()
// Consume messages from the channel in a separate goroutine
go func() {
for msg := range logCh {
fmt.Print("received log: ", msg)
}
}()
logger.Warn("disk usage high", "percent", "92")
// The consumer goroutine receives the text-formatted log line
The hook uses a non-blocking send — if the channel is full, messages are dropped rather than blocking the logging goroutine.
Log Levels
Available via logger.LogLevel:
logger.LogLevel.Debug // "debug"
logger.LogLevel.Info // "info"
logger.LogLevel.Warn // "warn"
logger.LogLevel.Error // "error"
Or use string constants:
logger.StrLevelDebug // "debug"
logger.StrLevelInfo // "info"
logger.StrLevelWarn // "warn"
logger.StrLevelError // "error"
Utility Functions
Stack Trace
Print the current stack trace for debugging:
logger.PrintStackTrace()
Location Helper
Add location context to log messages:
logger.Log("error", "Some error occurred", "location", serr.FunctionLoc(serr.FrameLevels.FrameLevel1))
// => {"level":"error","location":"package/file.go:25","msg":"Some error occurred","time":"..."}
Best Practices
- Always call
defer logger.CloseLog()afterInitLog()to ensure async logs are flushed - Use
logger.LogErr(err)orlogger.Err(err)for error logging to capture full context - Prefer
serr.Wrap(err)to wrap errors before logging for maximum context - Use structured key-value pairs instead of string formatting for searchable logs
- Set appropriate log levels for different environments (debug for dev, info/warn for prod)