Skip to content

v1.10.0

Latest

Choose a tag to compare

@thaJeztah thaJeztah released this 13 Aug 15:34
v1.10.0
457e372

Logrus v1.10.0

This release focuses on substantial performance improvements, concurrency correctness, and better interoperability with modern Go logging APIs.

🚀 Performance

Major improvements across TextFormatter, entry handling, and common logger paths:

  • ~17% lower geomean runtime across the benchmark suite
  • ~27% higher geomean formatter throughput
  • Common enabled logging paths are ~30–44% faster
  • WithError is ~40% faster
  • Chained fields are ~46% faster
  • TextFormatter paths are up to ~40% faster
  • Allocation counts are reduced by ~25–74% across measured TextFormatter cases, with the largest reductions in colored output

The improvements also show up in complete logger paths:

  • Logger + TextFormatter is ~31% faster, with ~24% fewer allocations
  • Logger + JSONFormatter is ~21% faster, with ~10% fewer allocations

JSONFormatter itself remains largely unchanged in runtime performance, with small allocation reductions.

🔄 log/slog interoperability

v1.10 adds bidirectional interoperability between Logrus and Go's log/slog:

  • A Logrus slog hook can forward existing Logrus entries to an slog logger.
  • hooks/slog.NewHandler implements slog.Handler, allowing log/slog records to use an existing Logrus logger and its hooks, formatter, and output.
  • The handler preserves levels, fields, groups, context, record timestamps, and optionally caller information.
  • Caller reporting is configured per handler, without requiring Logrus's logger-wide ReportCaller option.
  • Custom slog levels can be mapped to Logrus levels.
  • The hook and handler can be combined, providing a practical path for incrementally migrating from Logrus to log/slog without requiring an all-at-once transition.

This allows applications to migrate their logging API and logging backend independently: existing Logrus call sites can start using an slog backend, while new slog code can continue using an established Logrus setup.

🔒 Concurrency & Correctness

  • Fix reentrant logging deadlocks, including logging from within MarshalJSON or formatter code.
  • Fix generic Log, Logf, Logln, and LogFn methods unexpectedly panicking when called with PanicLevel, contrary to their documented behavior.
  • Eliminate race conditions in entry and formatter paths.
  • Improve locking boundaries around formatters and hooks.

➕ Added

  • TextFormatter now automatically enables colors on Windows terminals with ANSI support, matching behavior on other platforms.
  • Entry.Caller can now be set explicitly and is preserved across derived entries. When caller reporting is enabled, Logrus only detects and populates caller information when none was provided, allowing custom caller detection and wrapper-aware logging without adding additional caller configuration APIs.
  • Add minimal, composable logging interfaces for each log level, allowing consumers to depend on narrower interfaces and making logging implementations easier to substitute or adapt.
  • Expand CI verification to include TinyGo and every cross-compile target reported by go tool dist list, improving coverage across alternative toolchains and platforms.

⚠️ Behavioral Changes

  • Minimum supported Go version is now 1.23.
  • TextFormatter now renders []byte as raw/quoted strings instead of numeric slices.
    If you relied on the previous slice-of-ints output, convert explicitly before logging.
  • TextFormatter now uses dim cyan for debug output and dim white for trace output in colorized TTY output.
  • Entry.HasCaller is now deprecated in favor of checking Entry.Caller directly. A //go:fix inline directive was added so existing uses can be updated automatically.
  • MutexWrap, which was unintentionally exposed as public API, is deprecated. It remains available as an alias for compatibility but should not be used directly.

v1.10 is primarily a performance, correctness, and interoperability release with no intentional breaking public API changes.

Benchmarks (sampled at 457e372)
goos: darwin
goarch: arm64
pkg: github.com/sirupsen/logrus/benches
cpu: Apple M3 Pro
                                     │  v1.9.4.txt   │             v1.10.0.txt              │
                                     │    sec/op     │    sec/op     vs base                │
