Skip to content

Commit

Permalink
fix(output): cache lipgloss renderers (#52)
Browse files Browse the repository at this point in the history
* fix(output): cache lipgloss renderers

Cache and reuse lipgloss renderers to avoid concurrently querying the
terminal for background colors. Lipgloss HasDarkBackground function
queries the terminal for the background color. Creating multiple logger
instances with the same output will query the output multiple times
causing Log to hange and/or freeze.

To solve this, we store and retrieve the Lipgloss renderer in a global
sync.Map for each output along with caching the background/foreground
colors of the underlying Termenv Output.

Fixes: #50

* Update logger.go

Co-authored-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>

---------

Co-authored-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
  • Loading branch information
aymanbagabas and caarlos0 committed Mar 22, 2023
1 parent c9ffb27 commit 6e534d0
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 3 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.17
require (
github.com/charmbracelet/lipgloss v0.7.1
github.com/go-logfmt/logfmt v0.6.0
github.com/muesli/termenv v0.15.1
github.com/stretchr/testify v1.8.2
)

Expand All @@ -15,7 +16,6 @@ require (
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
golang.org/x/sys v0.6.0 // indirect
Expand Down
9 changes: 8 additions & 1 deletion logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"sync/atomic"

"github.com/charmbracelet/lipgloss"
"github.com/muesli/termenv"
)

var (
Expand Down Expand Up @@ -252,7 +253,13 @@ func (l *Logger) SetOutput(w io.Writer) {
isDiscard = 1
}
atomic.StoreUint32(&l.isDiscard, isDiscard)
l.re = lipgloss.NewRenderer(w)
// Reuse cached renderers
if v, ok := registry.Load(w); ok {
l.re = v.(*lipgloss.Renderer)
} else {
l.re = lipgloss.NewRenderer(w, termenv.WithColorCache(true))
registry.Store(w, l.re)
}
}

// SetFormatter sets the formatter.
Expand Down
8 changes: 7 additions & 1 deletion pkg.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ import (
"time"
)

var defaultLogger = NewWithOptions(os.Stderr, Options{ReportTimestamp: true})
var (
// registry is a map of all registered lipgloss renderers.
registry = sync.Map{}

// defaultLogger is the default global logger instance.
defaultLogger = NewWithOptions(os.Stderr, Options{ReportTimestamp: true})
)

// Default returns the default logger. The default logger comes with timestamp enabled.
func Default() *Logger {
Expand Down

0 comments on commit 6e534d0

Please sign in to comment.