packages feed

ribosome-0.9.9.9: lib/Ribosome/Report.hs

-- |Smart constructors for @'DataLog' 'LogReport'@
module Ribosome.Report (
  module Ribosome.Report,
  module Ribosome.Host.Effect.Reports,
  module Ribosome.Host.Interpreter.Reports,
  LogReport (LogReport),
  Report (Report),
  ReportContext (ReportContext),
  Reportable (toReport),
) where

import Log (Severity (Error, Info, Warn), dataLog)
import qualified Polysemy.Log as Log

import Ribosome.Data.SettingError (SettingError)
import Ribosome.Effect.Scratch (Scratch)
import Ribosome.Effect.Settings (Settings)
import qualified Ribosome.Host.Data.Report as Report
import Ribosome.Host.Data.Report (
  LogReport (LogReport),
  Report (Report),
  ReportContext (ReportContext),
  Reportable (toReport),
  resumeReport,
  severity,
  )
import Ribosome.Host.Data.RpcError (RpcError)
import Ribosome.Host.Effect.Reports (Reports (..), storeReport, storedReports)
import Ribosome.Host.Effect.Rpc (Rpc)
import Ribosome.Host.Interpreter.Reports

-- |Add a segment to the current 'Report' logging context.
context ::
  Member (DataLog LogReport) r =>
  Text ->
  Sem r a ->
  Sem r a
context ctx =
  Log.local (#context %~ \ (ReportContext cur) -> ReportContext (ctx : cur))

-- |Set the current 'Report' logging context.
setContext ::
  Member (DataLog LogReport) r =>
  ReportContext ->
  Sem r a ->
  Sem r a
setContext ctx =
  Log.local (#context .~ ctx)

-- |Convert a value to 'Report' via 'Reportable' and send it to the log.
logReport ::
  Reportable e =>
  Member (DataLog LogReport) r =>
  e ->
  Sem r ()
logReport e =
  dataLog (LogReport r True (severity r >= Warn) mempty)
  where
    r = toReport e

-- |Send a 'Report' to the log given a user and log message, with serverity 'Info'.
info ::
  Member (DataLog LogReport) r =>
  Text ->
  [Text] ->
  Sem r ()
info user log =
  logReport Report {severity = Info, ..}

-- |Send a 'Report' to the log given a user and log message, with serverity 'Warn'.
warn ::
  Member (DataLog LogReport) r =>
  Text ->
  [Text] ->
  Sem r ()
warn user log =
  logReport Report {severity = Warn, ..}

-- |Send a 'Report' to the log given a user and log message, with serverity 'Log.Error'.
error ::
  Member (DataLog LogReport) r =>
  Text ->
  [Text] ->
  Sem r ()
error user log =
  logReport Report {severity = Error, ..}

-- |Eliminate @'Stop' err@ by converting @err@ to a 'Report' and logging it, continuing execution for a unit action.
reportStop ::
  ∀ err r .
  Reportable err =>
  Member (DataLog LogReport) r =>
  Sem (Stop err : r) () ->
  Sem r ()
reportStop sem =
  withFrozenCallStack do
    either logReport pure =<< runStop sem

-- |Resume an effect by converting the error to a 'Report' and logging it, continuing execution for a unit action.
resumeLogReport ::
  ∀ eff e r .
  Reportable e =>
  Members [eff !! e, DataLog LogReport] r =>
  Sem (eff : r) () ->
  Sem r ()
resumeLogReport sem =
  withFrozenCallStack do
    sem !! logReport

-- |Resume all plugin effects.
pluginLogReports ::
  Members [Scratch !! RpcError, Settings !! SettingError, Rpc !! RpcError, Stop Report] r =>
  InterpretersFor [Scratch, Settings, Rpc] r
pluginLogReports =
  resumeReport @Rpc .
  resumeReport @Settings .
  resumeReport @Scratch