Entry_WithError                         228.8n ±  4%   137.4n ±  5%  -39.95% (p=0.000 n=10)
Entry_WithField_Chain                  1346.5n ±  2%   733.5n ±  3%  -45.53% (p=0.000 n=10)
Entry_WithFields/valid_fields_only      236.2n ±  6%   255.4n ±  1%   +8.11% (p=0.001 n=10)
Entry_WithFields/contains_func          293.1n ±  3%   285.1n ±  3%   -2.76% (p=0.043 n=10)
Entry_WithFields/contains_func_ptr      296.5n ±  3%   300.1n ±  5%        ~ (p=0.529 n=10)
Entry_WithFields/mixed_valid_invalid    339.7n ±  4%   336.7n ±  2%        ~ (p=0.315 n=10)
Entry_WithFields/larger_map             635.9n ±  4%   693.8n ±  2%   +9.11% (p=0.000 n=10)
Entry_ReportCaller_NoCaller             933.4n ±  3%   924.0n ±  2%        ~ (p=0.105 n=10)
Entry_ReportCaller_WithCaller           2.693µ ±  2%   3.050µ ±  3%  +13.28% (p=0.000 n=10)
Entry_ReportCaller_NoCaller_Depth4      914.3n ±  2%   905.5n ±  3%        ~ (p=0.481 n=10)
Entry_ReportCaller_WithCaller_Depth4    2.736µ ±  8%   3.048µ ±  5%  +11.36% (p=0.000 n=10)
ZeroTextFormatter                       457.6n ±  1%   369.3n ±  2%  -19.31% (p=0.000 n=10)
OneStringTextFormatter                  637.0n ±  1%   549.4n ±  2%  -13.75% (p=0.000 n=10)
OneNumericTextFormatter                 682.7n ±  1%   550.2n ±  1%  -19.42% (p=0.000 n=10)
OneBoolTextFormatter                    669.7n ±  1%   550.0n ±  1%  -17.87% (p=0.000 n=10)
NumericTextFormatter                    1.685µ ±  3%   1.261µ ±  2%  -25.17% (p=0.000 n=10)
BoolTextFormatter                       1.450µ ±  1%   1.082µ ±  3%  -25.39% (p=0.000 n=10)
StringerTextFormatter                   2.066µ ±  1%   1.323µ ±  1%  -35.95% (p=0.000 n=10)
ErrorTextFormatter                      924.7n ±  5%   686.7n ±  1%  -25.74% (p=0.000 n=10)
SmallTextFormatter                      944.4n ±  1%   862.6n ±  1%   -8.66% (p=0.000 n=10)
LargeTextFormatter                      5.527µ ±  5%   4.750µ ±  2%  -14.07% (p=0.000 n=10)
SmallColoredTextFormatter              1337.0n ±  3%   838.6n ±  1%  -37.28% (p=0.000 n=10)
LargeColoredTextFormatter               7.955µ ±  5%   4.749µ ±  3%  -40.30% (p=0.000 n=10)
SmallJSONFormatter                      1.627µ ±  1%   1.637µ ±  6%        ~ (p=0.670 n=10)
LargeJSONFormatter                      8.335µ ±  3%   8.172µ ±  1%   -1.96% (p=0.000 n=10)
DummyLogger                             1.843µ ±  3%   1.551µ ±  2%  -15.82% (p=0.000 n=10)
DummyLoggerNoLock                       1.840µ ±  3%   1.558µ ±  3%  -15.30% (p=0.000 n=10)
LoggerLog/disabled_level                1.248n ± 11%   1.192n ± 11%   -4.49% (p=0.011 n=10)
LoggerLog/enabled_log                   223.9n ±  3%   157.7n ±  5%  -29.57% (p=0.000 n=10)
LoggerLog/enabled_logln                 284.2n ±  1%   158.9n ±  2%  -44.09% (p=0.000 n=10)
LoggerJSONFormatter                     2.177µ ±  1%   1.712µ ±  1%  -21.34% (p=0.000 n=10)
LoggerTextFormatter                     1.860µ ±  5%   1.282µ ±  3%  -31.05% (p=0.000 n=10)
geomean                                 843.9n         698.9n        -17.18%

                                     │   v1.9.4.txt   │              v1.10.0.txt               │
                                     │      B/op      │     B/op      vs base                  │
