packages feed

extensible-effects-concurrent 0.5.0.1 → 0.6.0

raw patch · 16 files changed

+1054/−900 lines, 16 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.Eff.Log: [LogMsg] :: message -> Logs message ()
- Control.Eff.Log: captureLogs :: NFData message => Eff (Logs message : r) a -> Eff r (a, Seq message)
- Control.Eff.Log: closeLogChannelAfter :: (Show message, Typeable message, IsString message) => Maybe message -> LogChannel message -> IO a -> IO a
- Control.Eff.Log: data JoinLogChannelException m
- Control.Eff.Log: data KillLogChannelException m
- Control.Eff.Log: data LogChannel message
- Control.Eff.Log: data Logs message a
- Control.Eff.Log: filterLogChannel :: (message -> Bool) -> LogChannel message -> LogChannel message
- Control.Eff.Log: foldLogMessages :: forall r m a f. (Foldable f, Member (Logs m) r) => (m -> f m) -> Eff r a -> Eff r a
- Control.Eff.Log: forkLogger :: forall message. (Typeable message, Show message) => Int -> (message -> IO ()) -> Maybe message -> IO (LogChannel message)
- Control.Eff.Log: handleLogsWith :: forall m r message a. (NFData message, Monad m, SetMember Lift (Lift m) r) => (message -> m ()) -> Eff (Logs message : r) a -> Eff r a
- Control.Eff.Log: handleLogsWithLoggingTHandler :: forall m r message a. (Monad m, SetMember Lift (Lift m) r) => Eff (Logs message : r) a -> (forall b. (Handler m message -> m b) -> m b) -> Eff r a
- Control.Eff.Log: ignoreLogs :: forall message r a. Eff (Logs message : r) a -> Eff r a
- Control.Eff.Log: instance (Data.Typeable.Internal.Typeable m, GHC.Show.Show m) => GHC.Exception.Exception (Control.Eff.Log.JoinLogChannelException m)
- Control.Eff.Log: instance (Data.Typeable.Internal.Typeable m, GHC.Show.Show m) => GHC.Exception.Exception (Control.Eff.Log.KillLogChannelException m)
- Control.Eff.Log: instance GHC.Show.Show m => GHC.Show.Show (Control.Eff.Log.JoinLogChannelException m)
- Control.Eff.Log: instance GHC.Show.Show m => GHC.Show.Show (Control.Eff.Log.KillLogChannelException m)
- Control.Eff.Log: interceptLogging :: forall r m a. Member (Logs m) r => (m -> Eff r ()) -> Eff r a -> Eff r a
- Control.Eff.Log: joinLogChannel :: (Show message, Typeable message) => Maybe message -> LogChannel message -> IO ()
- Control.Eff.Log: killLogChannel :: (Show message, Typeable message) => Maybe message -> LogChannel message -> IO ()
- Control.Eff.Log: logChannelBracket :: (Show message, Typeable message) => Int -> Maybe message -> Maybe message -> (LogChannel message -> IO a) -> LoggingT message IO a
- Control.Eff.Log: logChannelPutIO :: LogChannel message -> message -> IO ()
- Control.Eff.Log: logMsg :: Member (Logs m) r => m -> Eff r ()
- Control.Eff.Log: logToChannel :: forall r message a. (SetMember Lift (Lift IO) r) => LogChannel message -> Eff (Logs message : r) a -> Eff r a
- Control.Eff.Log: noLogger :: LogChannel message
- Control.Eff.Log.MessageFactory: composeMessageFactories :: forall m e a. (Member (MessageFactoryReader m) e) => (m -> IO m) -> Eff e a -> Eff e a
- Control.Eff.Log.MessageFactory: data MessageFactory m
- Control.Eff.Log.MessageFactory: localMessageFactory :: forall m e a. (Member (MessageFactoryReader m) e) => IO m -> Eff e a -> Eff e a
- Control.Eff.Log.MessageFactory: mkLogMsg :: forall m io e. (Member (Logs m) e, MonadIO io, SetMember Lift (Lift io) e, Member (MessageFactoryReader m) e) => (m -> m) -> Eff e ()
- Control.Eff.Log.MessageFactory: type MessageFactoryReader m = Reader (MessageFactory m)
- Control.Eff.Log.MessageFactory: withLogMessageFactory :: forall m io e a. (Member (Logs m) e, Default m, MonadIO io, SetMember Lift (Lift io) e) => Eff (MessageFactoryReader m : e) a -> Eff e a
- Control.Eff.Log.Syslog: LogMessage :: Facility -> Severity -> Maybe UTCTime -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> [StructuredDataElement] -> Maybe SrcLoc -> String -> LogMessage
- Control.Eff.Log.Syslog: StructuredDataElement :: String -> [(String, Maybe String)] -> StructuredDataElement
- Control.Eff.Log.Syslog: [_lmAppname] :: LogMessage -> Maybe String
- Control.Eff.Log.Syslog: [_lmFacility] :: LogMessage -> Facility
- Control.Eff.Log.Syslog: [_lmHostname] :: LogMessage -> Maybe String
- Control.Eff.Log.Syslog: [_lmMessageId] :: LogMessage -> Maybe String
- Control.Eff.Log.Syslog: [_lmMessage] :: LogMessage -> String
- Control.Eff.Log.Syslog: [_lmProcessId] :: LogMessage -> Maybe String
- Control.Eff.Log.Syslog: [_lmSeverity] :: LogMessage -> Severity
- Control.Eff.Log.Syslog: [_lmSrcLoc] :: LogMessage -> Maybe SrcLoc
- Control.Eff.Log.Syslog: [_lmStructuredData] :: LogMessage -> [StructuredDataElement]
- Control.Eff.Log.Syslog: [_lmTimestamp] :: LogMessage -> Maybe UTCTime
- Control.Eff.Log.Syslog: [_sdElementId] :: StructuredDataElement -> String
- Control.Eff.Log.Syslog: [_sdElementParameters] :: StructuredDataElement -> [(String, Maybe String)]
- Control.Eff.Log.Syslog: addSyslogTimestamps :: (MonadIO io, SetMember Lift (Lift io) e, Member (Logs LogMessage) e, Member (MessageFactoryReader LogMessage) e) => Eff e a -> Eff e a
- Control.Eff.Log.Syslog: alertSeverity :: Severity
- Control.Eff.Log.Syslog: clockDaemon :: Facility
- Control.Eff.Log.Syslog: clockDaemon2 :: Facility
- Control.Eff.Log.Syslog: criticalSeverity :: Severity
- Control.Eff.Log.Syslog: data Facility
- Control.Eff.Log.Syslog: data LogMessage
- Control.Eff.Log.Syslog: data Severity
- Control.Eff.Log.Syslog: data StructuredDataElement
- Control.Eff.Log.Syslog: debugSeverity :: Severity
- Control.Eff.Log.Syslog: emergencySeverity :: Severity
- Control.Eff.Log.Syslog: errorSeverity :: Severity
- Control.Eff.Log.Syslog: ftpDaemon :: Facility
- Control.Eff.Log.Syslog: informationalSeverity :: Severity
- Control.Eff.Log.Syslog: instance Control.DeepSeq.NFData Control.Eff.Log.Syslog.Facility
- Control.Eff.Log.Syslog: instance Control.DeepSeq.NFData Control.Eff.Log.Syslog.LogMessage
- Control.Eff.Log.Syslog: instance Control.DeepSeq.NFData Control.Eff.Log.Syslog.Severity
- Control.Eff.Log.Syslog: instance Control.DeepSeq.NFData Control.Eff.Log.Syslog.StructuredDataElement
- Control.Eff.Log.Syslog: instance Data.Default.Class.Default Control.Eff.Log.Syslog.LogMessage
- Control.Eff.Log.Syslog: instance GHC.Classes.Eq Control.Eff.Log.Syslog.Facility
- Control.Eff.Log.Syslog: instance GHC.Classes.Eq Control.Eff.Log.Syslog.LogMessage
- Control.Eff.Log.Syslog: instance GHC.Classes.Eq Control.Eff.Log.Syslog.Severity
- Control.Eff.Log.Syslog: instance GHC.Classes.Eq Control.Eff.Log.Syslog.StructuredDataElement
- Control.Eff.Log.Syslog: instance GHC.Classes.Ord Control.Eff.Log.Syslog.Facility
- Control.Eff.Log.Syslog: instance GHC.Classes.Ord Control.Eff.Log.Syslog.Severity
- Control.Eff.Log.Syslog: instance GHC.Classes.Ord Control.Eff.Log.Syslog.StructuredDataElement
- Control.Eff.Log.Syslog: instance GHC.Generics.Generic Control.Eff.Log.Syslog.Facility
- Control.Eff.Log.Syslog: instance GHC.Generics.Generic Control.Eff.Log.Syslog.LogMessage
- Control.Eff.Log.Syslog: instance GHC.Generics.Generic Control.Eff.Log.Syslog.Severity
- Control.Eff.Log.Syslog: instance GHC.Generics.Generic Control.Eff.Log.Syslog.StructuredDataElement
- Control.Eff.Log.Syslog: instance GHC.Show.Show Control.Eff.Log.Syslog.Facility
- Control.Eff.Log.Syslog: instance GHC.Show.Show Control.Eff.Log.Syslog.LogMessage
- Control.Eff.Log.Syslog: instance GHC.Show.Show Control.Eff.Log.Syslog.Severity
- Control.Eff.Log.Syslog: instance GHC.Show.Show Control.Eff.Log.Syslog.StructuredDataElement
- Control.Eff.Log.Syslog: kernelMessages :: Facility
- Control.Eff.Log.Syslog: linePrinterSubsystem :: Facility
- Control.Eff.Log.Syslog: lmAppname :: Lens' LogMessage (Maybe String)
- Control.Eff.Log.Syslog: lmFacility :: Lens' LogMessage Facility
- Control.Eff.Log.Syslog: lmHostname :: Lens' LogMessage (Maybe String)
- Control.Eff.Log.Syslog: lmMessage :: Lens' LogMessage String
- Control.Eff.Log.Syslog: lmMessageId :: Lens' LogMessage (Maybe String)
- Control.Eff.Log.Syslog: lmProcessId :: Lens' LogMessage (Maybe String)
- Control.Eff.Log.Syslog: lmSeverity :: Lens' LogMessage Severity
- Control.Eff.Log.Syslog: lmSrcLoc :: Lens' LogMessage (Maybe SrcLoc)
- Control.Eff.Log.Syslog: lmStructuredData :: Lens' LogMessage [StructuredDataElement]
- Control.Eff.Log.Syslog: lmTimestamp :: Lens' LogMessage (Maybe UTCTime)
- Control.Eff.Log.Syslog: local0 :: Facility
- Control.Eff.Log.Syslog: local1 :: Facility
- Control.Eff.Log.Syslog: local2 :: Facility
- Control.Eff.Log.Syslog: local3 :: Facility
- Control.Eff.Log.Syslog: local4 :: Facility
- Control.Eff.Log.Syslog: local5 :: Facility
- Control.Eff.Log.Syslog: local6 :: Facility
- Control.Eff.Log.Syslog: local7 :: Facility
- Control.Eff.Log.Syslog: logAlertFacility :: Facility
- Control.Eff.Log.Syslog: logAuditFacility :: Facility
- Control.Eff.Log.Syslog: mailSystem :: Facility
- Control.Eff.Log.Syslog: networkNewsSubsystem :: Facility
- Control.Eff.Log.Syslog: noticeSeverity :: Severity
- Control.Eff.Log.Syslog: ntpSubsystem :: Facility
- Control.Eff.Log.Syslog: sdElementId :: Lens' StructuredDataElement String
- Control.Eff.Log.Syslog: sdElementParameters :: Lens' StructuredDataElement [(String, Maybe String)]
- Control.Eff.Log.Syslog: securityAuthorizationMessages10 :: Facility
- Control.Eff.Log.Syslog: securityAuthorizationMessages4 :: Facility
- Control.Eff.Log.Syslog: syslogMsg :: (HasCallStack, MonadIO io, SetMember Lift (Lift io) e, Member (Logs LogMessage) e, Member (MessageFactoryReader LogMessage) e) => (LogMessage -> LogMessage) -> Eff e ()
- Control.Eff.Log.Syslog: systemDaemons :: Facility
- Control.Eff.Log.Syslog: userLevelMessages :: Facility
- Control.Eff.Log.Syslog: uucpSubsystem :: Facility
- Control.Eff.Log.Syslog: warningSeverity :: Severity
- Control.Eff.Log.Syslog: withSyslog :: forall io e a. (Member (Logs LogMessage) e, Default LogMessage, MonadIO io, SetMember Lift (Lift io) e) => Eff (MessageFactoryReader LogMessage : e) a -> Eff e a
+ Control.Eff.Log.Channel: closeLogChannelAfter :: (Typeable message, IsString message) => Maybe message -> LogChannel message -> IO a -> IO a
+ Control.Eff.Log.Channel: data JoinLogChannelException
+ Control.Eff.Log.Channel: data KillLogChannelException
+ Control.Eff.Log.Channel: data LogChannel message
+ Control.Eff.Log.Channel: filterLogChannel :: (message -> Bool) -> LogChannel message -> LogChannel message
+ Control.Eff.Log.Channel: forkLogger :: forall message. (Typeable message) => Int -> (message -> IO ()) -> Maybe message -> IO (LogChannel message)
+ Control.Eff.Log.Channel: instance GHC.Exception.Exception Control.Eff.Log.Channel.JoinLogChannelException
+ Control.Eff.Log.Channel: instance GHC.Exception.Exception Control.Eff.Log.Channel.KillLogChannelException
+ Control.Eff.Log.Channel: instance GHC.Show.Show Control.Eff.Log.Channel.JoinLogChannelException
+ Control.Eff.Log.Channel: instance GHC.Show.Show Control.Eff.Log.Channel.KillLogChannelException
+ Control.Eff.Log.Channel: joinLogChannel :: (Typeable message) => LogChannel message -> IO ()
+ Control.Eff.Log.Channel: killLogChannel :: (Typeable message) => LogChannel message -> IO ()
+ Control.Eff.Log.Channel: logChannelBracket :: (Typeable message) => Int -> Maybe message -> (LogChannel message -> IO a) -> LoggingT message IO a
+ Control.Eff.Log.Channel: logChannelPutIO :: LogChannel message -> message -> IO ()
+ Control.Eff.Log.Channel: logToChannel :: forall r message a. (SetMember Lift (Lift IO) r) => LogChannel message -> Eff (Logs message : r) a -> Eff r a
+ Control.Eff.Log.Channel: noLogger :: LogChannel message
+ Control.Eff.Log.Handler: [LogMsg] :: message -> Logs message ()
+ Control.Eff.Log.Handler: captureLogs :: NFData message => Eff (Logs message : r) a -> Eff r (a, Seq message)
+ Control.Eff.Log.Handler: data Logs message a
+ Control.Eff.Log.Handler: foldLogMessages :: forall r m a f. (Foldable f, Member (Logs m) r) => (m -> f m) -> Eff r a -> Eff r a
+ Control.Eff.Log.Handler: handleLogsLifted :: forall m r message a. (NFData message, Monad m, SetMember Lift (Lift m) r) => (message -> m ()) -> Eff (Logs message : r) a -> Eff r a
+ Control.Eff.Log.Handler: handleLogsWith :: forall message e a. (message -> Eff e ()) -> Eff (Logs message : e) a -> Eff e a
+ Control.Eff.Log.Handler: handleLogsWithLoggingTHandler :: forall m r message a. (Monad m, SetMember Lift (Lift m) r) => (forall b. (Handler m message -> m b) -> m b) -> Eff (Logs message : r) a -> Eff r a
+ Control.Eff.Log.Handler: ignoreLogs :: forall message r a. Eff (Logs message : r) a -> Eff r a
+ Control.Eff.Log.Handler: interceptLogging :: forall r m a. Member (Logs m) r => (m -> Eff r ()) -> Eff r a -> Eff r a
+ Control.Eff.Log.Handler: logMsg :: Member (Logs m) r => m -> Eff r ()
+ Control.Eff.Log.Handler: relogAsString :: forall m e a. (Show m, Member (Logs String) e) => Eff (Logs m : e) a -> Eff e a
+ Control.Eff.Log.Message: LogMessage :: Facility -> Severity -> Maybe UTCTime -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> [StructuredDataElement] -> Maybe ThreadId -> Maybe SrcLoc -> String -> LogMessage
+ Control.Eff.Log.Message: SdElement :: String -> [SdParameter] -> StructuredDataElement
+ Control.Eff.Log.Message: [_lmAppname] :: LogMessage -> Maybe String
+ Control.Eff.Log.Message: [_lmFacility] :: LogMessage -> Facility
+ Control.Eff.Log.Message: [_lmHostname] :: LogMessage -> Maybe String
+ Control.Eff.Log.Message: [_lmMessageId] :: LogMessage -> Maybe String
+ Control.Eff.Log.Message: [_lmMessage] :: LogMessage -> String
+ Control.Eff.Log.Message: [_lmProcessId] :: LogMessage -> Maybe String
+ Control.Eff.Log.Message: [_lmSeverity] :: LogMessage -> Severity
+ Control.Eff.Log.Message: [_lmSrcLoc] :: LogMessage -> Maybe SrcLoc
+ Control.Eff.Log.Message: [_lmStructuredData] :: LogMessage -> [StructuredDataElement]
+ Control.Eff.Log.Message: [_lmThreadId] :: LogMessage -> Maybe ThreadId
+ Control.Eff.Log.Message: [_lmTimestamp] :: LogMessage -> Maybe UTCTime
+ Control.Eff.Log.Message: [_sdElementId] :: StructuredDataElement -> String
+ Control.Eff.Log.Message: [_sdElementParameters] :: StructuredDataElement -> [SdParameter]
+ Control.Eff.Log.Message: alertSeverity :: Severity
+ Control.Eff.Log.Message: clockDaemon :: Facility
+ Control.Eff.Log.Message: clockDaemon2 :: Facility
+ Control.Eff.Log.Message: criticalSeverity :: Severity
+ Control.Eff.Log.Message: data Facility
+ Control.Eff.Log.Message: data LogMessage
+ Control.Eff.Log.Message: data Severity
+ Control.Eff.Log.Message: data StructuredDataElement
+ Control.Eff.Log.Message: debugMessage :: String -> LogMessage
+ Control.Eff.Log.Message: debugMessageIO :: MonadIO m => String -> m LogMessage
+ Control.Eff.Log.Message: debugSeverity :: Severity
+ Control.Eff.Log.Message: emergencySeverity :: Severity
+ Control.Eff.Log.Message: errorMessage :: String -> LogMessage
+ Control.Eff.Log.Message: errorMessageIO :: MonadIO m => String -> m LogMessage
+ Control.Eff.Log.Message: errorSeverity :: Severity
+ Control.Eff.Log.Message: ftpDaemon :: Facility
+ Control.Eff.Log.Message: infoMessage :: String -> LogMessage
+ Control.Eff.Log.Message: infoMessageIO :: MonadIO m => String -> m LogMessage
+ Control.Eff.Log.Message: informationalSeverity :: Severity
+ Control.Eff.Log.Message: instance Control.DeepSeq.NFData Control.Eff.Log.Message.Facility
+ Control.Eff.Log.Message: instance Control.DeepSeq.NFData Control.Eff.Log.Message.LogMessage
+ Control.Eff.Log.Message: instance Control.DeepSeq.NFData Control.Eff.Log.Message.SdParameter
+ Control.Eff.Log.Message: instance Control.DeepSeq.NFData Control.Eff.Log.Message.Severity
+ Control.Eff.Log.Message: instance Control.DeepSeq.NFData Control.Eff.Log.Message.StructuredDataElement
+ Control.Eff.Log.Message: instance Data.Default.Class.Default Control.Eff.Log.Message.Facility
+ Control.Eff.Log.Message: instance Data.Default.Class.Default Control.Eff.Log.Message.LogMessage
+ Control.Eff.Log.Message: instance Data.Default.Class.Default Control.Eff.Log.Message.Severity
+ Control.Eff.Log.Message: instance Data.String.IsString Control.Eff.Log.Message.LogMessage
+ Control.Eff.Log.Message: instance GHC.Classes.Eq Control.Eff.Log.Message.Facility
+ Control.Eff.Log.Message: instance GHC.Classes.Eq Control.Eff.Log.Message.LogMessage
+ Control.Eff.Log.Message: instance GHC.Classes.Eq Control.Eff.Log.Message.SdParameter
+ Control.Eff.Log.Message: instance GHC.Classes.Eq Control.Eff.Log.Message.Severity
+ Control.Eff.Log.Message: instance GHC.Classes.Eq Control.Eff.Log.Message.StructuredDataElement
+ Control.Eff.Log.Message: instance GHC.Classes.Ord Control.Eff.Log.Message.Facility
+ Control.Eff.Log.Message: instance GHC.Classes.Ord Control.Eff.Log.Message.SdParameter
+ Control.Eff.Log.Message: instance GHC.Classes.Ord Control.Eff.Log.Message.Severity
+ Control.Eff.Log.Message: instance GHC.Classes.Ord Control.Eff.Log.Message.StructuredDataElement
+ Control.Eff.Log.Message: instance GHC.Generics.Generic Control.Eff.Log.Message.Facility
+ Control.Eff.Log.Message: instance GHC.Generics.Generic Control.Eff.Log.Message.LogMessage
+ Control.Eff.Log.Message: instance GHC.Generics.Generic Control.Eff.Log.Message.SdParameter
+ Control.Eff.Log.Message: instance GHC.Generics.Generic Control.Eff.Log.Message.Severity
+ Control.Eff.Log.Message: instance GHC.Generics.Generic Control.Eff.Log.Message.StructuredDataElement
+ Control.Eff.Log.Message: instance GHC.Show.Show Control.Eff.Log.Message.Facility
+ Control.Eff.Log.Message: instance GHC.Show.Show Control.Eff.Log.Message.SdParameter
+ Control.Eff.Log.Message: instance GHC.Show.Show Control.Eff.Log.Message.Severity
+ Control.Eff.Log.Message: instance GHC.Show.Show Control.Eff.Log.Message.StructuredDataElement
+ Control.Eff.Log.Message: kernelMessages :: Facility
+ Control.Eff.Log.Message: linePrinterSubsystem :: Facility
+ Control.Eff.Log.Message: lmAppname :: Lens' LogMessage (Maybe String)
+ Control.Eff.Log.Message: lmFacility :: Lens' LogMessage Facility
+ Control.Eff.Log.Message: lmHostname :: Lens' LogMessage (Maybe String)
+ Control.Eff.Log.Message: lmMessage :: Lens' LogMessage String
+ Control.Eff.Log.Message: lmMessageId :: Lens' LogMessage (Maybe String)
+ Control.Eff.Log.Message: lmProcessId :: Lens' LogMessage (Maybe String)
+ Control.Eff.Log.Message: lmSeverity :: Lens' LogMessage Severity
+ Control.Eff.Log.Message: lmSrcLoc :: Lens' LogMessage (Maybe SrcLoc)
+ Control.Eff.Log.Message: lmStructuredData :: Lens' LogMessage [StructuredDataElement]
+ Control.Eff.Log.Message: lmThreadId :: Lens' LogMessage (Maybe ThreadId)
+ Control.Eff.Log.Message: lmTimestamp :: Lens' LogMessage (Maybe UTCTime)
+ Control.Eff.Log.Message: local0 :: Facility
+ Control.Eff.Log.Message: local1 :: Facility
+ Control.Eff.Log.Message: local2 :: Facility
+ Control.Eff.Log.Message: local3 :: Facility
+ Control.Eff.Log.Message: local4 :: Facility
+ Control.Eff.Log.Message: local5 :: Facility
+ Control.Eff.Log.Message: local6 :: Facility
+ Control.Eff.Log.Message: local7 :: Facility
+ Control.Eff.Log.Message: logAlert :: Member (Logs LogMessage) e => String -> Eff e ()
+ Control.Eff.Log.Message: logAlertFacility :: Facility
+ Control.Eff.Log.Message: logAuditFacility :: Facility
+ Control.Eff.Log.Message: logCritical :: Member (Logs LogMessage) e => String -> Eff e ()
+ Control.Eff.Log.Message: logDebug :: Member (Logs LogMessage) e => String -> Eff e ()
+ Control.Eff.Log.Message: logEmergency :: Member (Logs LogMessage) e => String -> Eff e ()
+ Control.Eff.Log.Message: logError :: Member (Logs LogMessage) e => String -> Eff e ()
+ Control.Eff.Log.Message: logInfo :: Member (Logs LogMessage) e => String -> Eff e ()
+ Control.Eff.Log.Message: logNotice :: Member (Logs LogMessage) e => String -> Eff e ()
+ Control.Eff.Log.Message: logWarning :: Member (Logs LogMessage) e => String -> Eff e ()
+ Control.Eff.Log.Message: logWithSeverity :: Member (Logs LogMessage) e => Severity -> String -> Eff e ()
+ Control.Eff.Log.Message: mailSystem :: Facility
+ Control.Eff.Log.Message: networkNewsSubsystem :: Facility
+ Control.Eff.Log.Message: noticeSeverity :: Severity
+ Control.Eff.Log.Message: ntpSubsystem :: Facility
+ Control.Eff.Log.Message: printLogMessage :: LogMessage -> IO ()
+ Control.Eff.Log.Message: relogAsDebugMessages :: Member (Logs LogMessage) e => Eff (Logs String : e) a -> Eff e a
+ Control.Eff.Log.Message: renderRFC5424 :: LogMessage -> String
+ Control.Eff.Log.Message: sdElementId :: Lens' StructuredDataElement String
+ Control.Eff.Log.Message: sdElementParameters :: Lens' StructuredDataElement [SdParameter]
+ Control.Eff.Log.Message: securityAuthorizationMessages10 :: Facility
+ Control.Eff.Log.Message: securityAuthorizationMessages4 :: Facility
+ Control.Eff.Log.Message: setCallStack :: CallStack -> LogMessage -> LogMessage
+ Control.Eff.Log.Message: systemDaemons :: Facility
+ Control.Eff.Log.Message: userLevelMessages :: Facility
+ Control.Eff.Log.Message: uucpSubsystem :: Facility
+ Control.Eff.Log.Message: warningSeverity :: Severity
- Control.Eff.Concurrent: defaultMainWithLogChannel :: LogChannel String -> Eff (ConsProcess SchedulerIO) () -> IO ()
+ Control.Eff.Concurrent: defaultMainWithLogChannel :: LogChannel LogMessage -> Eff (ConsProcess SchedulerIO) () -> IO ()
- Control.Eff.Concurrent: schedule :: Eff (ConsProcess SchedulerIO) () -> LogChannel String -> IO ()
+ Control.Eff.Concurrent: schedule :: Eff (ConsProcess SchedulerIO) () -> LogChannel LogMessage -> IO ()
- Control.Eff.Concurrent: spawnCallbackObserver :: forall o r q. (SetMember Process (Process q) r, Typeable o, Show (Observation o), Observable o, Member (Logs String) q) => SchedulerProxy q -> (Server o -> Observation o -> Eff (Process q : q) Bool) -> Eff r (Server (CallbackObserver o))
+ Control.Eff.Concurrent: spawnCallbackObserver :: forall o r q. (SetMember Process (Process q) r, Typeable o, Show (Observation o), Observable o, Member (Logs LogMessage) q) => SchedulerProxy q -> (Server o -> Observation o -> Eff (Process q : q) Bool) -> Eff r (Server (CallbackObserver o))
- Control.Eff.Concurrent: spawnLoggingObserver :: forall o r q. (SetMember Process (Process q) r, Typeable o, Show (Observation o), Observable o, Member (Logs String) q) => SchedulerProxy q -> Eff r (Server (CallbackObserver o))
+ Control.Eff.Concurrent: spawnLoggingObserver :: forall o r q. (SetMember Process (Process q) r, Typeable o, Show (Observation o), Observable o, Member (Logs LogMessage) q) => SchedulerProxy q -> Eff r (Server (CallbackObserver o))
- Control.Eff.Concurrent: type HasSchedulerIO r = (HasCallStack, SetMember Lift (Lift IO) r, Member (Logs String) r, Member (Reader SchedulerVar) r)
+ Control.Eff.Concurrent: type HasSchedulerIO r = (HasCallStack, SetMember Lift (Lift IO) r, Member (Logs LogMessage) r, Member (Reader SchedulerVar) r)
- Control.Eff.Concurrent: type SchedulerIO = '[Reader SchedulerVar, Logs String, Lift IO]
+ Control.Eff.Concurrent: type SchedulerIO = '[Reader SchedulerVar, Logs LogMessage, Lift IO]
- Control.Eff.Concurrent.Api.Observer: spawnCallbackObserver :: forall o r q. (SetMember Process (Process q) r, Typeable o, Show (Observation o), Observable o, Member (Logs String) q) => SchedulerProxy q -> (Server o -> Observation o -> Eff (Process q : q) Bool) -> Eff r (Server (CallbackObserver o))
+ Control.Eff.Concurrent.Api.Observer: spawnCallbackObserver :: forall o r q. (SetMember Process (Process q) r, Typeable o, Show (Observation o), Observable o, Member (Logs LogMessage) q) => SchedulerProxy q -> (Server o -> Observation o -> Eff (Process q : q) Bool) -> Eff r (Server (CallbackObserver o))
- Control.Eff.Concurrent.Api.Observer: spawnLoggingObserver :: forall o r q. (SetMember Process (Process q) r, Typeable o, Show (Observation o), Observable o, Member (Logs String) q) => SchedulerProxy q -> Eff r (Server (CallbackObserver o))
+ Control.Eff.Concurrent.Api.Observer: spawnLoggingObserver :: forall o r q. (SetMember Process (Process q) r, Typeable o, Show (Observation o), Observable o, Member (Logs LogMessage) q) => SchedulerProxy q -> Eff r (Server (CallbackObserver o))
- Control.Eff.Concurrent.Process.ForkIOScheduler: defaultMainWithLogChannel :: LogChannel String -> Eff (ConsProcess SchedulerIO) () -> IO ()
+ Control.Eff.Concurrent.Process.ForkIOScheduler: defaultMainWithLogChannel :: LogChannel LogMessage -> Eff (ConsProcess SchedulerIO) () -> IO ()
- Control.Eff.Concurrent.Process.ForkIOScheduler: schedule :: Eff (ConsProcess SchedulerIO) () -> LogChannel String -> IO ()
+ Control.Eff.Concurrent.Process.ForkIOScheduler: schedule :: Eff (ConsProcess SchedulerIO) () -> LogChannel LogMessage -> IO ()
- Control.Eff.Concurrent.Process.ForkIOScheduler: type HasSchedulerIO r = (HasCallStack, SetMember Lift (Lift IO) r, Member (Logs String) r, Member (Reader SchedulerVar) r)
+ Control.Eff.Concurrent.Process.ForkIOScheduler: type HasSchedulerIO r = (HasCallStack, SetMember Lift (Lift IO) r, Member (Logs LogMessage) r, Member (Reader SchedulerVar) r)
- Control.Eff.Concurrent.Process.ForkIOScheduler: type SchedulerIO = '[Reader SchedulerVar, Logs String, Lift IO]
+ Control.Eff.Concurrent.Process.ForkIOScheduler: type SchedulerIO = '[Reader SchedulerVar, Logs LogMessage, Lift IO]
- Control.Eff.Concurrent.Process.SingleThreadedScheduler: defaultMain :: HasCallStack => Eff '[Process '[Logs String, Lift IO], Logs String, Lift IO] () -> IO ()
+ Control.Eff.Concurrent.Process.SingleThreadedScheduler: defaultMain :: HasCallStack => Eff '[Process '[Logs LogMessage, Lift IO], Logs LogMessage, Lift IO] () -> IO ()
- Control.Eff.Concurrent.Process.SingleThreadedScheduler: type LoggingAndIo = '[Logs String, Lift IO]
+ Control.Eff.Concurrent.Process.SingleThreadedScheduler: type LoggingAndIo = '[Logs LogMessage, Lift IO]

