diff --git a/lib/Polysemy/Log.hs b/lib/Polysemy/Log.hs
--- a/lib/Polysemy/Log.hs
+++ b/lib/Polysemy/Log.hs
@@ -12,6 +12,8 @@
   dataLog,
 
   -- ** Interpreters
+  interpretDataLogStderrWith,
+  interpretDataLogStderr,
   interpretDataLogAtomic',
   interpretDataLogAtomic,
 
@@ -31,6 +33,9 @@
   Severity(..),
 
   -- ** Interpreters
+  interpretLogStderrWith,
+  interpretLogStderr,
+  interpretLogStderr',
   interpretLogDataLog,
   interpretLogDataLog',
   interpretLogOutput,
@@ -51,7 +56,16 @@
 import Polysemy.Log.Data.LogMessage (LogMessage(LogMessage))
 import Polysemy.Log.Data.Severity (Severity(..))
 import Polysemy.Log.Format (formatLogEntry)
-import Polysemy.Log.Log (interpretLogDataLog, interpretLogDataLog', interpretLogDataLogConc)
+import Polysemy.Log.Log (
+  interpretLogDataLog,
+  interpretLogDataLog',
+  interpretLogDataLogConc,
+  interpretDataLogStderrWith,
+  interpretDataLogStderr,
+  interpretLogStderrWith,
+  interpretLogStderr,
+  interpretLogStderr',
+  )
 import Polysemy.Log.Pure (interpretLogNull, interpretLogOutput)
 
 -- $intro
diff --git a/lib/Polysemy/Log/Atomic.hs b/lib/Polysemy/Log/Atomic.hs
--- a/lib/Polysemy/Log/Atomic.hs
+++ b/lib/Polysemy/Log/Atomic.hs
@@ -1,29 +1,12 @@
 -- |Description: Internal
 module Polysemy.Log.Atomic where
 
-import Polysemy (interpretH, runT)
 import Polysemy.Internal (InterpretersFor)
-import Polysemy.Internal.Tactics (liftT)
 
-import Polysemy.Log.Data.DataLog (DataLog(DataLog, Local))
+import Polysemy.Log.Data.DataLog (DataLog)
 import Polysemy.Log.Data.Log (Log(Log))
 import Polysemy.Log.Data.LogMessage (LogMessage)
-
--- |Interpret 'DataLog' by prepending each message to a list in an 'AtomicState'.
--- Maintains a context function as state that is applied to each logged message, allowing the context of a block to be
--- modified.
-interpretDataLogAtomicLocal ::
-  ∀ a r .
-  Member (AtomicState [a]) r =>
-  (a -> a) ->
-  InterpreterFor (DataLog a) r
-interpretDataLogAtomicLocal context =
-  interpretH \case
-    DataLog msg ->
-      liftT (atomicModify' (context msg :))
-    Local f ma ->
-      raise . interpretDataLogAtomicLocal (f . context) =<< runT ma
-{-# INLINE interpretDataLogAtomicLocal #-}
+import Polysemy.Log.Log (interpretDataLog)
 
 -- |Interpret 'DataLog' by prepending each message to a list in an 'AtomicState'.
 interpretDataLogAtomic' ::
@@ -31,7 +14,7 @@
   Member (AtomicState [a]) r =>
   InterpreterFor (DataLog a) r
 interpretDataLogAtomic' =
-  interpretDataLogAtomicLocal id
+  interpretDataLog \ msg -> atomicModify' @[a] (msg :)
 {-# INLINE interpretDataLogAtomic' #-}
 
 -- |Interpret 'DataLog' by prepending each message to a list in an 'AtomicState', then interpret the 'AtomicState' in a
diff --git a/lib/Polysemy/Log/Log.hs b/lib/Polysemy/Log/Log.hs
--- a/lib/Polysemy/Log/Log.hs
+++ b/lib/Polysemy/Log/Log.hs
@@ -1,18 +1,22 @@
 -- |Description: Internal
 module Polysemy.Log.Log where
 
+import qualified Data.Text.IO as Text
+import Polysemy (interpretH, runT)
 import Polysemy.Async (Async)
 import Polysemy.Conc (Race)
 import Polysemy.Internal (InterpretersFor)
+import Polysemy.Internal.Tactics (liftT)
 import Polysemy.Resource (Resource)
 import Polysemy.Time (GhcTime, interpretTimeGhc)
 
 import Polysemy.Log.Conc (interceptDataLogConc)
-import Polysemy.Log.Data.DataLog (DataLog, dataLog)
+import Polysemy.Log.Data.DataLog (DataLog(DataLog, Local), dataLog)
 import Polysemy.Log.Data.Log (Log(Log))
 import Polysemy.Log.Data.LogEntry (LogEntry, annotate)
 import Polysemy.Log.Data.LogMessage (LogMessage)
 import Polysemy.Log.Data.LogMetadata (LogMetadata(Annotated), annotated)
+import Polysemy.Log.Format (formatLogEntry)
 
 -- |Interpret 'Log' into the intermediate internal effect 'LogMetadata'.
 interpretLogLogMetadata ::
@@ -75,3 +79,77 @@
   interpretLogLogMetadata .
   raiseUnder2
 {-# INLINE interpretLogDataLogConc #-}
+
+-- |Helper for maintaining context function as state that is applied to each logged message, allowing the context of a
+-- block to be modified.
+interpretDataLogLocal ::
+  ∀ a r .
+  (a -> a) ->
+  (a -> Sem r ()) ->
+  InterpreterFor (DataLog a) r
+interpretDataLogLocal context log =
+  interpretH \case
+    DataLog msg ->
+      liftT (log (context msg))
+    Local f ma ->
+      raise . interpretDataLogLocal (f . context) log =<< runT ma
+{-# INLINE interpretDataLogLocal #-}
+
+-- |Combinator for building 'DataLog' interpreters that handles 'Local'.
+interpretDataLog ::
+  ∀ a r .
+  (a -> Sem r ()) ->
+  InterpreterFor (DataLog a) r
+interpretDataLog =
+  interpretDataLogLocal id
+
+-- |Interpret 'DataLog' by printing to stderr, converting messages to 'Text' with the supplied function.
+interpretDataLogStderrWith ::
+  Member (Embed IO) r =>
+  (a -> Text) ->
+  InterpreterFor (DataLog a) r
+interpretDataLogStderrWith fmt =
+  interpretDataLog \ msg -> embed (Text.hPutStrLn stderr (fmt msg))
+{-# INLINE interpretDataLogStderrWith #-}
+
+-- |Interpret 'DataLog' by printing to stderr, converting messages to 'Text' by using 'Show'.
+interpretDataLogStderr ::
+  Show a =>
+  Member (Embed IO) r =>
+  InterpreterFor (DataLog a) r
+interpretDataLogStderr =
+  interpretDataLogStderrWith show
+{-# INLINE interpretDataLogStderr #-}
+
+-- |Interpret 'Log' by printing to stderr, converting messages to 'Text' with the supplied function.
+interpretLogStderrWith ::
+  Members [Embed IO, GhcTime] r =>
+  (LogEntry LogMessage -> Text) ->
+  InterpreterFor Log r
+interpretLogStderrWith fmt =
+  interpretDataLogStderrWith fmt .
+  interpretTimeGhc .
+  interpretLogDataLog .
+  raiseUnder2
+{-# INLINE interpretLogStderrWith #-}
+
+-- |Interpret 'Log' by printing to stderr, using the default formatter.
+--
+-- Since this adds a timestamp, it has a dependency on 'GhcTime'.
+-- Use 'interpretLogStderr'' for a variant that interprets 'GhcTime' in-place.
+interpretLogStderr ::
+  Members [Embed IO, GhcTime] r =>
+  InterpreterFor Log r
+interpretLogStderr =
+  interpretLogStderrWith formatLogEntry
+{-# INLINE interpretLogStderr #-}
+
+-- |Interpret 'Log' by printing to stderr, using the default formatter, then interpreting 'GhcTime'.
+interpretLogStderr' ::
+  Member (Embed IO) r =>
+  InterpreterFor Log r
+interpretLogStderr' =
+  interpretTimeGhc .
+  interpretLogStderr .
+  raiseUnder
+{-# INLINE interpretLogStderr' #-}
diff --git a/polysemy-log.cabal b/polysemy-log.cabal
--- a/polysemy-log.cabal
+++ b/polysemy-log.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           polysemy-log
-version:        0.2.0.1
+version:        0.2.1.0
 synopsis:       Polysemy effects for logging
 description:    See <https://hackage.haskell.org/package/polysemy-log/docs/Polysemy-Log.html>
 category:       Logging