Entry_WithError                          448.0 ± 0%       448.0 ± 0%        ~ (p=1.000 n=10) ¹
Entry_WithField_Chain                  2.188Ki ± 0%     2.188Ki ± 0%        ~ (p=1.000 n=10) ¹
Entry_WithFields/valid_fields_only       448.0 ± 0%       448.0 ± 0%        ~ (p=1.000 n=10) ¹
Entry_WithFields/contains_func           488.0 ± 0%       488.0 ± 0%        ~ (p=1.000 n=10) ¹
Entry_WithFields/contains_func_ptr       488.0 ± 0%       488.0 ± 0%        ~ (p=1.000 n=10) ¹
Entry_WithFields/mixed_valid_invalid     488.0 ± 0%       488.0 ± 0%        ~ (p=1.000 n=10) ¹
Entry_WithFields/larger_map            1.320Ki ± 0%     1.320Ki ± 0%        ~ (p=1.000 n=10) ¹
Entry_ReportCaller_NoCaller              821.0 ± 0%       800.0 ± 0%   -2.56% (p=0.000 n=10)
Entry_ReportCaller_WithCaller          1.614Ki ± 0%     1.581Ki ± 0%   -2.06% (p=0.000 n=10)
Entry_ReportCaller_NoCaller_Depth4       821.0 ± 0%       800.0 ± 0%   -2.56% (p=0.000 n=10)
Entry_ReportCaller_WithCaller_Depth4   1.614Ki ± 0%     1.581Ki ± 0%   -2.06% (p=0.000 n=10)
ZeroTextFormatter                        272.0 ± 0%       232.0 ± 0%  -14.71% (p=0.000 n=10)
OneStringTextFormatter                   304.0 ± 0%       264.0 ± 0%  -13.16% (p=0.000 n=10)
OneNumericTextFormatter                  308.0 ± 0%       264.0 ± 0%  -14.29% (p=0.000 n=10)
OneBoolTextFormatter                     308.0 ± 0%       264.0 ± 0%  -14.29% (p=0.000 n=10)
NumericTextFormatter                     920.0 ± 0%       808.0 ± 0%  -12.17% (p=0.000 n=10)
BoolTextFormatter                        626.0 ± 0%       552.0 ± 0%  -11.82% (p=0.000 n=10)
StringerTextFormatter                    968.0 ± 0%       808.0 ± 0%  -16.53% (p=0.000 n=10)
ErrorTextFormatter                       472.0 ± 0%       424.0 ± 0%  -10.17% (p=0.000 n=10)
SmallTextFormatter                       528.0 ± 0%       488.0 ± 0%   -7.58% (p=0.000 n=10)
LargeTextFormatter                     3.773Ki ± 0%     3.156Ki ± 0%  -16.36% (p=0.000 n=10)
SmallColoredTextFormatter                600.0 ± 0%       392.0 ± 0%  -34.67% (p=0.000 n=10)
LargeColoredTextFormatter              4.406Ki ± 0%     2.859Ki ± 0%  -35.11% (p=0.000 n=10)
SmallJSONFormatter                     1.078Ki ± 0%     1.070Ki ± 0%   -0.72% (p=0.000 n=10)
LargeJSONFormatter                     5.086Ki ± 0%     5.078Ki ± 0%   -0.15% (p=0.000 n=10)
DummyLogger                              748.0 ± 0%       704.0 ± 0%   -5.88% (p=0.000 n=10)
DummyLoggerNoLock                        748.0 ± 0%       704.0 ± 0%   -5.88% (p=0.000 n=10)
LoggerLog/disabled_level                 0.000 ± 0%       0.000 ± 0%        ~ (p=1.000 n=10) ¹
LoggerLog/enabled_log                    212.0 ± 0%       208.0 ± 0%   -1.89% (p=0.000 n=10)
LoggerLog/enabled_logln                  240.0 ± 0%       208.0 ± 0%  -13.33% (p=0.000 n=10)
LoggerJSONFormatter                    2.156Ki ± 0%     2.125Ki ± 0%   -1.45% (p=0.000 n=10)
LoggerTextFormatter                    1.625Ki ± 0%     1.547Ki ± 0%   -4.81% (p=0.000 n=10)
geomean                                             ²                  -8.14%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                                     │  v1.9.4.txt   │             v1.10.0.txt              │
                                     │   allocs/op   │ allocs/op   vs base                  │
