{-# LANGUAGE TemplateHaskell #-}{-# LANGUAGE CPP #-}{-# LANGUAGE TypeFamilies #-}{-# LANGUAGE FlexibleInstances #-}{-# LANGUAGE MultiParamTypeClasses #-}{-# LANGUAGE UndecidableInstances #-}-- | This module provides the facilities needed for a decoupled logging system.---- The 'MonadLogger' class is implemented by monads that give access to a-- logging facility. Note that although 'IO', 'Identity' and 'ST' are-- instances of 'MonadLogger', they will /discard all log messages/. If you're-- defining a custom monad, then you may define an instance of 'MonadLogger'-- that routes the log messages to the appropriate place (e.g., that's what-- @yesod-core@'s @GHandler@ does). Otherwise, you may use the 'LoggingT'-- monad included in this module (see 'runStderrLoggingT').---- As a user of the logging facility, we provide you some convenient Template-- Haskell splices that use the 'MonadLogger' class. They will record their-- source file and position, which is very helpful when debugging. See-- 'logDebug' for more information.moduleControl.Monad.Logger(-- * MonadLoggerMonadLogger(..),LogLevel(..),LogSource-- * Helper transformer,LoggingT(..),runStderrLoggingT,runStdoutLoggingT-- * TH logging,logDebug,logInfo,logWarn,logError,logOther-- * TH logging with source,logDebugS,logInfoS,logWarnS,logErrorS,logOtherS)whereimportLanguage.Haskell.TH.Syntax(Lift(lift),Q,Exp,Loc(..),qLocation)importSystem.Log.FastLogger(ToLogStr(toLogStr),LogStr(..))importData.Monoid(Monoid)importControl.Applicative(Applicative(..))importControl.Monad(liftM,ap)importControl.Monad.Base(MonadBase(liftBase))importControl.Monad.Trans.Control(MonadBaseControl(..),MonadTransControl(..))importData.Functor.Identity(Identity)importControl.Monad.ST(ST)importqualifiedControl.Monad.ST.LazyasLazy(ST)importqualifiedControl.Monad.Trans.ClassasTransimportSystem.IO(stdout,stderr,Handle)importControl.Monad.IO.Class(MonadIO(liftIO))importControl.Monad.Trans.Resource(MonadResource(liftResourceT),MonadThrow(monadThrow))importControl.Monad.Trans.Identity(IdentityT)importControl.Monad.Trans.List(ListT)importControl.Monad.Trans.Maybe(MaybeT)importControl.Monad.Trans.Error(ErrorT,Error)importControl.Monad.Trans.Reader(ReaderT)importControl.Monad.Trans.Cont(ContT)importControl.Monad.Trans.State(StateT)importControl.Monad.Trans.Writer(WriterT)importControl.Monad.Trans.RWS(RWST)importControl.Monad.Trans.Resource(ResourceT)importData.Conduit(Pipe)importqualifiedControl.Monad.Trans.RWS.StrictasStrict(RWST)importqualifiedControl.Monad.Trans.State.StrictasStrict(StateT)importqualifiedControl.Monad.Trans.Writer.StrictasStrict(WriterT)importData.Text(Text,pack,unpack,empty)importqualifiedData.TextasTimportqualifiedData.ByteString.Char8asS8importData.Text.Encoding(encodeUtf8)importControl.Monad.Cont.Class(MonadCont(..))importControl.Monad.Error.Class(MonadError(..))importControl.Monad.RWS.Class(MonadRWS)importControl.Monad.Reader.Class(MonadReader(..))importControl.Monad.State.Class(MonadState(..))importControl.Monad.Writer.Class(MonadWriter(..))dataLogLevel=LevelDebug|LevelInfo|LevelWarn|LevelError|LevelOtherTextderiving(Eq,Prelude.Show,Prelude.Read,Ord)instanceLiftLogLevelwhereliftLevelDebug=[|LevelDebug|]liftLevelInfo=[|LevelInfo|]liftLevelWarn=[|LevelWarn|]liftLevelError=[|LevelError|]lift(LevelOtherx)=[|LevelOther$pack$(lift$unpackx)|]typeLogSource=TextclassMonadm=>MonadLoggermwheremonadLoggerLog::ToLogStrmsg=>Loc->LogLevel->msg->m()monadLoggerLogSource::ToLogStrmsg=>Loc->LogSource->LogLevel->msg->m()monadLoggerLogSourceloc_levelmsg=monadLoggerLogloclevelmsginstanceMonadLoggerIOwheremonadLoggerLog___=return()instanceMonadLoggerIdentitywheremonadLoggerLog___=return()instanceMonadLogger(STs)wheremonadLoggerLog___=return()instanceMonadLogger(Lazy.STs)wheremonadLoggerLog___=return()#define DEF monadLoggerLog a b c = Trans.lift $ monadLoggerLog a b c; monadLoggerLogSource a b c d = Trans.lift $ monadLoggerLogSource a b c dinstanceMonadLoggerm=>MonadLogger(IdentityTm)whereDEFinstanceMonadLoggerm=>MonadLogger(ListTm)whereDEFinstanceMonadLoggerm=>MonadLogger(MaybeTm)whereDEFinstance(MonadLoggerm,Errore)=>MonadLogger(ErrorTem)whereDEFinstanceMonadLoggerm=>MonadLogger(ReaderTrm)whereDEFinstanceMonadLoggerm=>MonadLogger(ContTrm)whereDEFinstanceMonadLoggerm=>MonadLogger(StateTsm)whereDEFinstance(MonadLoggerm,Monoidw)=>MonadLogger(WriterTwm)whereDEFinstance(MonadLoggerm,Monoidw)=>MonadLogger(RWSTrwsm)whereDEFinstanceMonadLoggerm=>MonadLogger(ResourceTm)whereDEFinstanceMonadLoggerm=>MonadLogger(Pipelioum)whereDEFinstanceMonadLoggerm=>MonadLogger(Strict.StateTsm)whereDEFinstance(MonadLoggerm,Monoidw)=>MonadLogger(Strict.WriterTwm)whereDEFinstance(MonadLoggerm,Monoidw)=>MonadLogger(Strict.RWSTrwsm)whereDEF#undef DEFlogTH::LogLevel->QExplogTHlevel=[|monadLoggerLog$(qLocation>>=liftLoc)$(liftlevel).(id::Text->Text)|]-- | Generates a function that takes a 'Text' and logs a 'LevelDebug' message. Usage:---- > $(logDebug) "This is a debug log message"logDebug::QExplogDebug=logTHLevelDebug-- | See 'logDebug'logInfo::QExplogInfo=logTHLevelInfo-- | See 'logDebug'logWarn::QExplogWarn=logTHLevelWarn-- | See 'logDebug'logError::QExplogError=logTHLevelError-- | Generates a function that takes a 'Text' and logs a 'LevelOther' message. Usage:---- > $(logOther "My new level") "This is a log message"logOther::Text->QExplogOther=logTH.LevelOtherliftLoc::Loc->QExpliftLoc(Locabc(d1,d2)(e1,e2))=[|Loc$(lifta)$(liftb)$(liftc)($(liftd1),$(liftd2))($(lifte1),$(lifte2))|]-- | Generates a function that takes a 'LogSource' and 'Text' and logs a 'LevelDebug' message. Usage:---- > $logDebug "SomeSource" "This is a debug log message"logDebugS::QExplogDebugS=[|\ab->monadLoggerLogSource$(qLocation>>=liftLoc)aLevelDebug(b::Text)|]-- | See 'logDebugS'logInfoS::QExplogInfoS=[|\ab->monadLoggerLogSource$(qLocation>>=liftLoc)aLevelInfo(b::Text)|]-- | See 'logDebugS'logWarnS::QExplogWarnS=[|\ab->monadLoggerLogSource$(qLocation>>=liftLoc)aLevelWarn(b::Text)|]-- | See 'logDebugS'logErrorS::QExplogErrorS=[|\ab->monadLoggerLogSource$(qLocation>>=liftLoc)aLevelError(b::Text)|]-- | Generates a function that takes a 'LogSource', a level name and a 'Text' and logs a 'LevelOther' message. Usage:---- > $logOther "SomeSource" "My new level" "This is a log message"logOtherS::QExplogOtherS=[|\srclevelmsg->monadLoggerLogSource$(qLocation>>=liftLoc)src(LevelOtherlevel)(msg::Text)|]-- | Monad transformer that adds a new logging function.---- Since 0.2.2newtypeLoggingTma=LoggingT{runLoggingT::(Loc->LogSource->LogLevel->LogStr->IO())->ma}instanceMonadm=>Functor(LoggingTm)wherefmap=liftMinstanceMonadm=>Applicative(LoggingTm)wherepure=return(<*>)=apinstanceMonadm=>Monad(LoggingTm)wherereturn=LoggingT.const.returnLoggingTma>>=f=LoggingT$\r->doa<-marletLoggingTf'=faf'rinstanceMonadIOm=>MonadIO(LoggingTm)whereliftIO=Trans.lift.liftIOinstanceMonadThrowm=>MonadThrow(LoggingTm)wheremonadThrow=Trans.lift.monadThrowinstanceMonadResourcem=>MonadResource(LoggingTm)whereliftResourceT=Trans.lift.liftResourceTinstanceMonadBasebm=>MonadBaseb(LoggingTm)whereliftBase=Trans.lift.liftBaseinstanceTrans.MonadTransLoggingTwherelift=LoggingT.constinstanceMonadTransControlLoggingTwherenewtypeStTLoggingTa=StReader{unStReader::a}liftWithf=LoggingT$\r->f$\(LoggingTt)->liftMStReader$trrestoreT=LoggingT.const.liftMunStReader{-# INLINE liftWith #-}{-# INLINE restoreT #-}instanceMonadBaseControlbm=>MonadBaseControlb(LoggingTm)wherenewtypeStM(LoggingTm)a=StMT(StMma)liftBaseWithf=LoggingT$\reader'->liftBaseWith$\runInBase->f$liftMStMT.runInBase.(\(LoggingTr)->rreader')restoreM(StMTbase)=LoggingT$const$restoreMbaseinstanceMonadIOm=>MonadLogger(LoggingTm)wheremonadLoggerLogabc=monadLoggerLogSourceaemptybcmonadLoggerLogSourceabcd=LoggingT$\f->liftIO$fabc(toLogStrd)defaultOutput::Handle->Loc->LogSource->LogLevel->LogStr->IO()defaultOutputhlocsrclevelmsg=S8.hPutStrLnh$S8.concatbswherebs=[S8.pack"[",caselevelofLevelOthert->encodeUtf8t_->encodeUtf8$pack$drop5$showlevel,ifT.nullsrcthenS8.emptyelseencodeUtf8$'#'`T.cons`src,S8.pack"] ",casemsgofLSs->encodeUtf8$packsLBb->b,S8.pack" @(",encodeUtf8$packfileLocStr,S8.pack")\n"]-- taken from file-location package-- turn the TH Loc loaction information into a human readable string-- leaving out the loc_end parameterfileLocStr=(loc_packageloc)++':':(loc_moduleloc)++' ':(loc_filenameloc)++':':(lineloc)++':':(charloc)whereline=show.fst.loc_startchar=show.snd.loc_start-- | Run a block using a @MonadLogger@ instance which prints to stderr.---- Since 0.2.2runStderrLoggingT::MonadIOm=>LoggingTma->marunStderrLoggingT=(`runLoggingT`defaultOutputstderr)-- | Run a block using a @MonadLogger@ instance which prints to stdout.---- Since 0.2.2runStdoutLoggingT::MonadIOm=>LoggingTma->marunStdoutLoggingT=(`runLoggingT`defaultOutputstdout)instanceMonadContm=>MonadCont(LoggingTm)wherecallCCf=LoggingT$\i->callCC$\c->runLoggingT(f(LoggingT.const.c))iinstanceMonadErrorem=>MonadErrore(LoggingTm)wherethrowError=Trans.lift.throwErrorcatchErrorrh=LoggingT$\i->runLoggingTri`catchError`\e->runLoggingT(he)iinstanceMonadRWSrwsm=>MonadRWSrws(LoggingTm)instanceMonadReaderrm=>MonadReaderr(LoggingTm)whereask=Trans.liftasklocal=mapLoggingT.localmapLoggingT::(ma->nb)->LoggingTma->LoggingTnbmapLoggingTf=LoggingT.(f.).runLoggingTinstanceMonadStatesm=>MonadStates(LoggingTm)whereget=Trans.liftgetput=Trans.lift.putinstanceMonadWriterwm=>MonadWriterw(LoggingTm)wheretell=Trans.lift.telllisten=mapLoggingTlistenpass=mapLoggingTpass