Skip to content
CAI
Software that uses CAICheck a score

typelevel/log4cats

60.1

Adequate · 20 September 2026

3.7k

lines of production code

Scala

primary language

1

measurement over time

CAI band scale
CAI lens gauges

What this system is

This system is a functional logging library for Scala that provides a unified, effect-safe API for structured logging across JVM, JavaScript, and Native platforms. It integrates with SLF4J for production use while offering specialized implementations for testing, deferred buffering, and browser console output. The library emphasizes non-blocking operations, lazy evaluation, and compile-time logger name derivation to ensure robustness and ease of use within effectful applications.

How it got here

2018–2021 — Structured logging and cross-platform modernization

16 changes.

The project underwent a major architectural overhaul, migrating to sbt-typelevel and supporting Scala 2.12, 2.13, and 3 across JVM, JS, and Native platforms. Core logging capabilities were significantly expanded with the introduction of structured logging, message pagination, and new deferred and writer-based logger implementations. Integration with SLF4J was refactored to ensure non-blocking MDC handling and macro-based logger creation for both Scala 2 and 3.

2022–2024 — Scala 2 compatibility and JS console support

5 changes.

This period focused on enhancing platform support by introducing a Scala 2 macro for automatic logger name derivation and adding a new js-console module for browser logging. The work also involved refactoring the NoOpLogger into the core module and expanding test coverage for logger name resolution and deferred logging capabilities.

Features

Add Scala 2 macro for automatic logger name derivation

Introduced a Scala 2-specific compatibility layer that automatically derives the logger name from the enclosing class or module at compile time. This is implemented via a new \LoggerNameCompat\ trait and the \LoggerNameMacro\ implementation, which resolves the enclosing symbol and generates the appropriate \LoggerName\ instance, handling edge cases such as package objects, inner classes, and higher-kinded types to ensure correct naming behavior for Scala 2 users.

core/shared/src/main/scala-2, core/shared/src/main/scala-3 · high confidence

Add Scala.js console logging support

Introduces a new \js-console\ module that enables logging to the browser's Web Console in Scala.js applications. This includes a \ConsoleLogger\ implementation that maps log levels to browser console methods (info, warn, error, debug), a \ConsoleLoggerFactory\ for creating instances, and internal facade classes (\Console\, \ConsoleF\) to interact with the JavaScript environment via \cats-effect-kernel\.

js-console · high confidence

Add string interpolation syntax for Logger methods

Users can now use string interpolation syntax (e.g., logger"message") to log messages at various levels (error, warn, info, debug, trace) via the new LoggerInterpolator implicit class in the syntax package.

core/shared/src/main/scala/org/typelevel/log4cats/syntax · high confidence

Added Scala 2 compatibility layer for SLF4J logger creation

Introduced a new compatibility package for Scala 2 that provides macro-based implementations for creating SLF4J loggers. This includes \Slf4jLoggerCompat\ and \GetLoggerMacros\, which enable the \getLogger\ and \create\ methods to function correctly on Scala 2 by generating the appropriate logger instances via compile-time macros, ensuring binary compatibility and correct behavior for users on this platform.

slf4j/src/main/scala-2 · high confidence

New deferred and Writer-based logger implementations in log4cats extras

The \org.typelevel.log4cats.extras\ package now includes \DeferredLogger\, \DeferredStructuredLogger\, \DeferredSelfAwareStructuredLogger\, and \DeferredLoggerFactory\, which buffer log messages in memory and only emit them when explicitly triggered or when a resource scope fails or is cancelled—making them safer for scenarios like failure-only logging. Additionally, \WriterLogger\, \WriterStructuredLogger\, \WriterTLogger\, and \WriterTStructuredLogger\ provide logger implementations backed by \cats.data.Writer\ and \WriterT\, allowing logs to be accumulated alongside computation results, with a README documenting important caveats about their lifecycle and error-handling behavior.

core/shared/src/main/scala/org/typelevel/log4cats/extras · high confidence

New testing and extras utilities for structured logging

This change introduces new utilities in the \testing\ and \extras\ modules to support structured logging and easier testing. It adds \LogLevel\, \LogMessage\, and \StructuredLogMessage\ types to the \extras\ package, providing a standardized way to represent log levels and messages, including context maps for structured logging. Additionally, it provides \TestingLogger\, \StructuredTestingLogger\, and \TestingLoggerFactory\ in the \testing\ module, allowing developers to capture and inspect log messages during tests, with support for both standard and structured logging contexts.

repository · high confidence

Removals

Removal of placeholder Main entry point

The default application entry point (Main.scala) has been removed from the project. This eliminates the initial placeholder code that simply printed a startup message, indicating the project is moving past its initial scaffolding phase.

src/main · high confidence

Behavioural changes

Introduce structured logging traits and paging support

The core logging API has been refactored to support structured logging and message pagination. New traits—MessageLogger, ErrorLogger, StructuredLogger, SelfAwareLogger, and SelfAwareStructuredLogger—provide granular control over log levels and context injection via methods like addContext and withModifiedString. The LoggerFactory now exposes mapK, addContext, and withModifiedString to transform logger instances. Additionally, PagingSelfAwareStructuredLogger allows wrapping loggers to split large messages into paginated chunks, preventing truncation by underlying logging providers, with the previous withPaging method deprecated in favor of paged.

core/shared/src/main/scala/org/typelevel/log4cats · high confidence

