Skip to content
This repository has been archived by the owner on Dec 30, 2024. It is now read-only.

Commit

Permalink
use zerolog.LevelWriter interface to skip parsing log if level should…
Browse files Browse the repository at this point in the history
… not be logged
  • Loading branch information
krombel committed Jun 21, 2023
1 parent 22731d7 commit 43ad775
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 23 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
```go
import (
"errors"
"io"
stdlog "log"
"os"

Expand All @@ -22,7 +21,8 @@ func main() {

defer w.Close()

logger := zerolog.New(io.MultiWriter(w, os.Stdout)).With().Timestamp().Logger()
multi := zerolog.MultiLevelWriter(os.Stdout, w)
logger := zerolog.New(multi).With().Timestamp().Logger()

logger.Error().Err(errors.New("dial timeout")).Msg("test message")
}
Expand Down
66 changes: 45 additions & 21 deletions writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,22 @@ type Writer struct {
}

// Write handles zerolog's json and sends events to sentry.
func (w *Writer) Write(data []byte) (int, error) {
func (w *Writer) Write(data []byte) (n int, err error) {
n = len(data)

lvl, err := w.parseLogLevel(data)
if err != nil {
return n, nil
}

_, enabled := w.levels[lvl]
if !enabled {
return
}

event, ok := w.parseLogEvent(data)
event.Level = levelsMapping[lvl]

if ok {
w.hub.CaptureEvent(event)
// should flush before os.Exit
Expand All @@ -42,7 +56,27 @@ func (w *Writer) Write(data []byte) (int, error) {
}
}

return len(data), nil
return
}

// implements zerolog.LevelWriter
func (w *Writer) WriteLevel(level zerolog.Level, p []byte) (n int, err error) {
n = len(p)
if _, enabled := w.levels[level]; !enabled {
return
}

event, ok := w.parseLogEvent(p)
event.Level = levelsMapping[level]

if ok {
w.hub.CaptureEvent(event)
// should flush before os.Exit
if event.Level == sentry.LevelFatal {
w.hub.Flush(w.flushTimeout)
}
}
return
}

// Close forces client to flush all pending events.
Expand All @@ -52,37 +86,27 @@ func (w *Writer) Close() error {
return nil
}

func (w *Writer) parseLogEvent(data []byte) (*sentry.Event, bool) {
const logger = "zerolog"

// parses the log level from the encoded log
func (w *Writer) parseLogLevel(data []byte) (zerolog.Level, error) {
lvlStr, err := jsonparser.GetUnsafeString(data, zerolog.LevelFieldName)
if err != nil {
return nil, false
}

lvl, err := zerolog.ParseLevel(lvlStr)
if err != nil {
return nil, false
return zerolog.Disabled, nil
}

_, enabled := w.levels[lvl]
if !enabled {
return nil, false
}
return zerolog.ParseLevel(lvlStr)
}

sentryLvl, ok := levelsMapping[lvl]
if !ok {
return nil, false
}
// parses the event except the log level
func (w *Writer) parseLogEvent(data []byte) (*sentry.Event, bool) {
const logger = "zerolog"

event := sentry.Event{
Timestamp: now(),
Level: sentryLvl,
Logger: logger,
Extra: map[string]interface{}{},
}

err = jsonparser.ObjectEach(data, func(key, value []byte, vt jsonparser.ValueType, offset int) error {
err := jsonparser.ObjectEach(data, func(key, value []byte, vt jsonparser.ValueType, offset int) error {
switch string(key) {
case zerolog.MessageFieldName:
event.Message = bytesToStrUnsafe(value)
Expand Down
36 changes: 36 additions & 0 deletions writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ func TestParseLogEvent(t *testing.T) {

ev, ok := w.parseLogEvent(logEventJSON)
require.True(t, ok)
zLevel, err := w.parseLogLevel(logEventJSON)
assert.Nil(t, err)
ev.Level = levelsMapping[zLevel]

assert.Equal(t, ts, ev.Timestamp)
assert.Equal(t, sentry.LevelError, ev.Level)
Expand Down Expand Up @@ -56,3 +59,36 @@ func BenchmarkParseLogEvent_DisabledLevel(b *testing.B) {
w.parseLogEvent(logEventJSON)
}
}

func BenchmarkWriteLogEvent(b *testing.B) {
w, err := New("")
if err != nil {
b.Errorf("failed to create writer: %v", err)
}

for i := 0; i < b.N; i++ {
_, _ = w.Write(logEventJSON)
}
}

func BenchmarkWriteLogLevelEvent(b *testing.B) {
w, err := New("")
if err != nil {
b.Errorf("failed to create writer: %v", err)
}

for i := 0; i < b.N; i++ {
_, _ = w.WriteLevel(zerolog.ErrorLevel, logEventJSON)
}
}

func BenchmarkWriteLogLevelEvent_DisabledLevel(b *testing.B) {
w, err := New("", WithLevels(zerolog.FatalLevel))
if err != nil {
b.Errorf("failed to create writer: %v", err)
}

for i := 0; i < b.N; i++ {
_, _ = w.WriteLevel(zerolog.ErrorLevel, logEventJSON)
}
}

0 comments on commit 43ad775

Please sign in to comment.