Skip to content

Commit

Permalink
fix log format
Browse files Browse the repository at this point in the history
  • Loading branch information
samber committed Mar 3, 2024
1 parent d829d80 commit e6c3fee
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 40 deletions.
23 changes: 11 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,23 +68,21 @@ type Option struct {

// optional: customize json payload builder
Converter Converter
// optional: custom marshaler
Marshaler func(v any) ([]byte, error)

// optional: see slog.HandlerOptions
AddSource bool
ReplaceAttr func(groups []string, a slog.Attr) slog.Attr
}
```

Attributes will be injected in log payload.
Attributes will be injected in log "extra".

Other global parameters:

```go
sloggraylog.SourceKey = "source"
sloggraylog.ContextKey = "extra"
sloggraylog.ErrorKeys = []string{"error", "err"}
sloggraylog.LogLevels = map[slog.Level]int32{...}
```

### Example
Expand All @@ -105,6 +103,8 @@ func main() {
log.Fatalf("gelf.NewWriter: %s", err)
}

gelfWriter.CompressionType = gelf.CompressNone // for debugging only

logger := slog.New(sloggraylog.Option{Level: slog.LevelDebug, Writer: gelfWriter}.NewGraylogHandler())
logger = logger.
With("environment", "dev").
Expand Down Expand Up @@ -135,14 +135,14 @@ Output:
```json
{
"timestamp":"2023-04-10T14:00:0.000000+00:00",
"level":"ERROR",
"level":3,
"message":"caramba!",
"error":{
"error":"could not count users",
"kind":"*errors.errorString",
"stack":null
},
"extra":{
"error":{
"error":"could not count users",
"kind":"*errors.errorString",
"stack":null
},
"environment":"dev",
"release":"v1.0.0",
"category":"sql",
Expand All @@ -154,9 +154,8 @@ Output:

{
"timestamp":"2023-04-10T14:00:0.000000+00:00",
"level":"INFO",
"level":6,
"message":"user registration",
"error":null,
"extra":{
"environment":"dev",
"release":"v1.0.0",
Expand Down
22 changes: 5 additions & 17 deletions converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ import (
)

var SourceKey = "source"
var ContextKey = "extra"
var ErrorKeys = []string{"error", "err"}

type Converter func(addSource bool, replaceAttr func(groups []string, a slog.Attr) slog.Attr, loggerAttr []slog.Attr, groups []string, record *slog.Record) map[string]any
type Converter func(addSource bool, replaceAttr func(groups []string, a slog.Attr) slog.Attr, loggerAttr []slog.Attr, groups []string, record *slog.Record) (extra map[string]any)

func DefaultConverter(addSource bool, replaceAttr func(groups []string, a slog.Attr) slog.Attr, loggerAttr []slog.Attr, groups []string, record *slog.Record) map[string]any {
func DefaultConverter(addSource bool, replaceAttr func(groups []string, a slog.Attr) slog.Attr, loggerAttr []slog.Attr, groups []string, record *slog.Record) (extra map[string]any) {
// aggregate all attributes
attrs := slogcommon.AppendRecordAttrsToAttrs(loggerAttr, groups, record)

Expand All @@ -23,27 +22,16 @@ func DefaultConverter(addSource bool, replaceAttr func(groups []string, a slog.A
attrs = slogcommon.ReplaceAttrs(replaceAttr, []string{}, attrs...)

// handler formatter
log := map[string]any{
"logger.name": name,
"logger.version": version,
"timestamp": record.Time.UTC(),
"level": record.Level.String(),
"message": record.Message,
}

extra := slogcommon.AttrsToMap(attrs...)
extra = slogcommon.AttrsToMap(attrs...)

for _, errorKey := range ErrorKeys {
if v, ok := extra[errorKey]; ok {
if err, ok := v.(error); ok {
log[errorKey] = slogcommon.FormatError(err)
delete(extra, errorKey)
extra[errorKey] = slogcommon.FormatError(err)
break
}
}
}

log[ContextKey] = extra

return log
return extra
}
4 changes: 4 additions & 0 deletions example/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ func main() {
log.Fatalf("gelf.NewWriter: %s", err)
}

gelfWriter.CompressionType = gelf.CompressNone // for debugging only

logger := slog.New(sloggraylog.Option{Level: slog.LevelDebug, Writer: gelfWriter}.NewGraylogHandler())
logger = logger.With("release", "v1.0.0")

Expand All @@ -33,4 +35,6 @@ func main() {
With("environment", "dev").
With("error", fmt.Errorf("an error")).
Error("A message")

time.Sleep(1 * time.Second)
}
9 changes: 9 additions & 0 deletions graylog.go
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
package sloggraylog

import "log/slog"

var LogLevels = map[slog.Level]int32{
slog.LevelDebug: 7,
slog.LevelInfo: 6,
slog.LevelWarn: 4,
slog.LevelError: 3,
}
43 changes: 32 additions & 11 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package sloggraylog

import (
"context"
"encoding/json"
"fmt"
"os"
"strings"

"log/slog"

Expand All @@ -19,12 +21,13 @@ type Option struct {

// optional: customize json payload builder
Converter Converter
// optional: custom marshaler
Marshaler func(v any) ([]byte, error)

// optional: see slog.HandlerOptions
AddSource bool
ReplaceAttr func(groups []string, a slog.Attr) slog.Attr

// internal
hostname string
}

func (o Option) NewGraylogHandler() slog.Handler {
Expand All @@ -35,13 +38,16 @@ func (o Option) NewGraylogHandler() slog.Handler {
if o.Writer == nil {
panic("missing graylog connections")
}
if o.Writer.Facility == "" {
o.Writer.Facility = fmt.Sprintf("%s/%s", name, version)
}

if o.Converter == nil {
o.Converter = DefaultConverter
}

if o.Marshaler == nil {
o.Marshaler = json.Marshal
if hostname, err := os.Hostname(); err == nil {
o.hostname = hostname
}

return &GraylogHandler{
Expand All @@ -64,15 +70,21 @@ func (h *GraylogHandler) Enabled(_ context.Context, level slog.Level) bool {
}

func (h *GraylogHandler) Handle(ctx context.Context, record slog.Record) error {
message := h.option.Converter(h.option.AddSource, h.option.ReplaceAttr, h.attrs, h.groups, &record)

bytes, err := h.option.Marshaler(message)
if err != nil {
return err
extra := h.option.Converter(h.option.AddSource, h.option.ReplaceAttr, h.attrs, h.groups, &record)

msg := &gelf.Message{
Version: "1.1",
Host: h.option.hostname,
Short: short(&record),
Full: strings.TrimSpace(record.Message),
TimeUnix: float64(record.Time.Unix()),
Level: LogLevels[record.Level],
Facility: h.option.Writer.Facility,
Extra: extra,
}

go func() {
_, _ = h.option.Writer.Write(append(bytes, byte('\n')))
_ = h.option.Writer.WriteMessage(msg)
}()

return nil
Expand All @@ -93,3 +105,12 @@ func (h *GraylogHandler) WithGroup(name string) slog.Handler {
groups: append(h.groups, name),
}
}

func short(record *slog.Record) string {
msg := strings.TrimSpace(record.Message)
if i := strings.IndexRune(msg, '\n'); i > 0 {
return msg[:i]
}

return msg
}

0 comments on commit e6c3fee

Please sign in to comment.