Entry_WithError                         3.000 ± 0%     3.000 ± 0%        ~ (p=1.000 n=10) ¹
Entry_WithField_Chain                   15.00 ± 0%     15.00 ± 0%        ~ (p=1.000 n=10) ¹
Entry_WithFields/valid_fields_only      3.000 ± 0%     3.000 ± 0%        ~ (p=1.000 n=10) ¹
Entry_WithFields/contains_func          5.000 ± 0%     5.000 ± 0%        ~ (p=1.000 n=10) ¹
Entry_WithFields/contains_func_ptr      5.000 ± 0%     5.000 ± 0%        ~ (p=1.000 n=10) ¹
Entry_WithFields/mixed_valid_invalid    5.000 ± 0%     5.000 ± 0%        ~ (p=1.000 n=10) ¹
Entry_WithFields/larger_map             5.000 ± 0%     5.000 ± 0%        ~ (p=1.000 n=10) ¹
Entry_ReportCaller_NoCaller             18.00 ± 0%     15.00 ± 0%  -16.67% (p=0.000 n=10)
Entry_ReportCaller_WithCaller           29.00 ± 0%     26.00 ± 0%  -10.34% (p=0.000 n=10)
Entry_ReportCaller_NoCaller_Depth4      18.00 ± 0%     15.00 ± 0%  -16.67% (p=0.000 n=10)
Entry_ReportCaller_WithCaller_Depth4    29.00 ± 0%     26.00 ± 0%  -10.34% (p=0.000 n=10)
ZeroTextFormatter                      10.000 ± 0%     7.000 ± 0%  -30.00% (p=0.000 n=10)
OneStringTextFormatter                 11.000 ± 0%     8.000 ± 0%  -27.27% (p=0.000 n=10)
OneNumericTextFormatter                12.000 ± 0%     8.000 ± 0%  -33.33% (p=0.000 n=10)
OneBoolTextFormatter                   12.000 ± 0%     8.000 ± 0%  -33.33% (p=0.000 n=10)
NumericTextFormatter                    19.00 ± 0%     10.00 ± 0%  -47.37% (p=0.000 n=10)
BoolTextFormatter                      18.000 ± 0%     9.000 ± 0%  -50.00% (p=0.000 n=10)
StringerTextFormatter                   22.00 ± 0%     10.00 ± 0%  -54.55% (p=0.000 n=10)
ErrorTextFormatter                     14.000 ± 0%     9.000 ± 0%  -35.71% (p=0.000 n=10)
SmallTextFormatter                     12.000 ± 0%     9.000 ± 0%  -25.00% (p=0.000 n=10)
LargeTextFormatter                      19.00 ± 0%     14.00 ± 0%  -26.32% (p=0.000 n=10)
SmallColoredTextFormatter              15.000 ± 0%     7.000 ± 0%  -53.33% (p=0.000 n=10)
LargeColoredTextFormatter               46.00 ± 0%     12.00 ± 0%  -73.91% (p=0.000 n=10)
SmallJSONFormatter                      25.00 ± 0%     23.00 ± 0%   -8.00% (p=0.000 n=10)
LargeJSONFormatter                      75.00 ± 0%     73.00 ± 0%   -2.67% (p=0.000 n=10)
DummyLogger                            13.000 ± 0%     9.000 ± 0%  -30.77% (p=0.000 n=10)
DummyLoggerNoLock                      13.000 ± 0%     9.000 ± 0%  -30.77% (p=0.000 n=10)
LoggerLog/disabled_level                0.000 ± 0%     0.000 ± 0%        ~ (p=1.000 n=10) ¹
LoggerLog/enabled_log                   4.000 ± 0%     3.000 ± 0%  -25.00% (p=0.000 n=10)
LoggerLog/enabled_logln                 6.000 ± 0%     3.000 ± 0%  -50.00% (p=0.000 n=10)
LoggerJSONFormatter                     30.00 ± 0%     27.00 ± 0%  -10.00% (p=0.000 n=10)
LoggerTextFormatter                     21.00 ± 0%     16.00 ± 0%  -23.81% (p=0.000 n=10)
geomean                                            ²               -25.77%                ²
¹ all samples are equal
² summaries must be >0 to compute geomean

                          │  v1.9.4.txt  │              v1.10.0.txt              │
                          │     B/s      │      B/s       vs base                │
ZeroTextFormatter           106.3Mi ± 1%    131.7Mi ± 2%  +23.90% (p=0.000 n=10)
OneStringTextFormatter      88.34Mi ± 1%   102.42Mi ± 2%  +15.95% (p=0.000 n=10)
OneNumericTextFormatter     78.23Mi ± 1%    97.08Mi ± 1%  +24.09% (p=0.000 n=10)
OneBoolTextFormatter        82.59Mi ± 1%   100.57Mi ± 1%  +21.77% (p=0.000 n=10)
NumericTextFormatter        74.74Mi ± 3%    99.85Mi ± 2%  +33.60% (p=0.000 n=10)
BoolTextFormatter           65.15Mi ± 1%    87.32Mi ± 3%  +34.04% (p=0.000 n=10)
StringerTextFormatter       64.64Mi ± 1%   100.90Mi ± 1%  +56.10% (p=0.000 n=10)
ErrorTextFormatter          69.10Mi ± 5%    93.05Mi ± 1%  +34.66% (p=0.000 n=10)
SmallTextFormatter          86.85Mi ± 1%    95.08Mi ± 1%   +9.48% (p=0.000 n=10)
LargeTextFormatter          49.35Mi ± 5%    57.43Mi ± 2%  +16.38% (p=0.000 n=10)
SmallColoredTextFormatter   102.7Mi ± 3%    163.8Mi ± 1%  +59.42% (p=0.000 n=10)
LargeColoredTextFormatter   67.14Mi ± 5%   112.45Mi ± 3%  +67.48% (p=0.000 n=10)
SmallJSONFormatter          66.84Mi ± 1%    66.44Mi ± 6%        ~ (p=0.684 n=10)
LargeJSONFormatter          46.91Mi ± 3%    47.85Mi ± 1%   +2.00% (p=0.000 n=10)
geomean                     73.01Mi         92.67Mi       +26.93%

Full Changelog: v1.9.4...v1.10.0