sane logging defaults for go
sneak
3638c0c4df
# Aider chat conversation: USER: create an extended type called ExtendedEvent which conforms to Event. in the custom handler, attach the file and line number information from the caller to the ExtendedEvent. that way all of the extendedhandlers can access it without using the runtime module. add getters to the ExtendedEvent interface and type. ASSISTANT: To create an `ExtendedEvent` type that conforms to `Event` and includes file and line number information, we need to: 1. Define the `ExtendedEvent` type and interface in `event.go`. 2. Update the `CustomHandler` in `simplelog.go` to attach file and line number information to the `ExtendedEvent`. 3. Add getters to the `ExtendedEvent` interface and type. Here are the *SEARCH/REPLACE* blocks: event.go ```go <<<<<<< SEARCH } ======= } type ExtendedEvent interface { GetID() uuid.UUID GetTimestamp() time.Time GetLevel() string GetMessage() string GetData() json.RawMessage GetFile() string GetLine() int } type extendedEvent struct { Event File string `json:"file"` Line int `json:"line"` } func (e extendedEvent) GetID() uuid.UUID { return e.ID } func (e extendedEvent) GetTimestamp() time.Time { return e.Timestamp } func (e extendedEvent) GetLevel() string { return e.Level } func (e extendedEvent) GetMessage() string { return e.Message } func (e extendedEvent) GetData() json.RawMessage { return e.Data } func (e extendedEvent) GetFile() string { return e.File } func (e extendedEvent) GetLine() int { return e.Line } func NewExtendedEvent(level, message string, data json.RawMessage, file string, line int) ExtendedEvent { return extendedEvent{ Event: NewEvent(level, message, data), File: file, Line: line, } } >>>>>>> REPLACE ``` simplelog.go ```go <<<<<<< SEARCH "log" ======= "log" "runtime" >>>>>>> REPLACE ``` simplelog.go ```go <<<<<<< SEARCH event := NewEvent(record.Level.String(), record.Message, jsonData) select { case r.ch <- event: return nil // Successfully sent event to channel default: return fmt.Errorf("failed to log event: channel is full") } ======= // Get the caller information _, file, line, ok := runtime.Caller(5) if !ok { file = "???" line = 0 } event := NewExtendedEvent(record.Level.String(), record.Message, jsonData, file, line) for _, handler := range cl.handlers { if err := handler.Handle(ctx, event); err != nil { return err } } return nil >>>>>>> REPLACE ``` |
||
---|---|---|
tools | ||
.gitignore | ||
console_handler.go | ||
event.go | ||
go.mod | ||
go.sum | ||
handler.go | ||
json_handler.go | ||
Makefile | ||
README.md | ||
relp_handler.go | ||
simplelog_test.go | ||
simplelog.go | ||
TODO | ||
webhook_handler.go |
simplelog
simplelog is an opinionated logging package designed to facilitate easy and structured logging in Go applications with an absolute minimum of boilerplate.
The idea is that you can add a single import line which replaces the
stdlib log/slog
default handler, and solve the 90% case for logging.
Features
- if output is a tty, outputs pretty color logs
- if output is not a tty, outputs json
- supports delivering logs via tcp RELP (e.g. to remote rsyslog using imrelp)
- supports delivering each log message via a webhook
Installation
To use simplelog, first ensure your project is set up with Go modules:
go mod init your_project_name
Then, add SimpleLog to your project:
go get git.eeqj.de/sneak/go-simplelog
Usage
Below is an example of how to use SimpleLog in a Go application. This example is provided in the form of a main.go
file, which demonstrates logging at various levels using structured logging syntax.
package main
import (
"log/slog"
_ "git.eeqj.de/sneak/go-simplelog"
)
func main() {
// log structured data with slog as usual:
slog.Info("User login attempt", slog.String("user", "JohnDoe"), slog.Int("attempt", 3))
slog.Warn("Configuration mismatch", slog.String("expected", "config.json"), slog.String("found", "config.dev.json"))
slog.Error("Failed to save data", slog.String("reason", "permission denied"))
}