Files

ChangeLog.md view
@@ -1,11 +1,17 @@ # Changelog for extensible-effects-concurrent ++## 0.6.0++- Rewrite Logging+- Improve Experimental Nix expressions+ ## 0.5.0.0  - Switch to `extensible-effects` version `3.1.0.0` - Bump to stackage LTS-12.9 - Add `Control.Eff.Log.MessageFactory`-- Add `Control.Eff.Log.Syslog`+- Add `Control.Eff.Log.Message`  ## 0.4.0.0 
extensible-effects-concurrent.cabal view
@@ -1,12 +1,12 @@ name:           extensible-effects-concurrent-version:        0.5.0.1+version:        0.6.0 description:    Please see the README on GitHub at <https://github.com/sheyll/extensible-effects-concurrent#readme> synopsis:       Message passing concurrency as extensible-effect homepage:       https://github.com/sheyll/extensible-effects-concurrent#readme bug-reports:    https://github.com/sheyll/extensible-effects-concurrent/issues-author:         Sven Heyll                +author:         Sven Heyll maintainer:     sven.heyll@gmail.com-category:       Concurrency                +category:       Concurrency copyright:      Copyright Sven Heyll license:        BSD3 license-file:   LICENSE@@ -57,8 +57,9 @@                   Control.Eff.Loop,                   Control.Eff.ExceptionExtra,                   Control.Eff.Log,-                  Control.Eff.Log.Syslog,-                  Control.Eff.Log.MessageFactory,+                  Control.Eff.Log.Channel,+                  Control.Eff.Log.Handler,+                  Control.Eff.Log.Message,                   Control.Eff.Concurrent,                   Control.Eff.Concurrent.Api,                   Control.Eff.Concurrent.Api.Client,
src/Control/Eff/Concurrent/Api/Observer.hs view
@@ -22,21 +22,22 @@   , CallbackObserver   , spawnCallbackObserver   , spawnLoggingObserver-  ) where+  )+where -import GHC.Stack-import Data.Dynamic-import Data.Set (Set)-import qualified Data.Set as Set-import Control.Eff-import Control.Eff.Concurrent.Process-import Control.Eff.Concurrent.Api-import Control.Eff.Concurrent.Api.Client-import Control.Eff.Concurrent.Api.Server-import Control.Eff.Log-import Control.Eff.State.Strict-import Control.Lens-import Control.Monad+import           GHC.Stack+import           Data.Dynamic+import           Data.Set                       ( Set )+import qualified Data.Set                      as Set+import           Control.Eff+import           Control.Eff.Concurrent.Process+import           Control.Eff.Concurrent.Api+import           Control.Eff.Concurrent.Api.Client+import           Control.Eff.Concurrent.Api.Server+import           Control.Eff.Log+import           Control.Eff.State.Strict+import           Control.Lens+import           Control.Monad  -- | An 'Api' index that support observation of the -- another 'Api' that is 'Observable'.@@ -57,30 +58,33 @@   forgetObserverMessage :: SomeObserver o -> Api o 'Asynchronous  -- | Send an 'Observation' to an 'Observer'-notifyObserver :: ( SetMember Process (Process q) r-                 , Observable o-                 , Observer p o-                 , HasCallStack-                 )-               => SchedulerProxy q -> Server p -> Server o -> Observation o -> Eff r ()+notifyObserver+  :: (SetMember Process (Process q) r, Observable o, Observer p o, HasCallStack)+  => SchedulerProxy q+  -> Server p+  -> Server o+  -> Observation o+  -> Eff r () notifyObserver px observer observed observation =   cast px observer (observationMessage observed observation)  -- | Send the 'registerObserverMessage'-registerObserver :: ( SetMember Process (Process q) r-                 , Observable o-                 , Observer p o-                 , HasCallStack-                 )-               => SchedulerProxy q -> Server p -> Server o -> Eff r ()+registerObserver+  :: (SetMember Process (Process q) r, Observable o, Observer p o, HasCallStack)+  => SchedulerProxy q+  -> Server p+  -> Server o+  -> Eff r () registerObserver px observer observed =   cast px observed (registerObserverMessage (SomeObserver observer))  -- | Send the 'forgetObserverMessage'-forgetObserver :: ( SetMember Process (Process q) r-                , Observable o-                , Observer p o)-              => SchedulerProxy q -> Server p -> Server o -> Eff r ()+forgetObserver+  :: (SetMember Process (Process q) r, Observable o, Observer p o)+  => SchedulerProxy q+  -> Server p+  -> Server o+  -> Eff r () forgetObserver px observer observed =   cast px observed (forgetObserverMessage (SomeObserver observer)) @@ -101,15 +105,13 @@     o1 == o2  -- | Send an 'Observation' to 'SomeObserver'.-notifySomeObserver :: ( SetMember Process (Process q) r-                     , Observable o-                     , HasCallStack-                     )-                   => SchedulerProxy q-                   -> Server o-                   -> Observation o-                   -> SomeObserver o-                   -> Eff r ()+notifySomeObserver+  :: (SetMember Process (Process q) r, Observable o, HasCallStack)+  => SchedulerProxy q+  -> Server o+  -> Observation o+  -> SomeObserver o+  -> Eff r () notifySomeObserver px observed observation (SomeObserver observer) =   notifyObserver px observer observed observation @@ -130,27 +132,34 @@ -- | Add an 'Observer' to the 'Observers' managed by 'manageObservers'. addObserver   :: ( SetMember Process (Process q) r-    , Member (State (Observers o)) r-    , Observable o)-  => SomeObserver o -> Eff r ()+     , Member (State (Observers o)) r+     , Observable o+     )+  => SomeObserver o+  -> Eff r () addObserver = modify . over observers . Set.insert  -- | Delete an 'Observer' from the 'Observers' managed by 'manageObservers'. removeObserver-  ::  ( SetMember Process (Process q) r-    , Member (State (Observers o)) r-    , Observable o)-  => SomeObserver o -> Eff r ()+  :: ( SetMember Process (Process q) r+     , Member (State (Observers o)) r+     , Observable o+     )+  => SomeObserver o+  -> Eff r () removeObserver = modify . over observers . Set.delete   -- | Send an 'Observation' to all 'SomeObserver's in the 'Observers' state. notifyObservers   :: forall o r q-    . ( Observable o-      , SetMember Process (Process q) r-      , Member (State (Observers o)) r)-  => SchedulerProxy q -> Observation o -> Eff r ()+   . ( Observable o+     , SetMember Process (Process q) r+     , Member (State (Observers o)) r+     )+  => SchedulerProxy q+  -> Observation o+  -> Eff r () notifyObservers px observation = do   me <- asServer @o <$> self px   os <- view observers <$> get@@ -173,29 +182,29 @@ -- | Start a new process for an 'Observer' that schedules -- all observations to an effectful callback. spawnCallbackObserver-  :: forall o r q .-  ( SetMember Process (Process q) r-  , Typeable o-  , Show (Observation o)-  , Observable o-  , Member (Logs String) q)+  :: forall o r q+   . ( SetMember Process (Process q) r+     , Typeable o+     , Show (Observation o)+     , Observable o+     , Member (Logs LogMessage) q+     )   => SchedulerProxy q   -> (Server o -> Observation o -> Eff (Process q ': q) Bool)   -> Eff r (Server (CallbackObserver o)) spawnCallbackObserver px onObserve =   asServer @(CallbackObserver o)-  <$>-  (spawn @r @q $ do-      let loopUntil =-            serve px-            (ApiHandler @(CallbackObserver o)-              (handleCast loopUntil)-              (unhandledCallError px)-              (defaultTermination px))-      loopUntil)+    <$> (spawn @r @q $ do+          let loopUntil = serve+                px+                (ApiHandler @(CallbackObserver o) (handleCast loopUntil)+                                                  (unhandledCallError px)+                                                  (defaultTermination px)+                )+          loopUntil+        )  where-   handleCast k (CbObserved fromSvr v) =-     onObserve fromSvr v >>= flip when k+  handleCast k (CbObserved fromSvr v) = onObserve fromSvr v >>= flip when k  -- | Use 'spawnCallbackObserver' to create a universal logging observer, -- using the 'Show' instance of the 'Observation'.@@ -204,14 +213,15 @@ -- -- @since 0.3.0.0 spawnLoggingObserver-  :: forall o r q .-  ( SetMember Process (Process q) r-  , Typeable o-  , Show (Observation o)-  , Observable o-  , Member (Logs String) q)+  :: forall o r q+   . ( SetMember Process (Process q) r+     , Typeable o+     , Show (Observation o)+     , Observable o+     , Member (Logs LogMessage) q+     )   => SchedulerProxy q   -> Eff r (Server (CallbackObserver o))-spawnLoggingObserver px =-  spawnCallbackObserver px-  (\s o -> logMsg (show s ++ " OBSERVED: " ++ show o) >> return True)+spawnLoggingObserver px = spawnCallbackObserver+  px+  (\s o -> logDebug (show s ++ " OBSERVED: " ++ show o) >> return True)
src/Control/Eff/Concurrent/Examples.hs view
@@ -1,13 +1,13 @@ -- | A complete example for the library module Control.Eff.Concurrent.Examples where -import GHC.Stack-import Control.Eff-import Control.Eff.Lift-import Control.Monad-import Data.Dynamic-import Control.Eff.Concurrent-import qualified Control.Exception as Exc+import           GHC.Stack+import           Control.Eff+import           Control.Eff.Lift+import           Control.Monad+import           Data.Dynamic+import           Control.Eff.Concurrent+import qualified Control.Exception             as Exc  data TestApi   deriving Typeable@@ -30,100 +30,100 @@ main = defaultMain (example forkIoScheduler)  mainProcessSpawnsAChildAndReturns-  :: ( HasCallStack, SetMember Process (Process q) r)-  => SchedulerProxy q -> Eff r ()-mainProcessSpawnsAChildAndReturns px =-  void (spawn (void (receiveMessage px)))+  :: (HasCallStack, SetMember Process (Process q) r)+  => SchedulerProxy q+  -> Eff r ()+mainProcessSpawnsAChildAndReturns px = void (spawn (void (receiveMessage px)))  example   :: ( HasCallStack-    , SetMember Process (Process q) r-    , Member (Logs String) r-    , Member (Logs String) q-    , SetMember Lift (Lift IO) q-    , SetMember Lift (Lift IO) r)-  => SchedulerProxy q -> Eff r ()+     , SetMember Process (Process q) r+     , Member (Logs LogMessage) r+     , Member (Logs LogMessage) q+     , SetMember Lift (Lift IO) q+     , SetMember Lift (Lift IO) r+     )+  => SchedulerProxy q+  -> Eff r () example px = do   me <- self px-  logMsg ("I am " ++ show me)+  logInfo ("I am " ++ show me)   server <- asServer @TestApi <$> spawn testServerLoop-  logMsg ("Started server " ++ show server)+  logInfo ("Started server " ++ show server)   let go = do         x <- lift getLine         case x of-          ('k':rest) -> do+          ('k' : rest) -> do             callRegistered px (TerminateError rest)             go-          ('s':_) -> do+          ('s' : _) -> do             callRegistered px Terminate             go-          ('c':_) -> do+          ('c' : _) -> do             castRegistered px (Shout x)             go-          ('r':rest) -> do-            void (replicateM-                  (read rest)-                  (castRegistered px (Shout x)))+          ('r' : rest) -> do+            void (replicateM (read rest) (castRegistered px (Shout x)))             go-          ('q':_) ->-            logMsg "Done."-          _ ->-            do res <- ignoreProcessError px (callRegistered px (SayHello x))-               logMsg ("Result: " ++ show res)-               go+          ('q' : _) -> logInfo "Done."+          _         -> do+            res <- ignoreProcessError px (callRegistered px (SayHello x))+            logInfo ("Result: " ++ show res)+            go   registerServer server go  testServerLoop-  :: forall r .-    (HasCallStack-    , Member (Logs String) r-    , SetMember Lift (Lift IO) r)+  :: forall r+   . (HasCallStack, Member (Logs LogMessage) r, SetMember Lift (Lift IO) r)   => Eff (Process r ': r) ()-testServerLoop =-    serve px $ ApiHandler handleCast handleCall handleTerminate-  where-    px :: SchedulerProxy r-    px = SchedulerProxy-    handleCast :: Api TestApi 'Asynchronous -> Eff (Process r ': r) ()-    handleCast (Shout x) = do-      me <- self px-      logMsg (show me ++ " Shouting: " ++ x)-    handleCall :: Api TestApi ('Synchronous x) -> (x -> Eff (Process r ': r) ()) -> Eff (Process r ': r) ()-    handleCall (SayHello "e1") _reply = do-      me <- self px-      logMsg (show me ++ " raising an error")-      raiseError px "No body loves me... :,("-    handleCall (SayHello "e2") _reply = do-      me <- self px-      logMsg (show me ++ " throwing a MyException ")-      lift (Exc.throw MyException)-    handleCall (SayHello "self") reply = do-      me <- self px-      logMsg (show me ++ " casting to self")-      cast px (asServer @TestApi me) (Shout "from me")-      void (reply False)-    handleCall (SayHello "die") reply = do-      me <- self px-      logMsg (show me ++ " throwing and catching ")-      catchRaisedError px-        (\ er -> logMsg ("WOW: " ++ show er ++ " - No. This is wrong!"))-        (raiseError px "No body loves me... :,(")-      void (reply True)-    handleCall (SayHello x) reply = do-      me <- self px-      logMsg (show me ++ " Got Hello: " ++ x)-      void (reply (length x > 3))-    handleCall Terminate reply = do-      me <- self px-      logMsg (show me ++ " exiting")-      void (reply ())-      exitNormally px-    handleCall (TerminateError msg) reply = do-      me <- self px-      logMsg (show me ++ " exiting with error: " ++ msg)-      void (reply ())-      exitWithError px msg-    handleTerminate msg = do-      me <- self px-      logMsg (show me ++ " is exiting: " ++ show msg)-      maybe (exitNormally px) (exitWithError px) msg+testServerLoop = serve px $ ApiHandler handleCast handleCall handleTerminate+ where+  px :: SchedulerProxy r+  px = SchedulerProxy+  handleCast :: Api TestApi 'Asynchronous -> Eff (Process r ': r) ()+  handleCast (Shout x) = do+    me <- self px+    logInfo (show me ++ " Shouting: " ++ x)+  handleCall+    :: Api TestApi ( 'Synchronous x)+    -> (x -> Eff (Process r ': r) ())+    -> Eff (Process r ': r) ()+  handleCall (SayHello "e1") _reply = do+    me <- self px+    logInfo (show me ++ " raising an error")+    raiseError px "No body loves me... :,("+  handleCall (SayHello "e2") _reply = do+    me <- self px+    logInfo (show me ++ " throwing a MyException ")+    lift (Exc.throw MyException)+  handleCall (SayHello "self") reply = do+    me <- self px+    logInfo (show me ++ " casting to self")+    cast px (asServer @TestApi me) (Shout "from me")+    void (reply False)+  handleCall (SayHello "die") reply = do+    me <- self px+    logInfo (show me ++ " throwing and catching ")+    catchRaisedError+      px+      (\er -> logInfo ("WOW: " ++ show er ++ " - No. This is wrong!"))+      (raiseError px "No body loves me... :,(")+    void (reply True)+  handleCall (SayHello x) reply = do+    me <- self px+    logInfo (show me ++ " Got Hello: " ++ x)+    void (reply (length x > 3))+  handleCall Terminate reply = do+    me <- self px+    logInfo (show me ++ " exiting")+    void (reply ())+    exitNormally px+  handleCall (TerminateError msg) reply = do+    me <- self px+    logInfo (show me ++ " exiting with error: " ++ msg)+    void (reply ())+    exitWithError px msg+  handleTerminate msg = do+    me <- self px+    logInfo (show me ++ " is exiting: " ++ show msg)+    maybe (exitNormally px) (exitWithError px) msg
src/Control/Eff/Concurrent/Examples2.hs view
@@ -36,14 +36,14 @@   forgetObserverMessage = UnobserveCounter  logCounterObservations-  :: (SetMember Process (Process q) r, Member (Logs String) q)+  :: (SetMember Process (Process q) r, Member (Logs LogMessage) q)   => SchedulerProxy q   -> Eff r (Server (CallbackObserver Counter)) logCounterObservations px = spawnCallbackObserver   px   (\fromSvr msg -> do     me <- self px-    logMsg (show me ++ " observed on: " ++ show fromSvr ++ ": " ++ show msg)+    logInfo (show me ++ " observed on: " ++ show fromSvr ++ ": " ++ show msg)     return True   ) @@ -51,7 +51,7 @@   :: forall r q    . ( Member (State (Observers Counter)) r      , Member (State Integer) r-     , Member (Logs String) r+     , Member (Logs LogMessage) r      , SetMember Process (Process q) r      )   => SchedulerProxy q@@ -64,14 +64,14 @@   handleCast (ObserveCounter   o) = addObserver o   handleCast (UnobserveCounter o) = removeObserver o   handleCast Inc                  = do-    logMsg "Inc"+    logInfo "Inc"     modify (+ (1 :: Integer))     currentCount <- get     notifyObservers px (CountChanged currentCount)   handleCall :: Api Counter ( 'Synchronous x) -> (x -> Eff r ()) -> Eff r ()   handleCall Cnt reply = do     c <- get-    logMsg ("Cnt is " ++ show c)+    logInfo ("Cnt is " ++ show c)     reply c  -- * Second API@@ -87,7 +87,7 @@ pocketCalcHandler   :: forall r q    . ( Member (State Integer) r-     , Member (Logs String) r+     , Member (Logs LogMessage) r      , SetMember Process (Process q) r      )   => SchedulerProxy q@@ -98,21 +98,21 @@  where   handleCast :: Api PocketCalc 'Asynchronous -> Eff r ()   handleCast (AAdd x) = do-    logMsg ("AsyncAdd " ++ show x)+    logInfo ("AsyncAdd " ++ show x)     modify (+ x)     c <- get @Integer-    logMsg ("Accumulator is " ++ show c)+    logInfo ("Accumulator is " ++ show c)   handleCall :: Api PocketCalc ( 'Synchronous x) -> (x -> Eff r ()) -> Eff r ()   handleCall (Add x) reply = do-    logMsg ("Add " ++ show x)+    logInfo ("Add " ++ show x)     modify (+ x)     c <- get-    logMsg ("Accumulator is " ++ show c)+    logInfo ("Accumulator is " ++ show c)     reply c  serverLoop   :: forall r q-   . (Member (Logs String) r, SetMember Process (Process q) r)+   . (Member (Logs LogMessage) r, SetMember Process (Process q) r)   => SchedulerProxy q   -> Eff r () serverLoop px = evalState @Integer@@ -124,8 +124,8 @@  -- ** Counter client counterExample-  :: ( Member (Logs String) r-     , Member (Logs String) q+  :: ( Member (Logs LogMessage) r+     , Member (Logs LogMessage) q      , SetMember Process (Process q) r      )   => SchedulerProxy q@@ -133,7 +133,7 @@ counterExample px = do   let cnt sv = do         r <- call px sv Cnt-        logMsg (show sv ++ " " ++ show r)+        logInfo (show sv ++ " " ++ show r)   pid1 <- spawn (serverLoop px)   pid2 <- spawn (serverLoop px)   let cntServer1  = asServer @Counter pid1
src/Control/Eff/Concurrent/Process/ForkIOScheduler.hs view
@@ -40,15 +40,18 @@ import           Control.Eff.Lift import           Control.Eff.Log import           Control.Eff.Reader.Strict     as Reader+import           Control.Monad.Log              ( runLoggingT ) import           Control.Lens import           Control.Monad                  ( when                                                 , void                                                 , join+                                                , (>=>)                                                 ) import qualified Control.Monad.State           as Mtl import           Data.Dynamic import           Data.Map                       ( Map ) import qualified Data.Map                      as Map+import           Text.Printf import           Data.String  -- | Information about a process, needed to implement 'MessagePassing' and@@ -73,7 +76,7 @@                           , _processTable :: Map ProcessId ProcessInfo                           , _threadIdTable :: Map ProcessId ThreadId                           , _schedulerShuttingDown :: Bool-                          , _logChannel :: LogChannel String+                          , _logChannel :: LogChannel LogMessage                           }  makeLenses ''Scheduler@@ -107,14 +110,14 @@ -- See SchedulerIO type HasSchedulerIO r = ( HasCallStack                         , SetMember Lift (Lift IO) r-                        , Member (Logs String) r+                        , Member (Logs LogMessage) r                         , Member (Reader SchedulerVar) r)  -- | The concrete list of 'Eff'ects for this scheduler implementation. -- See HasSchedulerIO type SchedulerIO =               '[ Reader SchedulerVar-               , Logs String+               , Logs LogMessage                , Lift IO                ] @@ -125,15 +128,15 @@ -- | This is the main entry point to running a message passing concurrency -- application. This function takes a 'Process' on top of the 'SchedulerIO' -- effect and a 'LogChannel' for concurrent logging.-schedule :: Eff (ConsProcess SchedulerIO) () -> LogChannel String -> IO ()+schedule :: Eff (ConsProcess SchedulerIO) () -> LogChannel LogMessage -> IO () schedule e logC = void $ withNewSchedulerState $ \schedulerStateVar -> do   pidVar <- newEmptyTMVarIO   scheduleProcessWithShutdownAction schedulerStateVar pidVar $ do     mt <- lift myThreadId     mp <- lift (atomically (readTMVar pidVar))-    logMsg (show mp ++ " main process started in thread " ++ show mt)+    logInfo (show mp ++ " main process started in thread " ++ show mt)     e-    logMsg (show mp ++ " main process returned")+    logInfo (show mp ++ " main process returned")  where   withNewSchedulerState :: (SchedulerVar -> IO a) -> IO a   withNewSchedulerState mainProcessAction = do@@ -144,7 +147,7 @@    where     myPid = 1     tearDownScheduler myTId v = do-      logChannelPutIO logC (show myTId ++ " begin scheduler tear down")+      logChannelPutIO logC (debugMessage "begin scheduler tear down")       sch <-         (atomically           (do@@ -156,12 +159,13 @@         )       logChannelPutIO         logC-        (  show myTId-        ++ " killing "-        ++ let ts = (sch ^.. threadIdTable . traversed)-           in  if length ts > 100-                 then show (length ts) ++ " threads"-                 else show ts+        (debugMessage+          (  "killing "+          ++ let ts = (sch ^.. threadIdTable . traversed)+             in  if length ts > 100+                   then show (length ts) ++ " threads"+                   else show ts+          )         )       imapM_ (killProcThread myTId) (sch ^. threadIdTable)       Concurrent.yield@@ -177,8 +181,7 @@                   .  to Map.null           STM.check allThreadsDead         )-      logChannelPutIO logC "all threads dead"-+      logChannelPutIO logC (infoMessage "all threads dead")      killProcThread myTId _pid tid = when (myTId /= tid) (killThread tid) @@ -187,18 +190,17 @@ defaultMain :: Eff (ConsProcess SchedulerIO) () -> IO () defaultMain c = runLoggingT   (logChannelBracket 128-                     (Just "~~~~~~ main process started")-                     (Just "====== main process exited")+                     (Just (infoMessage "main process started"))                      (schedule c)   )-  (print :: String -> IO ())+  (printLogMessage :: LogMessage -> IO ())  -- | Start the message passing concurrency system then execute a 'Process' on -- top of 'SchedulerIO' effect. All logging is sent to standard output. defaultMainWithLogChannel-  :: LogChannel String -> Eff (ConsProcess SchedulerIO) () -> IO ()+  :: LogChannel LogMessage -> Eff (ConsProcess SchedulerIO) () -> IO () defaultMainWithLogChannel logC c = closeLogChannelAfter-  (Just (fromString "====== main process exited"))+  (Just (fromString "main process exited"))   logC   (schedule c logC) @@ -210,11 +212,10 @@ scheduleProcessWithShutdownAction schedulerVar pidVar procAction = do   cleanupVar <- newEmptyTMVarIO   logC       <- getLogChannelIO schedulerVar-  mTid       <- myThreadId   eeres      <- Exc.try (runProcEffects cleanupVar logC)   let eres = join eeres-  getAndExecCleanup cleanupVar eres logC mTid-  logChannelPutIO logC (show mTid ++ " <~< process cleanup finished")+  getAndExecCleanup cleanupVar eres logC+  logChannelPutIO logC =<< debugMessageIO "process cleanup finished"   return eres  where @@ -241,37 +242,44 @@             STM.putTMVar pidVar pid           )         )-      mTid <- lift myThreadId-      logMsg (show mTid ++ " >~> begin process " ++ show pid)-      procAction-  getAndExecCleanup cleanupVar eres lc mt = do+      interceptLogging+          (logMsg . over lmMessage (printf "[PID %7i] %s" (toInteger pid)))+        $ do+            logDebug "begin process"+            procAction+  getAndExecCleanup cleanupVar eres lc = do     mcleanup <- atomically (STM.tryTakeTMVar cleanupVar)     traverse_ execCleanup mcleanup    where     execCleanup ca = do       runCleanUpAction ca-      logChannelPutIO lc $ show mt ++ case eres of+      logChannelPutIO lc =<< case eres of         Left se -> case Exc.fromException se of-          Nothing -> " process caught exception: " ++ Exc.displayException se-          Just schedulerErr ->-            (case schedulerErr of-                ProcessShuttingDown  -> " process shutdown"-                ProcessExitError   m -> " process exited with error: " ++ show m-                ProcessRaisedError m -> " process raised error: " ++ show m-                _ -> " scheduler error: " ++ show schedulerErr-              )-              ++ " - full exception message: "-              ++ Exc.displayException se--        Right _ -> " process function returned"+          Nothing -> errorMessageIO+            ("process caught exception: " ++ Exc.displayException se)+          Just schedulerErr+            -> let exceptionMsg =+                     " - full exception message: " ++ Exc.displayException se+               in+                 case schedulerErr of+                   ProcessShuttingDown -> debugMessageIO "process shutdown"+                   ProcessExitError m  -> errorMessageIO+                     ("process exited with error: " ++ show m ++ exceptionMsg)+                   ProcessRaisedError m -> errorMessageIO+                     ("process raised error: " ++ show m ++ exceptionMsg)+                   _ ->+                     errorMessageIO+                       ("scheduler error: " ++ show schedulerErr ++ exceptionMsg+                       )+        Right _ -> debugMessageIO "process function returned"  -getLogChannel :: HasSchedulerIO r => Eff r (LogChannel String)+getLogChannel :: HasSchedulerIO r => Eff r (LogChannel LogMessage) getLogChannel = do   s <- getSchedulerVar   lift (getLogChannelIO s) -getLogChannelIO :: SchedulerVar -> IO (LogChannel String)+getLogChannelIO :: SchedulerVar -> IO (LogChannel LogMessage) getLogChannelIO s = view logChannel <$> readTVarIO (fromSchedulerVar s)  overProcessInfo@@ -432,7 +440,7 @@   ShutdownAction (forall a . Either SchedulerError () -> IO a)  invokeShutdownAction-  :: (HasCallStack, SetMember Lift (Lift IO) r, Member (Logs String) r)+  :: (HasCallStack, SetMember Lift (Lift IO) r, Member (Logs LogMessage) r)   => ShutdownAction   -> Either SchedulerError ()   -> Eff r a@@ -488,13 +496,16 @@                   (return . (maybe (show pid) show))      case didWork of-      Right (_pinfo, True) -> return ()-      Right (pinfo, False) ->-        logChannelPutIO lc ("queue already destroyed: " ++ show pinfo)+      Right (_pinfo, True ) -> return ()+      Right (pinfo , False) -> logChannelPutIO lc+        =<< errorMessageIO ("queue already destroyed: " ++ show pinfo)       Left (e :: Exc.SomeException) ->         getCause-          >>= logChannelPutIO lc-          .   (("failed to destroy queue: " ++ show e ++ " ") ++)+          >>= (   ( errorMessageIO+                  . (("failed to destroy queue: " ++ show e ++ " ") ++)+                  )+              >=> logChannelPutIO lc+              )   overScheduler
src/Control/Eff/Concurrent/Process/SingleThreadedScheduler.hs view
@@ -21,7 +21,9 @@ import           Control.Lens            hiding ( (|>)                                                 , Empty                                                 )-import           Control.Monad                  ( void )+import           Control.Monad                  ( void+                                                , (>=>)+                                                ) import           Control.Monad.IO.Class import qualified Data.Sequence                 as Seq import           Data.Sequence                  ( Seq(..) )@@ -72,7 +74,7 @@   => (l -> m ())   -> Eff (ConsProcess '[Logs l, Lift m]) a   -> m (Either String a)-scheduleIOWithLogging handleLog = scheduleIO (handleLogsWith handleLog)+scheduleIOWithLogging handleLog = scheduleIO (handleLogsLifted handleLog)  -- | Handle the 'Process' effect, as well as all lower effects using an effect handler function. --@@ -262,7 +264,7 @@ -- | The concrete list of 'Eff'ects for running this pure scheduler on @IO@ and -- with string logging. type LoggingAndIo =-              '[ Logs String+              '[ Logs LogMessage                , Lift IO                ] @@ -274,8 +276,10 @@ -- @String@ effects. defaultMain   :: HasCallStack-  => Eff '[Process '[Logs String, Lift IO], Logs String, Lift IO] ()+  => Eff '[Process '[Logs LogMessage, Lift IO], Logs LogMessage, Lift IO] ()   -> IO ()-defaultMain e = void $ runLift $ handleLogsWithLoggingTHandler-  (scheduleMonadIOEff e)-  ($! putStrLn)+defaultMain =+  void+    . runLift+    . handleLogsWithLoggingTHandler ($ printLogMessage)+    . scheduleMonadIOEff
src/Control/Eff/Log.hs view
@@ -1,337 +1,11 @@ -- | A logging effect based on 'Control.Monad.Log.MonadLog'. module Control.Eff.Log-  (-    -- * Logging Effect-    Logs(..)-  , logMsg-  , interceptLogging-  , foldLogMessages-  , module ExtLog-  , captureLogs-  , ignoreLogs-  , handleLogsWith-  , handleLogsWithLoggingTHandler-    -- * Concurrent Logging-  , LogChannel()-  , logToChannel-  , noLogger-  , forkLogger-  , filterLogChannel-  , joinLogChannel-  , killLogChannel-  , closeLogChannelAfter-  , logChannelBracket-  , logChannelPutIO-  -- ** Internals-  , JoinLogChannelException()-  , KillLogChannelException()+  ( module Control.Eff.Log.Handler+  , module Control.Eff.Log.Channel+  , module Control.Eff.Log.Message   ) where -import           Control.Concurrent-import           Control.Concurrent.STM-import           Control.DeepSeq-import           Control.Eff                   as Eff-import           Control.Eff.Extend            as Eff-import           Control.Exception              ( bracket )-import qualified Control.Exception             as Exc-import           Control.Monad                  ( void-                                                , when-                                                , unless-                                                )-import           Control.Monad.Log             as ExtLog-                                         hiding ( )-import           Control.Monad.Trans.Control-import qualified Control.Eff.Lift              as Eff-import qualified Control.Monad.Log             as Log-import           Data.Foldable                  ( traverse_ )-import           Data.Kind                      ( )-import           Data.Sequence                  ( Seq() )-import qualified Data.Sequence                 as Seq-import           Data.String-import           Data.Typeable------ | Logging effect type, parameterized by a log message type.-data Logs message a where-  LogMsg :: message -> Logs message ()---- | Log a message.-logMsg :: Member (Logs m) r => m -> Eff r ()-logMsg msg = send (LogMsg msg)---- | Change, add or remove log messages and perform arbitrary actions upon--- intercepting a log message.------ Requirements:------   * All log meta data for typical prod code can be added without---     changing much of the code------   * Add timestamp to a log messages of a sub-computation.------   * Write some messages to a file.------   * Log something extra, e.g. runtime memory usage in load tests------ Approach: Install a callback that sneaks into to log message--- sending/receiving, to intercept the messages and execute some code and then--- return a new message.-interceptLogging-  :: forall r m a . Member (Logs m) r => (m -> Eff r ()) -> Eff r a -> Eff r a-interceptLogging interceptor = interpose return go- where-  go :: Member (Logs m) r => Logs m x -> (Arr r x y) -> Eff r y-  go (LogMsg m) k = do-    interceptor m-    k ()---- | Intercept logging to change, add or remove log messages.------ This is without side effects, hence faster than 'interceptLogging'.-foldLogMessages-  :: forall r m a f-   . (Foldable f, Member (Logs m) r)-  => (m -> f m)-  -> Eff r a-  -> Eff r a-foldLogMessages interceptor = interpose return go- where-  go :: Member (Logs m) r => Logs m x -> (Arr r x y) -> Eff r y-  go (LogMsg m) k = do-    traverse_ logMsg (interceptor m)-    k ()---- | Capture all log messages in a 'Seq' (strict).-captureLogs-  :: NFData message => Eff (Logs message ': r) a -> Eff r (a, Seq message)-captureLogs = Eff.handle_relay_s Seq.empty-                                 (\logs result -> return (result, logs))-                                 handleLogs- where-  handleLogs-    :: NFData message-    => Seq message-    -> Logs message x-    -> (Seq message -> Arr r x y)-    -> Eff r y-  handleLogs !logs (LogMsg !m) k = k (force (logs Seq.:|> m)) ()---- | Throw away all log messages.-ignoreLogs :: forall message r a . Eff (Logs message ': r) a -> Eff r a-ignoreLogs = Eff.handle_relay return handleLogs- where-  handleLogs :: Logs m x -> Arr r x y -> Eff r y-  handleLogs (LogMsg _) k = k ()---- | Handle the 'Logs' effect with a monadic call back function (strict).-handleLogsWith-  :: forall m r message a-   . (NFData message, Monad m, SetMember Eff.Lift (Eff.Lift m) r)-  => (message -> m ())-  -> Eff (Logs message ': r) a-  -> Eff r a-handleLogsWith logMessageHandler = Eff.handle_relay return go- where-  go :: Logs message b -> (b -> Eff r c) -> Eff r c-  go (LogMsg m) k = do-    res <- Eff.lift (logMessageHandler (force m))-    k res---- | Handle the 'Logs' effect using 'Log.LoggingT' 'Log.Handler's.-handleLogsWithLoggingTHandler-  :: forall m r message a-   . (Monad m, SetMember Eff.Lift (Eff.Lift m) r)-  => Eff (Logs message ': r) a-  -> (forall b . (Log.Handler m message -> m b) -> m b)-  -> Eff r a-handleLogsWithLoggingTHandler actionThatLogs foldHandler = Eff.handle_relay-  return-  go-  actionThatLogs- where-  go :: Logs message b -> (b -> Eff r c) -> Eff r c-  go (LogMsg m) k = Eff.lift (foldHandler (\doLog -> doLog m)) >>= k---- | A log channel processes logs from the 'Logs' effect by en-queuing them in a--- shared queue read from a seperate processes. A channel can contain log--- message filters.-data LogChannel message =-   FilteredLogChannel (message -> Bool) (LogChannel message)-   -- ^ filter log messages- | DiscardLogs-   -- ^ discard all log messages- | ConcurrentLogChannel-   { fromLogChannel :: TBQueue message-   , _logChannelThread :: ThreadId-   }-   -- ^ send all log messages to a log process---- | Send the log messages to a 'LogChannel'.-logToChannel-  :: forall r message a-   . (SetMember Eff.Lift (Eff.Lift IO) r)-  => LogChannel message-  -> Eff (Logs message ': r) a-  -> Eff r a-logToChannel logChan actionThatLogs = handleLogsWithLoggingTHandler-  actionThatLogs-  (\withHandler -> withHandler (logChannelPutIO logChan))---- | Enqueue a log message into a log channel-logChannelPutIO :: LogChannel message -> message -> IO ()-logChannelPutIO DiscardLogs               _ = return ()-logChannelPutIO (FilteredLogChannel f lc) m = when (f m) (logChannelPutIO lc m)-logChannelPutIO c                         m = atomically $ do-  dropMessage <- isFullTBQueue (fromLogChannel c)-  unless dropMessage (writeTBQueue (fromLogChannel c) m)---- | Create a 'LogChannel' that will discard all messages sent--- via 'forwardLogstochannel' or 'logChannelPutIO'.-noLogger :: LogChannel message-noLogger = DiscardLogs---- | Fork a new process, that applies a monadic action to all log messages sent--- via 'logToChannel' or 'logChannelPutIO'.-forkLogger-  :: forall message-   . (Typeable message, Show message)-  => Int -- ^ Size of the log message input queue. If the queue is full, message-        -- are dropped silently.-  -> (message -> IO ()) -- ^ An IO action to log the messages-  -> Maybe message -- ^ Optional __first__ message to log-  -> IO (LogChannel message)-forkLogger queueLen handle mFirstMsg = do-  msgQ <- atomically-    (do-      tq <- newTBQueue (fromIntegral @Int queueLen)-      mapM_ (writeTBQueue tq) mFirstMsg-      return tq-    )-  thread <- forkFinally (logLoop msgQ) (writeLastLogs msgQ)-  return (ConcurrentLogChannel msgQ thread)- where-  writeLastLogs :: TBQueue message -> Either Exc.SomeException () -> IO ()-  writeLastLogs tq ee = do-    logMessages <- atomically $ flushTBQueue tq-    case ee of-      Right _  -> return ()-      Left  se -> case Exc.fromException se of-        Just (JoinLogChannelException mCloseMsg) -> do-          traverse_ handle logMessages-          traverse_ handle mCloseMsg-        Nothing -> case Exc.fromException se of-          Just (KillLogChannelException mCloseMsg) ->-            traverse_ handle mCloseMsg-          Nothing -> mapM_ handle logMessages--  logLoop :: TBQueue message -> IO ()-  logLoop tq = do-    m <- atomically $ readTBQueue tq-    handle m-    logLoop tq---- | Filter logs sent to a 'LogChannel' using a predicate.-filterLogChannel-  :: (message -> Bool) -> LogChannel message -> LogChannel message-filterLogChannel = FilteredLogChannel---- | Run an action and close a 'LogChannel' created by 'noLogger', 'forkLogger'--- or 'filterLogChannel' afterwards using 'joinLogChannel'. If a--- 'Exc.SomeException' was thrown, the log channel is killed with--- 'killLogChannel', and the exception is re-thrown.-closeLogChannelAfter-  :: (Show message, Typeable message, IsString message)-  => Maybe message-  -> LogChannel message-  -> IO a-  -> IO a-closeLogChannelAfter mGoodbye logC ioAction = do-  res <- closeLogAndRethrow `Exc.handle` ioAction-  closeLogSuccess-  return res- where-  closeLogAndRethrow :: Exc.SomeException -> IO a-  closeLogAndRethrow se = do-    let closeMsg = Just (fromString (Exc.displayException se))-    void $ Exc.try @Exc.SomeException $ killLogChannel closeMsg logC-    Exc.throw se--  closeLogSuccess :: IO ()-  closeLogSuccess = joinLogChannel mGoodbye logC---- | Close a log channel created by e.g. 'forkLogger'. Message already enqueue--- are handled, as well as an optional final message. Subsequent log message--- will not be handled anymore. If the log channel must be closed immediately,--- use 'killLogChannel' instead.-joinLogChannel-  :: (Show message, Typeable message)-  => Maybe message-  -> LogChannel message-  -> IO ()-joinLogChannel _closeLogMessage DiscardLogs = return ()-joinLogChannel Nothing (FilteredLogChannel _f lc) = joinLogChannel Nothing lc-joinLogChannel (Just closeLogMessage) (FilteredLogChannel f lc) =-  if f closeLogMessage-    then joinLogChannel (Just closeLogMessage) lc-    else joinLogChannel Nothing lc-joinLogChannel closeLogMessage (ConcurrentLogChannel _tq thread) =-  throwTo thread (JoinLogChannelException closeLogMessage)---- | Close a log channel quickly, without logging messages already in the queue.--- Subsequent logging requests will not be handled anymore. If the log channel--- must be closed without loosing any messages, use 'joinLogChannel' instead.-killLogChannel-  :: (Show message, Typeable message)-  => Maybe message-  -> LogChannel message-  -> IO ()-killLogChannel _closeLogMessage DiscardLogs = return ()-killLogChannel Nothing (FilteredLogChannel _f lc) = killLogChannel Nothing lc-killLogChannel (Just closeLogMessage) (FilteredLogChannel f lc) =-  if f closeLogMessage-    then killLogChannel (Just closeLogMessage) lc-    else killLogChannel Nothing lc-killLogChannel closeLogMessage (ConcurrentLogChannel _tq thread) =-  throwTo thread (KillLogChannelException closeLogMessage)---- | Internal exception to shutdown a 'LogChannel' process created by--- 'forkLogger'. This exception is handled such that all message already--- en-queued are handled and then an optional final message is written.-newtype JoinLogChannelException m = JoinLogChannelException (Maybe m)-  deriving (Show, Typeable)--instance (Typeable m, Show m) => Exc.Exception (JoinLogChannelException m)---- | Internal exception to **immediately** shutdown a 'LogChannel' process--- created by 'forkLogger', other than 'JoinLogChannelException' the message queue--- will not be flushed, not further messages will be logged, except for the--- optional final message.-newtype KillLogChannelException m = KillLogChannelException (Maybe m)-  deriving (Show, Typeable)--instance (Typeable m, Show m) => Exc.Exception (KillLogChannelException m)---- | Wrap 'LogChannel' creation and destruction around a monad action in--- 'bracket'y manner. This function uses 'joinLogChannel', so en-queued messages--- are flushed on exit. The resulting action is a 'LoggingT' action, which--- is essentially a reader for a log handler function in 'IO'.-logChannelBracket-  :: (Show message, Typeable message)-  => Int -- ^ Size of the log message input queue. If the queue is full, message-        -- are dropped silently.-  -> Maybe message -- ^ Optional __first__ message to log-  -> Maybe message -- ^ Optional __last__ message to log-  -> (LogChannel message -> IO a) -- ^ An IO action that will use the-                                -- 'LogChannel', after the action returns (even-                                -- because of an exception) the log channel is-                                -- destroyed.-  -> LoggingT message IO a-logChannelBracket queueLen mWelcome mGoodbye f = control-  (\runInIO -> do-    let logHandler = void . runInIO . logMessage-    bracket (forkLogger queueLen logHandler mWelcome)-            (joinLogChannel mGoodbye)-            f-  )+import           Control.Eff.Log.Handler+import           Control.Eff.Log.Channel+import           Control.Eff.Log.Message
+ src/Control/Eff/Log/Channel.hs view
@@ -0,0 +1,193 @@+-- | Concurrent Logging+module Control.Eff.Log.Channel+  ( LogChannel()+  , logToChannel+  , noLogger+  , forkLogger+  , filterLogChannel+  , joinLogChannel+  , killLogChannel+  , closeLogChannelAfter+  , logChannelBracket+  , logChannelPutIO+  , JoinLogChannelException()+  , KillLogChannelException()+  )+where++import           Control.Concurrent+import           Control.Concurrent.STM+import           Control.Eff                   as Eff+import           Control.Exception              ( bracket )+import qualified Control.Exception             as Exc+import           Control.Monad                  ( void+                                                , when+                                                , unless+                                                )+import           Control.Monad.Log             as ExtLog+                                         hiding ( )+import           Control.Monad.Trans.Control+import           Control.Eff.Log.Handler+import qualified Control.Eff.Lift              as Eff+import           Data.Foldable                  ( traverse_ )+import           Data.Kind                      ( )+import           Data.String+import           Data.Typeable++-- | A log channel processes logs from the 'Logs' effect by en-queuing them in a+-- shared queue read from a seperate processes. A channel can contain log+-- message filters.+data LogChannel message =+   FilteredLogChannel (message -> Bool) (LogChannel message)+   -- ^ filter log messages+ | DiscardLogs+   -- ^ discard all log messages+ | ConcurrentLogChannel+   { fromLogChannel :: TBQueue message+   , _logChannelThread :: ThreadId+   }+   -- ^ send all log messages to a log process++-- | Send the log messages to a 'LogChannel'.+logToChannel+  :: forall r message a+   . (SetMember Eff.Lift (Eff.Lift IO) r)+  => LogChannel message+  -> Eff (Logs message ': r) a+  -> Eff r a+logToChannel logChan =+  handleLogsWithLoggingTHandler ($ logChannelPutIO logChan)++-- | Enqueue a log message into a log channel+logChannelPutIO :: LogChannel message -> message -> IO ()+logChannelPutIO DiscardLogs               _ = return ()+logChannelPutIO (FilteredLogChannel f lc) m = when (f m) (logChannelPutIO lc m)+logChannelPutIO c                         m = atomically $ do+  dropMessage <- isFullTBQueue (fromLogChannel c)+  unless dropMessage (writeTBQueue (fromLogChannel c) m)++-- | Create a 'LogChannel' that will discard all messages sent+-- via 'forwardLogstochannel' or 'logChannelPutIO'.+noLogger :: LogChannel message+noLogger = DiscardLogs++-- | Fork a new process, that applies a monadic action to all log messages sent+-- via 'logToChannel' or 'logChannelPutIO'.+forkLogger+  :: forall message+   . (Typeable message)+  => Int -- ^ Size of the log message input queue. If the queue is full, message+        -- are dropped silently.+  -> (message -> IO ()) -- ^ An IO action to log the messages+  -> Maybe message -- ^ Optional __first__ message to log+  -> IO (LogChannel message)+forkLogger queueLen handle mFirstMsg = do+  msgQ <- atomically+    (do+      tq <- newTBQueue (fromIntegral @Int queueLen)+      mapM_ (writeTBQueue tq) mFirstMsg+      return tq+    )+  thread <- forkFinally (logLoop msgQ) (writeLastLogs msgQ)+  return (ConcurrentLogChannel msgQ thread)+ where+  writeLastLogs :: TBQueue message -> Either Exc.SomeException () -> IO ()+  writeLastLogs tq ee = do+    logMessages <- atomically $ flushTBQueue tq+    case ee of+      Right _  -> return ()+      Left  se -> case Exc.fromException se of+        Just JoinLogChannelException -> traverse_ handle logMessages+        Nothing                      -> case Exc.fromException se of+          Just KillLogChannelException -> return ()+          Nothing                      -> mapM_ handle logMessages++  logLoop :: TBQueue message -> IO ()+  logLoop tq = do+    m <- atomically $ readTBQueue tq+    handle m+    logLoop tq++-- | Filter logs sent to a 'LogChannel' using a predicate.+filterLogChannel+  :: (message -> Bool) -> LogChannel message -> LogChannel message+filterLogChannel = FilteredLogChannel++-- | Run an action and close a 'LogChannel' created by 'noLogger', 'forkLogger'+-- or 'filterLogChannel' afterwards using 'joinLogChannel'. If a+-- 'Exc.SomeException' was thrown, the log channel is killed with+-- 'killLogChannel', and the exception is re-thrown.+closeLogChannelAfter+  :: (Typeable message, IsString message)+  => Maybe message+  -> LogChannel message+  -> IO a+  -> IO a+closeLogChannelAfter mGoodbye logC ioAction = do+  res <- closeLogAndRethrow `Exc.handle` ioAction+  closeLogSuccess+  return res+ where+  closeLogAndRethrow :: Exc.SomeException -> IO a+  closeLogAndRethrow se = do+    void $ Exc.try @Exc.SomeException $ killLogChannel logC+    Exc.throw se++  closeLogSuccess :: IO ()+  closeLogSuccess = joinLogChannel logC++-- | Close a log channel created by e.g. 'forkLogger'. Message already enqueue+-- are handled. Subsequent log message+-- will not be handled anymore. If the log channel must be closed immediately,+-- use 'killLogChannel' instead.+joinLogChannel :: (Typeable message) => LogChannel message -> IO ()+joinLogChannel DiscardLogs                = return ()+joinLogChannel (FilteredLogChannel _f lc) = joinLogChannel lc+joinLogChannel (ConcurrentLogChannel _tq thread) =+  throwTo thread JoinLogChannelException++-- | Close a log channel quickly, without logging messages already in the queue.+-- Subsequent logging requests will not be handled anymore. If the log channel+-- must be closed without loosing any messages, use 'joinLogChannel' instead.+killLogChannel :: (Typeable message) => LogChannel message -> IO ()+killLogChannel DiscardLogs                = return ()+killLogChannel (FilteredLogChannel _f lc) = killLogChannel lc+killLogChannel (ConcurrentLogChannel _tq thread) =+  throwTo thread KillLogChannelException++-- | Internal exception to shutdown a 'LogChannel' process created by+-- 'forkLogger'. This exception is handled such that all message already+-- en-queued are handled and then an optional final message is written.+data JoinLogChannelException = JoinLogChannelException+  deriving (Show, Typeable)++instance Exc.Exception JoinLogChannelException++-- | Internal exception to **immediately** shutdown a 'LogChannel' process+-- created by 'forkLogger', other than 'JoinLogChannelException' the message queue+-- will not be flushed, not further messages will be logged, except for the+-- optional final message.+data KillLogChannelException = KillLogChannelException+  deriving (Show, Typeable)++instance Exc.Exception KillLogChannelException++-- | Wrap 'LogChannel' creation and destruction around a monad action in+-- 'bracket'y manner. This function uses 'joinLogChannel', so en-queued messages+-- are flushed on exit. The resulting action is a 'LoggingT' action, which+-- is essentially a reader for a log handler function in 'IO'.+logChannelBracket+  :: (Typeable message)+  => Int -- ^ Size of the log message input queue. If the queue is full, message+        -- are dropped silently.+  -> Maybe message -- ^ Optional __first__ message to log+  -> (LogChannel message -> IO a) -- ^ An IO action that will use the+                                -- 'LogChannel', after the action returns (even+                                -- because of an exception) the log channel is+                                -- destroyed.+  -> LoggingT message IO a+logChannelBracket queueLen mWelcome f = control+  (\runInIO -> do+    let logHandler = void . runInIO . logMessage+    bracket (forkLogger queueLen logHandler mWelcome) joinLogChannel f+  )
+ src/Control/Eff/Log/Handler.hs view
@@ -0,0 +1,137 @@+-- | A logging effect based on 'Control.Monad.Log.MonadLog'.+module Control.Eff.Log.Handler+  (+    -- * Logging Effect+    Logs(..)+  , logMsg+  , interceptLogging+  , foldLogMessages+  , relogAsString+  , captureLogs+  , ignoreLogs+  , handleLogsWith+  , handleLogsLifted+  , handleLogsWithLoggingTHandler+  )+where++import           Control.DeepSeq+import           Control.Eff                   as Eff+import           Control.Eff.Extend            as Eff+import qualified Control.Eff.Lift              as Eff+import qualified Control.Monad.Log             as Log+import           Data.Foldable                  ( traverse_ )+import           Data.Kind                      ( )+import           Data.Sequence                  ( Seq() )+import qualified Data.Sequence                 as Seq++-- | Logging effect type, parameterized by a log message type.+data Logs message a where+  LogMsg :: message -> Logs message ()++-- | Log a message.+logMsg :: Member (Logs m) r => m -> Eff r ()+logMsg = send . LogMsg++-- | Change, add or remove log messages and perform arbitrary actions upon+-- intercepting a log message.+--+-- Requirements:+--+--   * All log meta data for typical prod code can be added without+--     changing much of the code+--+--   * Add timestamp to a log messages of a sub-computation.+--+--   * Write some messages to a file.+--+--   * Log something extra, e.g. runtime memory usage in load tests+--+-- Approach: Install a callback that sneaks into to log message+-- sending/receiving, to intercept the messages and execute some code and then+-- return a new message.+interceptLogging+  :: forall r m a . Member (Logs m) r => (m -> Eff r ()) -> Eff r a -> Eff r a+interceptLogging interceptor = interpose return go+ where+  go :: Member (Logs m) r => Logs m x -> (Arr r x y) -> Eff r y+  go (LogMsg m) k = do+    interceptor m+    k ()++-- | Intercept logging to change, add or remove log messages.+--+-- This is without side effects, hence faster than 'interceptLogging'.+foldLogMessages+  :: forall r m a f+   . (Foldable f, Member (Logs m) r)+  => (m -> f m)+  -> Eff r a+  -> Eff r a+foldLogMessages interceptor = interpose return go+ where+  go :: Member (Logs m) r => Logs m x -> (Arr r x y) -> Eff r y+  go (LogMsg m) k = do+    traverse_ logMsg (interceptor m)+    k ()++-- | Capture all log messages in a 'Seq' (strict).+captureLogs+  :: NFData message => Eff (Logs message ': r) a -> Eff r (a, Seq message)+captureLogs = Eff.handle_relay_s Seq.empty+                                 (\logs result -> return (result, logs))+                                 handleLogs+ where+  handleLogs+    :: NFData message+    => Seq message+    -> Logs message x+    -> (Seq message -> Arr r x y)+    -> Eff r y+  handleLogs !logs (LogMsg !m) k = k (force (logs Seq.:|> m)) ()++-- | Throw away all log messages.+ignoreLogs :: forall message r a . Eff (Logs message ': r) a -> Eff r a+ignoreLogs = Eff.handle_relay return handleLogs+ where+  handleLogs :: Logs m x -> Arr r x y -> Eff r y+  handleLogs (LogMsg _) k = k ()++-- | Handle a 'Logs' effect with a message that has a 'Show' instance by+-- **re-logging** each message applied to 'show'.+relogAsString+  :: forall m e a+   . (Show m, Member (Logs String) e)+  => Eff (Logs m ': e) a+  -> Eff e a+relogAsString = handleLogsWith (logMsg . show)++-- | Apply a function that returns an effect to each log message.+handleLogsWith+  :: forall message e a+   . (message -> Eff e ())+  -> Eff (Logs message ': e) a+  -> Eff e a+handleLogsWith h = handle_relay return $ \(LogMsg m) k -> h m >>= k++-- | Handle the 'Logs' effect with a monadic call back function (strict).+handleLogsLifted+  :: forall m r message a+   . (NFData message, Monad m, SetMember Eff.Lift (Eff.Lift m) r)+  => (message -> m ())+  -> Eff (Logs message ': r) a+  -> Eff r a+handleLogsLifted logMessageHandler = handleLogsWith go+ where+  go :: message -> Eff r ()+  go m = Eff.lift (logMessageHandler (force m))++-- | Handle the 'Logs' effect using 'Log.LoggingT' 'Log.Handler's.+handleLogsWithLoggingTHandler+  :: forall m r message a+   . (Monad m, SetMember Eff.Lift (Eff.Lift m) r)+  => (forall b . (Log.Handler m message -> m b) -> m b)+  -> Eff (Logs message ': r) a+  -> Eff r a+handleLogsWithLoggingTHandler foldHandler =+  handleLogsWith (Eff.lift . foldHandler . flip ($))
+ src/Control/Eff/Log/Message.hs view
@@ -0,0 +1,421 @@+-- | An RFC 5434 inspired log message and convenience functions for+-- logging them.+module Control.Eff.Log.Message+  ( LogMessage(..)+  , renderRFC5424+  , printLogMessage+  , relogAsDebugMessages+  , logWithSeverity+  , logEmergency+  , logAlert+  , logCritical+  , logError+  , logWarning+  , logNotice+  , logInfo+  , logDebug+  , errorMessage+  , infoMessage+  , debugMessage+  , errorMessageIO+  , infoMessageIO+  , debugMessageIO+  , Severity(fromSeverity)+  , emergencySeverity+  , alertSeverity+  , criticalSeverity+  , errorSeverity+  , warningSeverity+  , noticeSeverity+  , informationalSeverity+  , debugSeverity+  , Facility(fromFacility)+  , kernelMessages+  , userLevelMessages+  , mailSystem+  , systemDaemons+  , securityAuthorizationMessages4+  , linePrinterSubsystem+  , networkNewsSubsystem+  , uucpSubsystem+  , clockDaemon+  , securityAuthorizationMessages10+  , ftpDaemon+  , ntpSubsystem+  , logAuditFacility+  , logAlertFacility+  , clockDaemon2+  , local0+  , local1+  , local2+  , local3+  , local4+  , local5+  , local6+  , local7+  , lmFacility+  , lmSeverity+  , lmTimestamp+  , lmHostname+  , lmAppname+  , lmProcessId+  , lmMessageId+  , lmStructuredData+  , lmSrcLoc+  , lmThreadId+  , lmMessage+  , setCallStack+  , StructuredDataElement(..)+  , sdElementId+  , sdElementParameters+  )+where++import           Data.Time.Clock+import           Data.Time.Format+import           Control.Lens+import           Control.Eff+import           Control.Eff.Log.Handler+import           GHC.Stack+import           Data.Default+import           Control.DeepSeq+import           Control.Monad.IO.Class+import           Data.Maybe+import           Data.String+import           Control.Concurrent+import           GHC.Generics+import           Text.Printf+import           Control.Monad                  ( (>=>) )++-- | A message data type inspired by the RFC-5424 Syslog Protocol+data LogMessage =+  LogMessage { _lmFacility :: Facility+             , _lmSeverity :: Severity+             , _lmTimestamp :: Maybe UTCTime+             , _lmHostname :: Maybe String+             , _lmAppname :: Maybe String+             , _lmProcessId :: Maybe String+             , _lmMessageId :: Maybe String+             , _lmStructuredData :: [StructuredDataElement]+             , _lmThreadId :: Maybe ThreadId+             , _lmSrcLoc :: Maybe SrcLoc+             , _lmMessage :: String}+  deriving (Eq, Generic)++showLmMessage :: LogMessage -> [String]+showLmMessage (LogMessage _f _s _ts _hn _an _pid _mi _sd ti loc msg) =+  if null msg+    then []+    else+      maybe "" (printf "[%s]" . show) ti+      : msg+      : maybe [] (pure . prettySrcLoc) loc+++-- | Render a 'LogMessage' human readable.+renderLogMessage :: LogMessage -> String+renderLogMessage l@(LogMessage _f s ts hn an pid mi sd _ _ _) =+  unwords $ filter+    (not . null)+    ( maybe+        ""+        (formatTime defaultTimeLocale (iso8601DateFormat (Just "%H:%M:%S")))+        ts+    : fromMaybe "" hn+    : show s+    : fromMaybe "" an+    : fromMaybe "" pid+    : fromMaybe "" mi+    : (if null sd then "" else show sd)+    : showLmMessage l+    )++-- | Render a 'LogMessage' according to the rules in the given RFC, except for+-- the rules concerning unicode and ascii+renderRFC5424 :: LogMessage -> String+renderRFC5424 l@(LogMessage f s ts hn an pid mi sd _ _ _) = unwords+  ( ("<" ++ show (fromSeverity s + fromFacility f * 8) ++ ">" ++ "1")+  : maybe+      "-"+      (formatTime defaultTimeLocale (iso8601DateFormat (Just "%H:%M:%S")))+      ts+  : fromMaybe "-" hn+  : fromMaybe "-" an+  : fromMaybe "-" pid+  : fromMaybe "-" mi+  : (if null sd then "-" else show sd)+  : showLmMessage l+  )+++instance NFData LogMessage++-- | RFC-5424 defines how structured data can be included in a log message.+data StructuredDataElement =+  SdElement { _sdElementId :: String+            , _sdElementParameters :: [SdParameter]}+  deriving (Eq, Ord, Generic)++instance Show StructuredDataElement where+  show (SdElement sdid params) =+    "[" ++ sdName sdid ++ if null params then "" else " " ++ unwords (show <$> params) ++ "]"++instance NFData StructuredDataElement++-- | Component of a 'StructuredDataElement'+data SdParameter =+  SdParameter String String+  deriving (Eq, Ord, Generic)++instance Show SdParameter where+  show (SdParameter k v) = sdName k ++ "=\"" ++ sdParamValue v ++ "\""++sdName :: String -> String+sdName = take 32 . filter (\c -> c == '=' || c == ']' || c == ' ' || c == '"')++sdParamValue :: String -> String+sdParamValue e = e >>= \case+  '"'  -> "\\\""+  '\\' -> "\\\\"+  ']'  -> "\\]"+  x    -> [x]++instance NFData SdParameter++-- | An rfc 5424 severity+newtype Severity =+  Severity {fromSeverity :: Int}+  deriving (Eq, Ord, Generic, NFData)++instance Show Severity where+  show (Severity 1)             = "ALERT    "+  show (Severity 2)             = "CRITICAL "+  show (Severity 3)             = "ERROR    "+  show (Severity 4)             = "WARNING  "+  show (Severity 5)             = "NOTICE   "+  show (Severity 6)             = "INFO     "+  show (Severity x) |  x <= 0   = "EMERGENCY"+                    | otherwise = "DEBUG    "++-- | An rfc 5424 facility+newtype Facility = Facility {fromFacility :: Int}+  deriving (Eq, Ord, Show, Generic, NFData)+++makeLenses ''StructuredDataElement+makeLenses ''LogMessage++-- | Put the source location of the given callstack in 'lmSrcLoc'+setCallStack :: CallStack -> LogMessage -> LogMessage+setCallStack cs m = case getCallStack cs of+  []              -> m+  (_, srcLoc) : _ -> m & lmSrcLoc ?~ srcLoc++instance Default LogMessage where+  def = setCallStack callStack (LogMessage def def def def def def def def def def "")++instance IsString LogMessage where+  fromString = infoMessage++-- | Render a 'LogMessage' but set the timestamp and thread id fields.+printLogMessage :: LogMessage -> IO ()+printLogMessage =+  setLogMessageTimestamp+    >=> setLogMessageThreadId+    >=> putStrLn+    .   renderLogMessage++-- | An IO action that sets the current UTC time (see 'enableLogMessageTimestamps')+-- in 'lmTimestamp'.+setLogMessageTimestamp :: MonadIO m => LogMessage -> m LogMessage+setLogMessageTimestamp m = do+  now <- liftIO getCurrentTime+  return (m & lmTimestamp ?~ now)++-- | An IO action appends the the 'ThreadId' of the calling process (see 'myThreadId')+-- to 'lmMessage'.+setLogMessageThreadId :: MonadIO m => LogMessage -> m LogMessage+setLogMessageThreadId m = do+  t <- liftIO myThreadId+  return (m & lmThreadId ?~ t)++-- | Handle a 'Logs' effect for 'String' messages by re-logging the messages+-- as 'LogMessage's with 'debugSeverity'.+relogAsDebugMessages+  :: Member (Logs LogMessage) e => Eff (Logs String ': e) a -> Eff e a+relogAsDebugMessages = withFrozenCallStack . handleLogsWith logDebug++-- | Log a 'String' as 'LogMessage' with a given 'Severity'.+logWithSeverity :: Member (Logs LogMessage) e => Severity -> String -> Eff e ()+logWithSeverity s =+  withFrozenCallStack+    . logMsg+    . setCallStack callStack+    . set lmSeverity s+    . flip (set lmMessage) def++-- | Log a 'String' as 'emergencySeverity'.+logEmergency :: Member (Logs LogMessage) e => String -> Eff e ()+logEmergency = withFrozenCallStack . logWithSeverity emergencySeverity++-- | Log a message with 'alertSeverity'.+logAlert :: Member (Logs LogMessage) e => String -> Eff e ()+logAlert = withFrozenCallStack . logWithSeverity alertSeverity++-- | Log a 'criticalSeverity' message.+logCritical :: Member (Logs LogMessage) e => String -> Eff e ()+logCritical = withFrozenCallStack . logWithSeverity criticalSeverity++-- | Log a 'errorSeverity' message.+logError :: Member (Logs LogMessage) e => String -> Eff e ()+logError = withFrozenCallStack . logWithSeverity errorSeverity++-- | Log a 'warningSeverity' message.+logWarning :: Member (Logs LogMessage) e => String -> Eff e ()+logWarning = withFrozenCallStack . logWithSeverity warningSeverity++-- | Log a 'noticeSeverity' message.+logNotice :: Member (Logs LogMessage) e => String -> Eff e ()+logNotice = withFrozenCallStack . logWithSeverity noticeSeverity++-- | Log a 'informationalSeverity' message.+logInfo :: Member (Logs LogMessage) e => String -> Eff e ()+logInfo = withFrozenCallStack . logWithSeverity informationalSeverity++-- | Log a 'debugSeverity' message.+logDebug :: Member (Logs LogMessage) e => String -> Eff e ()+logDebug = withFrozenCallStack . logWithSeverity debugSeverity++-- | Construct a 'LogMessage' with 'errorSeverity'+errorMessage :: String -> LogMessage+errorMessage m = withFrozenCallStack+  (def & lmSeverity .~ errorSeverity & lmMessage .~ m & setCallStack callStack)++-- | Construct a 'LogMessage' with 'informationalSeverity'+infoMessage :: String -> LogMessage+infoMessage m = withFrozenCallStack+  (  def+  &  lmSeverity+  .~ informationalSeverity+  &  lmMessage+  .~ m+  &  setCallStack callStack+  )++-- | Construct a 'LogMessage' with 'debugSeverity'+debugMessage :: String -> LogMessage+debugMessage m = withFrozenCallStack+  (def & lmSeverity .~ debugSeverity & lmMessage .~ m & setCallStack callStack)++-- | Construct a 'LogMessage' with 'errorSeverity'+errorMessageIO :: MonadIO m => String -> m LogMessage+errorMessageIO =+  (setLogMessageThreadId >=> setLogMessageTimestamp) . errorMessage+-- | Construct a 'LogMessage' with 'informationalSeverity'+infoMessageIO :: MonadIO m => String -> m LogMessage+infoMessageIO =+  (setLogMessageThreadId >=> setLogMessageTimestamp) . infoMessage+-- | Construct a 'LogMessage' with 'debugSeverity'+debugMessageIO :: MonadIO m => String -> m LogMessage+debugMessageIO =+  (setLogMessageThreadId >=> setLogMessageTimestamp) . debugMessage+++emergencySeverity :: Severity+emergencySeverity = Severity 0++alertSeverity :: Severity+alertSeverity = Severity 1++criticalSeverity :: Severity+criticalSeverity = Severity 2++errorSeverity :: Severity+errorSeverity = Severity 3++warningSeverity :: Severity+warningSeverity = Severity 4++noticeSeverity :: Severity+noticeSeverity = Severity 5++informationalSeverity :: Severity+informationalSeverity = Severity 6++debugSeverity :: Severity+debugSeverity = Severity 7++instance Default Severity where+  def = debugSeverity++kernelMessages :: Facility+kernelMessages = Facility 0++userLevelMessages :: Facility+userLevelMessages = Facility 1++mailSystem :: Facility+mailSystem = Facility 2++systemDaemons :: Facility+systemDaemons = Facility 3++securityAuthorizationMessages4 :: Facility+securityAuthorizationMessages4 = Facility 4++linePrinterSubsystem :: Facility+linePrinterSubsystem = Facility 6++networkNewsSubsystem :: Facility+networkNewsSubsystem = Facility 7++uucpSubsystem :: Facility+uucpSubsystem = Facility 8++clockDaemon :: Facility+clockDaemon = Facility 9++securityAuthorizationMessages10 :: Facility+securityAuthorizationMessages10 = Facility 10++ftpDaemon :: Facility+ftpDaemon = Facility 11++ntpSubsystem :: Facility+ntpSubsystem = Facility 12++logAuditFacility :: Facility+logAuditFacility = Facility 13++logAlertFacility :: Facility+logAlertFacility = Facility 14++clockDaemon2 :: Facility+clockDaemon2 = Facility 15++local0 :: Facility+local0 = Facility 16++local1 :: Facility+local1 = Facility 17++local2 :: Facility+local2 = Facility 18++local3 :: Facility+local3 = Facility 19++local4 :: Facility+local4 = Facility 20++local5 :: Facility+local5 = Facility 21++local6 :: Facility+local6 = Facility 22++local7 :: Facility+local7 = Facility 23++instance Default Facility where+  def = local7
− src/Control/Eff/Log/MessageFactory.hs
@@ -1,56 +0,0 @@-module Control.Eff.Log.MessageFactory-  ( mkLogMsg-  , MessageFactory()-  , MessageFactoryReader-  , withLogMessageFactory-  , composeMessageFactories-  , localMessageFactory-  )-where--import           Control.Eff-import           Control.Eff.Log         hiding ( Severity )-import           Control.Eff.Reader.Strict-import           Control.Eff.Lift-import           Control.Monad.IO.Class-import           Data.Default--newtype MessageFactory m =-  MessageFactory { runMessageFactory :: IO m}--type MessageFactoryReader m = Reader (MessageFactory m)--mkLogMsg-  :: forall m io e-   . ( Member (Logs m) e-     , MonadIO io-     , SetMember Lift (Lift io) e-     , Member (MessageFactoryReader m) e-     )-  => (m -> m)-  -> Eff e ()-mkLogMsg f = ask >>= lift . liftIO . runMessageFactory >>= logMsg . f--localMessageFactory-  :: forall m e a-   . (Member (MessageFactoryReader m) e)-  => IO m-  -> Eff e a-  -> Eff e a-localMessageFactory = local . const . MessageFactory--composeMessageFactories-  :: forall m e a-   . (Member (MessageFactoryReader m) e)-  => (m -> IO m)-  -> Eff e a-  -> Eff e a-composeMessageFactories f2 =-  local (\(MessageFactory f1) -> MessageFactory (f1 >>= f2))--withLogMessageFactory-  :: forall m io e a-   . (Member (Logs m) e, Default m, MonadIO io, SetMember Lift (Lift io) e)-  => Eff (MessageFactoryReader m ': e) a-  -> Eff e a-withLogMessageFactory = runReader (MessageFactory (return def))
− src/Control/Eff/Log/Syslog.hs
@@ -1,249 +0,0 @@--- | An RFC 5434 inspired log message and convenience functions for--- logging them. TODO document-module Control.Eff.Log.Syslog-  ( Severity(fromSeverity)-  , emergencySeverity-  , alertSeverity-  , criticalSeverity-  , errorSeverity-  , warningSeverity-  , noticeSeverity-  , informationalSeverity-  , debugSeverity-  , Facility(fromFacility)-  , kernelMessages-  , userLevelMessages-  , mailSystem-  , systemDaemons-  , securityAuthorizationMessages4-  , linePrinterSubsystem-  , networkNewsSubsystem-  , uucpSubsystem-  , clockDaemon-  , securityAuthorizationMessages10-  , ftpDaemon-  , ntpSubsystem-  , logAuditFacility-  , logAlertFacility-  , clockDaemon2-  , local0-  , local1-  , local2-  , local3-  , local4-  , local5-  , local6-  , local7-  , LogMessage(..)-  , lmFacility-  , lmSeverity-  , lmTimestamp-  , lmHostname-  , lmAppname-  , lmProcessId-  , lmMessageId-  , lmStructuredData-  , lmSrcLoc-  , lmMessage-  , StructuredDataElement(..)-  , sdElementId-  , sdElementParameters-  , addSyslogTimestamps-  , syslogMsg-  , withSyslog-  )-where--import           Data.Time.Clock-import           Data.Time.Format-import           Control.Lens-import           Control.Eff-import           Control.Eff.Lift-import           Control.Eff.Log         hiding ( Severity )-import           GHC.Stack-import           Data.Default-import           Control.Eff.Log.MessageFactory-import           Control.DeepSeq-import           Control.Monad.IO.Class-import           Data.Maybe-import           GHC.Generics--data LogMessage =-  LogMessage { _lmFacility :: Facility-             , _lmSeverity :: Severity-             , _lmTimestamp :: Maybe UTCTime-             , _lmHostname :: Maybe String-             , _lmAppname :: Maybe String-             , _lmProcessId :: Maybe String-             , _lmMessageId :: Maybe String-             , _lmStructuredData :: [StructuredDataElement]-             , _lmSrcLoc :: Maybe SrcLoc-             , _lmMessage :: String}-  deriving (Eq, Generic)--instance Show LogMessage where-  show (LogMessage f s ts hn an pid mi sd loc msg) =-    unwords-      ( ("<" ++ show (fromSeverity s + fromFacility f * 8) ++ ">" ++ "1")-     : maybe "-" (formatTime defaultTimeLocale (iso8601DateFormat (Just "%H:%M:%S"))) ts-     : fromMaybe "-" hn-     : fromMaybe "-" an-     : fromMaybe "-" pid-     : fromMaybe "-" mi-     : (if null sd then "-" else show sd)-     : (if null msg then [] else msg : maybe [] (pure . prettySrcLoc) loc))--instance NFData LogMessage--data StructuredDataElement =-  StructuredDataElement {_sdElementId :: String-                        ,_sdElementParameters :: [(String, Maybe String)]}-  deriving (Eq, Ord, Show, Generic)--instance NFData StructuredDataElement--instance Default LogMessage where-  def = LogMessage local7 debugSeverity def def def def def def def ""---- | An rfc 5424 severity-newtype Severity = Severity {fromSeverity :: Int}-  deriving (Eq, Ord, Show, Generic, NFData)--emergencySeverity :: Severity-emergencySeverity = Severity 0--alertSeverity :: Severity-alertSeverity = Severity 1--criticalSeverity :: Severity-criticalSeverity = Severity 2--errorSeverity :: Severity-errorSeverity = Severity 3--warningSeverity :: Severity-warningSeverity = Severity 4--noticeSeverity :: Severity-noticeSeverity = Severity 5--informationalSeverity :: Severity-informationalSeverity = Severity 6--debugSeverity :: Severity-debugSeverity = Severity 7---- | An rfc 5424 facility-newtype Facility = Facility {fromFacility :: Int}-  deriving (Eq, Ord, Show, Generic, NFData)--kernelMessages :: Facility-kernelMessages = Facility 0--userLevelMessages :: Facility-userLevelMessages = Facility 1--mailSystem :: Facility-mailSystem = Facility 2--systemDaemons :: Facility-systemDaemons = Facility 3--securityAuthorizationMessages4 :: Facility-securityAuthorizationMessages4 = Facility 4--linePrinterSubsystem :: Facility-linePrinterSubsystem = Facility 6--networkNewsSubsystem :: Facility-networkNewsSubsystem = Facility 7--uucpSubsystem :: Facility-uucpSubsystem = Facility 8--clockDaemon :: Facility-clockDaemon = Facility 9--securityAuthorizationMessages10 :: Facility-securityAuthorizationMessages10 = Facility 10--ftpDaemon :: Facility-ftpDaemon = Facility 11--ntpSubsystem :: Facility-ntpSubsystem = Facility 12--logAuditFacility :: Facility-logAuditFacility = Facility 13--logAlertFacility :: Facility-logAlertFacility = Facility 14--clockDaemon2 :: Facility-clockDaemon2 = Facility 15--local0 :: Facility-local0 = Facility 16--local1 :: Facility-local1 = Facility 17--local2 :: Facility-local2 = Facility 18--local3 :: Facility-local3 = Facility 19--local4 :: Facility-local4 = Facility 20--local5 :: Facility-local5 = Facility 21--local6 :: Facility-local6 = Facility 22--local7 :: Facility-local7 = Facility 23--makeLenses ''StructuredDataElement-makeLenses ''LogMessage--addSyslogTimestamps-  :: ( MonadIO io-     , SetMember Lift (Lift io) e-     , Member (Logs LogMessage) e-     , Member (MessageFactoryReader LogMessage) e-     )-  => Eff e a-  -> Eff e a-addSyslogTimestamps = composeMessageFactories $ \m -> do-  now <- getCurrentTime-  return (m & lmTimestamp ?~ now)--syslogMsg-  :: ( HasCallStack-     , MonadIO io-     , SetMember Lift (Lift io) e-     , Member (Logs LogMessage) e-     , Member (MessageFactoryReader LogMessage) e-     )-  => (LogMessage -> LogMessage)-  -> Eff e ()-syslogMsg f = mkLogMsg (f . setCallStack callStack)- where-  setCallStack :: CallStack -> LogMessage -> LogMessage-  setCallStack cs m = case getCallStack cs of-    []              -> m-    (_, srcLoc) : _ -> m & lmSrcLoc ?~ srcLoc--withSyslog-  :: forall io e a-   . ( Member (Logs LogMessage) e-     , Default LogMessage-     , MonadIO io-     , SetMember Lift (Lift io) e-     )-  => Eff (MessageFactoryReader LogMessage ': e) a-  -> Eff e a-withSyslog = withLogMessageFactory . addSyslogTimestamps
test/Common.hs view
@@ -1,5 +1,4 @@-module Common-where+module Common where  import           Control.Concurrent.STM import           Control.Eff.Concurrent.Process@@ -20,7 +19,7 @@ timeoutSeconds seconds = Timeout (seconds * 1000000) (show seconds ++ "s")  withTestLogC-  :: (e -> LogChannel String -> IO ())+  :: (e -> LogChannel LogMessage -> IO ())   -> (IO (e -> IO ()) -> TestTree)   -> TestTree withTestLogC doSchedule k = withResource@@ -35,16 +34,16 @@     )   ) -testLogC :: IO (LogChannel String)+testLogC :: IO (LogChannel LogMessage) testLogC =-  filterLogChannel (\m -> take (length logPrefix) m == logPrefix)-    <$> forkLogger 1 (putStrLn) Nothing+  filterLogChannel (\m -> take (length logPrefix) (_lmMessage m) == logPrefix)+    <$> forkLogger 1 printLogMessage Nothing -testLogJoin :: LogChannel String -> IO ()-testLogJoin = joinLogChannel Nothing+testLogJoin :: LogChannel LogMessage -> IO ()+testLogJoin = joinLogChannel -tlog :: Member (Logs String) r => String -> Eff r ()-tlog = logMsg . (logPrefix ++)+tlog :: Member (Logs LogMessage) r => String -> Eff r ()+tlog = logInfo . (logPrefix ++)  logPrefix :: String logPrefix = "[TEST] "@@ -58,7 +57,7 @@  scheduleAndAssert   :: forall r-   . (SetMember Lift (Lift IO) r, Member (Logs String) r)+   . (SetMember Lift (Lift IO) r, Member (Logs LogMessage) r)   => IO (Eff (Process r ': r) () -> IO ())   -> (  (String -> Bool -> Eff (Process r ': r) ())      -> Eff (Process r ': r) ()@@ -78,7 +77,7 @@  applySchedulerFactory   :: forall r-   . (Member (Logs String) r, SetMember Lift (Lift IO) r)+   . (Member (Logs LogMessage) r, SetMember Lift (Lift IO) r)   => IO (Eff (Process r ': r) () -> IO ())   -> Eff (Process r ': r) ()   -> IO ()
test/LoggingTests.hs view
@@ -33,3 +33,6 @@  toOtherLogMsg :: ('[Logs String, Logs OtherLogMsg] <:: e) => String -> Eff e () toOtherLogMsg = logMsg . OtherLogMsg++demo2 :: Member (Logs LogMessage) e => Eff e ()+demo2 = relogAsDebugMessages demo
test/ProcessBehaviourTestCases.hs view
@@ -1,5 +1,4 @@-module ProcessBehaviourTestCases-where+module ProcessBehaviourTestCases where  import           Data.List                      ( sort ) import           Data.Dynamic@@ -33,7 +32,7 @@   (withTestLogC     (\e logC ->         -- void (runLift (logToChannel logC (SingleThreaded.schedule (return ()) e)))-      let runEff :: Eff '[Logs String, Lift IO] a -> IO a+      let runEff :: Eff '[Logs LogMessage, Lift IO] a -> IO a           runEff = runLift . logToChannel logC       in  void $ SingleThreaded.scheduleM runEff yield e     )@@ -43,7 +42,7 @@  allTests   :: forall r-   . (Member (Logs String) r, SetMember Lift (Lift IO) r)+   . (Member (Logs LogMessage) r, SetMember Lift (Lift IO) r)   => IO (Eff (Process r ': r) () -> IO ())   -> TestTree allTests schedulerFactory = localOption@@ -61,7 +60,7 @@  yieldLoopTests   :: forall r-   . (Member (Logs String) r, SetMember Lift (Lift IO) r)+   . (Member (Logs LogMessage) r, SetMember Lift (Lift IO) r)   => IO (Eff (Process r ': r) () -> IO ())   -> TestTree yieldLoopTests schedulerFactory@@ -100,7 +99,7 @@  pingPongTests   :: forall r-   . (Member (Logs String) r, SetMember Lift (Lift IO) r)+   . (Member (Logs LogMessage) r, SetMember Lift (Lift IO) r)   => IO (Eff (Process r ': r) () -> IO ())   -> TestTree pingPongTests schedulerFactory = testGroup@@ -175,7 +174,7 @@  errorTests   :: forall r-   . (Member (Logs String) r, SetMember Lift (Lift IO) r)+   . (Member (Logs LogMessage) r, SetMember Lift (Lift IO) r)   => IO (Eff (Process r ': r) () -> IO ())   -> TestTree errorTests schedulerFactory@@ -249,7 +248,7 @@  concurrencyTests   :: forall r-   . (Member (Logs String) r, SetMember Lift (Lift IO) r)+   . (Member (Logs LogMessage) r, SetMember Lift (Lift IO) r)   => IO (Eff (Process r ': r) () -> IO ())   -> TestTree concurrencyTests schedulerFactory@@ -292,10 +291,11 @@                 m <- receiveMessage px                 void (sendMessage px me m)               )-            child2 <- spawn (foreverCheap (void (sendMessage px 888 (toDyn ""))))-            True   <- sendMessageChecked px child1 (toDyn "test")-            i      <- receiveMessageAs px-            True   <- sendShutdownChecked px child2+            child2 <- spawn+              (foreverCheap (void (sendMessage px 888 (toDyn ""))))+            True <- sendMessageChecked px child1 (toDyn "test")+            i    <- receiveMessageAs px+            True <- sendShutdownChecked px child2             assertEff "" (i == "test")         , testCase "most processes send foreverCheap"         $ scheduleAndAssert schedulerFactory@@ -395,7 +395,7 @@  exitTests   :: forall r-   . (Member (Logs String) r, SetMember Lift (Lift IO) r)+   . (Member (Logs LogMessage) r, SetMember Lift (Lift IO) r)   => IO (Eff (Process r ': r) () -> IO ())   -> TestTree exitTests schedulerFactory =@@ -495,8 +495,8 @@           , (howToExit, doExit    ) <-             [ ("normally"        , void (exitNormally px))             , ("simply returning", return ())-            , ("raiseError"      , void (raiseError px "test error raised"))-            , ("exitWithError"   , void (exitWithError px "test error exit"))+            , ("raiseError", void (raiseError px "test error raised"))+            , ("exitWithError", void (exitWithError px "test error exit"))             , ( "sendShutdown to self"               , do                 me <- self px@@ -509,7 +509,7 @@  sendShutdownTests   :: forall r-   . (Member (Logs String) r, SetMember Lift (Lift IO) r)+   . (Member (Logs LogMessage) r, SetMember Lift (Lift IO) r)   => IO (Eff (Process r ': r) () -> IO ())   -> TestTree sendShutdownTests schedulerFactory =