Skip to content

Commit

Permalink
Add scaladocs and documentation of caveats
Browse files Browse the repository at this point in the history
  • Loading branch information
morgen-peschke committed May 31, 2024
1 parent 678d200 commit a23da95
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,25 @@ import org.typelevel.log4cats.extras.DeferredLogger.DeferredLogMessage
* }
* }
* }}}
*
* >>> WARNING: READ BEFORE USAGE! <<<
* https://github.com/typelevel/log4cats/blob/main/core/shared/src/main/scala/org/typelevel/log4cats/extras/README.md
* >>> WARNING: READ BEFORE USAGE! <<<
*/
trait DeferredLogger[F[_]] extends Logger[F] {
/**
* View the logs in the buffer.
*
* This is primarily useful for testing, and will not effect the behavior
* of calls to `log`
*/
def inspect: F[Chain[DeferredLogMessage]]

/**
* Log the deferred messages
*
* This may be called multiple times, and each log should only be logged once.
*/
def log: F[Unit]
}
object DeferredLogger {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,33 @@ import cats.{~>, Functor}
import org.typelevel.log4cats.extras.DeferredStructuredLogger.DeferredStructuredLogMessage
import org.typelevel.log4cats.{LoggerFactory, SelfAwareStructuredLogger}

/**
* A `LoggerFactory` that does not immediately log.
*
* Effectively a `LoggerFactory` equivalent to `DeferredSelfAwareStructuredLogger`.
* As an implementation note, the `LoggerFactory` trait is constrained in such a way that
* this will produce `SelfAwareStructuredLogger`, rather than `DeferredSelfAwareStructuredLogger`,
* so if logging is desired it needs to be triggered using the `DeferredLoggerFactory`, rather than
* being able to trigger it from any of the produced loggers.
*
* >>> WARNING: READ BEFORE USAGE! <<<
* https://github.com/typelevel/log4cats/blob/main/core/shared/src/main/scala/org/typelevel/log4cats/extras/README.md
* >>> WARNING: READ BEFORE USAGE! <<<
*/
trait DeferredLoggerFactory[F[_]] extends LoggerFactory[F] {
/**
* View the logs in the buffer.
*
* This is primarily useful for testing, and will not effect the behavior
* of calls to `log`
*/
def inspect: F[Chain[DeferredStructuredLogMessage]]

/**
* Log the deferred messages
*
* This may be called multiple times, and each log should only be logged once.
*/
def log: F[Unit]

override def getLoggerFromName(name: String): SelfAwareStructuredLogger[F]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,25 @@ import org.typelevel.log4cats.extras.DeferredStructuredLogger.{

/**
* Similar to `DeferredStructuredLogger`, for `SelfAwareStructuredLogger`
*
* >>> WARNING: READ BEFORE USAGE! <<<
* https://github.com/typelevel/log4cats/blob/main/core/shared/src/main/scala/org/typelevel/log4cats/extras/README.md
* >>> WARNING: READ BEFORE USAGE! <<<
*/
trait DeferredSelfAwareStructuredLogger[F[_]] extends SelfAwareStructuredLogger[F] {
/**
* View the logs in the buffer.
*
* This is primarily useful for testing, and will not effect the behavior
* of calls to `log`
*/
def inspect: F[Chain[DeferredStructuredLogMessage]]

/**
* Log the deferred messages
*
* This may be called multiple times, and each log should only be logged once.
*/
def log: F[Unit]

override def mapK[G[_]](fk: F ~> G): DeferredSelfAwareStructuredLogger[G] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,25 @@ import org.typelevel.log4cats.extras.DeferredStructuredLogger.DeferredStructured
* }
* }
* }}}
*
* >>> WARNING: READ BEFORE USAGE! <<<
* https://github.com/typelevel/log4cats/blob/main/core/shared/src/main/scala/org/typelevel/log4cats/extras/README.md
* >>> WARNING: READ BEFORE USAGE! <<<
*/
trait DeferredStructuredLogger[F[_]] extends StructuredLogger[F] {
/**
* View the logs in the buffer.
*
* This is primarily useful for testing, and will not effect the behavior
* of calls to `log`
*/
def inspect: F[Chain[DeferredStructuredLogMessage]]

/**
* Log the deferred messages
*
* This may be called multiple times, and each log should only be logged once.
*/
def log: F[Unit]
}
object DeferredStructuredLogger {
Expand Down
26 changes: 18 additions & 8 deletions core/shared/src/main/scala/org/typelevel/log4cats/extras/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
Important notes about `Writer*Logger`s
======================================
Important caveats about the loggers in `org.typelevel.log4cats.extras`
======================================================================

`Writer*Logger`
---------------

The loggers provided here backed by `Writer` and `WriterT` come with some important caveats that
you should be aware of before using.

General Notes
-------------
### General Notes

> **Note**
> These loggers tie their logs to the lifecycle of the return value, so they're generally only useful
Expand All @@ -24,8 +26,7 @@ Better alternatives are provided by the `testing` module:
- If a `SelfAwareStructuredLogger` is needed for test code, consider
`org.typelevel.log4cats.testing.StructuredTestingLogger` over `WriterStructuredLogger`

`WriterLogger` / `WriterStructureLogger`
----------------------------------------
### `WriterLogger` / `WriterStructureLogger`

> **Warning**
> Expect to lose logs if an exception occurs
Expand All @@ -34,8 +35,7 @@ These are built using `Writer`, which does not directly interact with effects, s
non-trivial amount of plumbing if you're planning on using them. Otherwise, if the logs don't matter
in the presence of errors in the context you're using them, they're fine.

`WriterTLogger` / `WriterTStructuredLogger`
-------------------------------------------
### `WriterTLogger` / `WriterTStructuredLogger`

These are built using `WriterT`, and are much easier to use with effects. Running the `WriterT`
instance will yield a value of type `F[(G[LogMessage], A)]`.
Expand All @@ -46,3 +46,13 @@ instance will yield a value of type `F[(G[LogMessage], A)]`.
Unfortunately, because of the way that cancellation (and thus timeouts) is handled by
`cats.effect.IO`, in practice `WriterT` isn't a great fit for anything which can timeout.

`Deferred*Logger` and `Deferred*LoggerFactory`
----------------------------------------------

The deferred `Logger` and `LoggerFactory` subclasses store their log messages in an unbounded
buffer. This is on the assumption that, if something is being logged, it matters enough to keep
around.

This carries the risk of potentially unbounded memory usage. For example, in situations where
logging is done by code that is caught in an infinite loop.

0 comments on commit a23da95

Please sign in to comment.