Skip to content

Commit

Permalink
Feat: async log writing
Browse files Browse the repository at this point in the history
  • Loading branch information
hmoog committed Mar 21, 2024
1 parent 9f498c0 commit 37ee252
Showing 1 changed file with 28 additions and 23 deletions.
51 changes: 28 additions & 23 deletions log/text_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import (
"sync/atomic"

"github.com/iotaledger/hive.go/ierrors"
"github.com/iotaledger/hive.go/runtime/workerpool"
)

// NewTextHandler creates a new handler that writes human-readable log records to the given output.
func NewTextHandler(options *Options) slog.Handler {
t := &textHandler{
output: options.Output,
timeFormat: options.TimeFormat,
ioWorker: workerpool.New("log.TextHandler", workerpool.WithWorkerCount(1)),
}

formatString := "%s\t%-7s\t%s\t%s %s\n"
Expand All @@ -33,6 +35,7 @@ type textHandler struct {
maxNamespaceLength atomic.Int64
formatString atomic.Pointer[string]
updateMutex sync.Mutex
ioWorker *workerpool.WorkerPool
}

// Enabled returns true for all levels as we handle the cutoff ourselves using reactive variables and the ability to
Expand All @@ -43,35 +46,37 @@ func (t *textHandler) Enabled(_ context.Context, _ slog.Level) bool {

// Handle writes the log record to the output.
func (t *textHandler) Handle(_ context.Context, r slog.Record) error {
var namespace string
fieldsBuffer := new(bytes.Buffer)
t.ioWorker.Submit(func() {
var namespace string
fieldsBuffer := new(bytes.Buffer)

fieldCount := r.NumAttrs() - 1
if fieldCount > 0 {
fieldsBuffer.WriteString("(")
}
fieldCount := r.NumAttrs() - 1
if fieldCount > 0 {
fieldsBuffer.WriteString("(")
}

r.Attrs(func(attr slog.Attr) bool {
if attr.Key == namespaceKey {
//nolint:forcetypeassert // false positive, we know that the value is a string for a namespace key
namespace = attr.Value.Any().(string)
} else {
fieldsBuffer.WriteString(attr.String())
fieldsBuffer.WriteString(" ")
r.Attrs(func(attr slog.Attr) bool {
if attr.Key == namespaceKey {
//nolint:forcetypeassert // false positive, we know that the value is a string for a namespace key
namespace = attr.Value.Any().(string)
} else {
fieldsBuffer.WriteString(attr.String())
fieldsBuffer.WriteString(" ")
}

return true
})

if fieldCount > 0 {
fieldsBuffer.Truncate(fieldsBuffer.Len() - 1)
fieldsBuffer.WriteString(")")
}

return true
if _, err := fmt.Fprintf(t.output, t.buildFormatString(namespace), r.Time.Format(t.timeFormat), LevelName(r.Level), namespace, r.Message, fieldsBuffer.String()); err != nil {
panic(ierrors.Wrap(err, "writing log record failed"))
}
})

if fieldCount > 0 {
fieldsBuffer.Truncate(fieldsBuffer.Len() - 1)
fieldsBuffer.WriteString(")")
}

if _, err := fmt.Fprintf(t.output, t.buildFormatString(namespace), r.Time.Format(t.timeFormat), LevelName(r.Level), namespace, r.Message, fieldsBuffer.String()); err != nil {
return ierrors.Wrap(err, "writing log record failed")
}

return nil
}

Expand Down

0 comments on commit 37ee252

Please sign in to comment.