NoOpLogger implementation moved to core module

The \NoOpLogger\ and \NoOpFactory\ implementations have been relocated to the \core/shared\ module. This change reorganizes the internal structure of the library, making the no-operation logger components part of the core shared codebase rather than a separate or peripheral location, without altering their functionality.

core/shared/src/main/scala/org/typelevel/log4cats/noop · high confidence

Ported SLF4J logger creation macros to Scala 3

The SLF4J logger creation logic has been migrated to Scala 3 using the new \scala.quoted\ macro system. This change introduces \Slf4jLoggerCompat\ and \GetLoggerMacros\ to handle the generation of \SelfAwareStructuredLogger\ instances, ensuring binary compatibility while updating the underlying implementation to use Scala 3's quote-based metaprogramming instead of the previous Scala 2 macros.

slf4j/src/main/scala-3 · high confidence

Refactor SLF4J logger creation with explicit factory pattern

The SLF4J integration now uses a new \Slf4jFactory\ trait and companion object to manage logger creation, replacing the previous implicit resolution mechanism. Users should now explicitly call \Slf4jFactory.create\[F\]\ to obtain a factory instance, as the previous implicit \loggerFactoryforSync\ has been deprecated. The \Slf4jLogger\ object provides updated methods like \getLoggerFromBlockingSlf4j\ and \fromBlockingSlf4j\ to support non-blocking logger instantiation, ensuring that creating logger instances does not block the calling thread.

slf4j/src/main/scala/org/typelevel/log4cats/slf4j · high confidence

Refactored internal SLF4J logger to handle MDC safely and non-blockingly

The internal \Slf4jLoggerInternal\ implementation has been rewritten to ensure that interactions with the SLF4J MDC (Mapped Diagnostic Context) are non-blocking and resilient to misconfiguration. The new code uses \Sync.delay\ to wrap MDC operations, preventing potential deadlocks in effectful contexts, and includes error handling to salvage logging output even if the MDC adapter is missing or throws an \IllegalStateException\. Additionally, the logger now exposes MDC state checks via \isEnabled\ methods and ensures that context is managed without blocking the calling thread.

slf4j/src/main/scala/org/typelevel/log4cats/slf4j/internal · high confidence

Switch to Apache 2.0 license and update build configuration

The project license has been changed to Apache 2.0. The build environment is now configured with specific JVM options in \.sbtopts\ (including G1GC and memory settings), and the Scala Steward configuration pins \slf4j-api\ and \logback-classic\ to version 1.x to prevent unwanted updates. Additionally, the \.scalafmt.conf\ file has been updated to version 3.11.5 with Scala 3 dialect support, and the Travis CI configuration has been removed.

(repo-wide) · high confidence

Test coverage

Added MUnit-based tests for paging structured logger; Added compilation hygiene and macro tests for Slf4jLogger; Added comprehensive tests for Slf4jLoggerInternal MDC handling and lazy evaluation; Added syntax compilation tests for LoggerFactory and Logger; Added tests for LoggerName resolution; Added tests for deferred logging capabilities; Removed obsolete MainSpec test.

Dependencies

Major dependency and build system overhaul

The project has been significantly modernized by upgrading core dependencies to Cats 2.13.0 and Cats-Effect 3.7.1, and updating the Scala versions to 2.12.21, 2.13.18, and 3.3.7. The build infrastructure has migrated to the sbt-typelevel plugin, replacing the previous release and CI setup, and the project structure has been split into distinct modules (core, testing, noop, slf4j, docs, js-console) with cross-compilation support for JVM, JS, and Native platforms.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

Baseline

  • First survey — no prior run to compare against. CAI 60.

Lenses

  • Code Health 96
  • Architecture 100
  • Maturity 46
  • Readiness 67
  • Security 65

Changes since last survey

  • 300 commits — 296 feature/other, 4 fixes

By area

  • (repo) — 134 commits
  • (root) — 59 commits
  • project/build.properties — 34 commits
  • project/plugins.sbt — 29 commits
  • slf4j/src — 16 commits
  • core/shared — 14 commits
  • .github/workflows — 9 commits
  • testing/shared — 5 commits

Notable commits

  • fix: Fix misalignment of types
  • fix: Fix some warnings related to -xsource:3
  • fix: Fix unused import
  • fix: Merge pull request #845 from danicheg/fix-#844
  • change: Add .sbtopts
  • change: Add DeferredLoggerFactory
  • change: Add TestingLoggerFactory
  • change: Add missing overrides for mapK and friends
  • change: Add test explicitly demonstrating MDC behavior
  • change: Always handle the MDC
  • change: Apply suggestions from code review
  • change: Attempt to balance warn message changes between Scala 2/3
  • change: Attempt to salvage the log if the MDC is busted
  • change: Bump base version
  • change: Bump tlBaseVersion
  • change: Clean up unneeded calls to Show
  • change: Colocate the logging levels in Slf4jLoggerInternal
  • change: Expand test coverage of Slf4jLogger
  • change: Expose MDC to Slf4jLoggerInternal isEnabled
  • change: Formatting and documentation cleanup
  • …and 280 more

Architecture

  • 0 containers · 1 bounded contexts · 0 dependency edges (baseline)

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

typelevel/log4cats was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 20 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 575a9320c5e824a25ee463db6d437fa199d5380d — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-b51f968c9b10.