{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE NumericUnderscores #-}
{-# LANGUAGE TypeApplications #-}
module OpenTelemetry.Internal.Logs.Core (
LoggerProviderOptions (..),
emptyLoggerProviderOptions,
createLoggerProvider,
setGlobalLoggerProvider,
getGlobalLoggerProvider,
shutdownLoggerProvider,
forceFlushLoggerProvider,
makeLogger,
emitLogRecord,
addAttribute,
addAttributes,
logRecordGetAttributes,
logDroppedAttributes,
emitOTelLogRecord,
) where
import Control.Applicative
import Control.Concurrent.Async
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Trans.Maybe
import Data.Coerce
import Data.HashMap.Strict (HashMap)
import qualified Data.HashMap.Strict as H
import Data.IORef
import Data.Maybe
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Vector as V
import Data.Version (showVersion)
import GHC.IO (unsafePerformIO)
import qualified OpenTelemetry.Attributes as A
import OpenTelemetry.Common
import OpenTelemetry.Context
import OpenTelemetry.Context.ThreadLocal
import OpenTelemetry.Internal.Common.Types
import OpenTelemetry.Internal.Logs.Types
import OpenTelemetry.Internal.Trace.Types (SpanContext (..), getSpanContext)
import OpenTelemetry.LogAttributes (LogAttributes)
import qualified OpenTelemetry.LogAttributes as LA
import OpenTelemetry.Resource (MaterializedResources, emptyMaterializedResources)
import Paths_hs_opentelemetry_api (version)
import System.Clock
import System.Timeout (timeout)
getCurrentTimestamp :: (MonadIO m) => m Timestamp
getCurrentTimestamp :: forall (m :: * -> *). MonadIO m => m Timestamp
getCurrentTimestamp = IO Timestamp -> m Timestamp
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Timestamp -> m Timestamp) -> IO Timestamp -> m Timestamp
forall a b. (a -> b) -> a -> b
$ forall a b. Coercible a b => a -> b
forall a b. Coercible a b => a -> b
coerce @(IO TimeSpec) @(IO Timestamp) (IO TimeSpec -> IO Timestamp) -> IO TimeSpec -> IO Timestamp
forall a b. (a -> b) -> a -> b
$ Clock -> IO TimeSpec
getTime Clock
Realtime
data LoggerProviderOptions = LoggerProviderOptions
{ LoggerProviderOptions -> MaterializedResources
loggerProviderOptionsResource :: MaterializedResources
, LoggerProviderOptions -> AttributeLimits
loggerProviderOptionsAttributeLimits :: A.AttributeLimits
}
emptyLoggerProviderOptions :: LoggerProviderOptions
emptyLoggerProviderOptions :: LoggerProviderOptions
emptyLoggerProviderOptions =
LoggerProviderOptions
{ loggerProviderOptionsResource :: MaterializedResources
loggerProviderOptionsResource = MaterializedResources
emptyMaterializedResources
, loggerProviderOptionsAttributeLimits :: AttributeLimits
loggerProviderOptionsAttributeLimits = AttributeLimits
A.defaultAttributeLimits
}
createLoggerProvider :: [LogRecordProcessor] -> LoggerProviderOptions -> LoggerProvider
createLoggerProvider :: [LogRecordProcessor] -> LoggerProviderOptions -> LoggerProvider
createLoggerProvider [LogRecordProcessor]
ps LoggerProviderOptions {AttributeLimits
MaterializedResources
loggerProviderOptionsResource :: LoggerProviderOptions -> MaterializedResources
loggerProviderOptionsAttributeLimits :: LoggerProviderOptions -> AttributeLimits
loggerProviderOptionsResource :: MaterializedResources
loggerProviderOptionsAttributeLimits :: AttributeLimits
..} =
LoggerProvider
{ loggerProviderProcessors :: Vector LogRecordProcessor
loggerProviderProcessors = [LogRecordProcessor] -> Vector LogRecordProcessor
forall a. [a] -> Vector a
V.fromList [LogRecordProcessor]
ps
, loggerProviderResource :: MaterializedResources
loggerProviderResource = MaterializedResources
loggerProviderOptionsResource
, loggerProviderAttributeLimits :: AttributeLimits
loggerProviderAttributeLimits = AttributeLimits
loggerProviderOptionsAttributeLimits
}
noOpLoggerProvider :: LoggerProvider
noOpLoggerProvider :: LoggerProvider
noOpLoggerProvider = [LogRecordProcessor] -> LoggerProviderOptions -> LoggerProvider
createLoggerProvider [] LoggerProviderOptions
emptyLoggerProviderOptions
globalLoggerProvider :: IORef LoggerProvider
globalLoggerProvider :: IORef LoggerProvider
globalLoggerProvider = IO (IORef LoggerProvider) -> IORef LoggerProvider
forall a. IO a -> a
unsafePerformIO (IO (IORef LoggerProvider) -> IORef LoggerProvider)
-> IO (IORef LoggerProvider) -> IORef LoggerProvider
forall a b. (a -> b) -> a -> b
$ LoggerProvider -> IO (IORef LoggerProvider)
forall a. a -> IO (IORef a)
newIORef LoggerProvider
noOpLoggerProvider
{-# NOINLINE globalLoggerProvider #-}
getGlobalLoggerProvider :: (MonadIO m) => m LoggerProvider
getGlobalLoggerProvider :: forall (m :: * -> *). MonadIO m => m LoggerProvider
getGlobalLoggerProvider = IO LoggerProvider -> m LoggerProvider
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO LoggerProvider -> m LoggerProvider)
-> IO LoggerProvider -> m LoggerProvider
forall a b. (a -> b) -> a -> b
$ IORef LoggerProvider -> IO LoggerProvider
forall a. IORef a -> IO a
readIORef IORef LoggerProvider
globalLoggerProvider
setGlobalLoggerProvider :: (MonadIO m) => LoggerProvider -> m ()
setGlobalLoggerProvider :: forall (m :: * -> *). MonadIO m => LoggerProvider -> m ()
setGlobalLoggerProvider = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ())
-> (LoggerProvider -> IO ()) -> LoggerProvider -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IORef LoggerProvider -> LoggerProvider -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef LoggerProvider
globalLoggerProvider
shutdownLoggerProvider :: (MonadIO m) => LoggerProvider -> m ()
shutdownLoggerProvider :: forall (m :: * -> *). MonadIO m => LoggerProvider -> m ()
shutdownLoggerProvider LoggerProvider {Vector LogRecordProcessor
loggerProviderProcessors :: LoggerProvider -> Vector LogRecordProcessor
loggerProviderProcessors :: Vector LogRecordProcessor
loggerProviderProcessors} = IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ do
Vector (Async ShutdownResult)
asyncShutdownResults <- Vector LogRecordProcessor
-> (LogRecordProcessor -> IO (Async ShutdownResult))
-> IO (Vector (Async ShutdownResult))
forall (m :: * -> *) a b.
Monad m =>
Vector a -> (a -> m b) -> m (Vector b)
V.forM Vector LogRecordProcessor
loggerProviderProcessors ((LogRecordProcessor -> IO (Async ShutdownResult))
-> IO (Vector (Async ShutdownResult)))
-> (LogRecordProcessor -> IO (Async ShutdownResult))
-> IO (Vector (Async ShutdownResult))
forall a b. (a -> b) -> a -> b
$ \LogRecordProcessor
processor -> do
LogRecordProcessor -> IO (Async ShutdownResult)
logRecordProcessorShutdown LogRecordProcessor
processor
(Async ShutdownResult -> IO ShutdownResult)
-> Vector (Async ShutdownResult) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ Async ShutdownResult -> IO ShutdownResult
forall a. Async a -> IO a
wait Vector (Async ShutdownResult)
asyncShutdownResults
forceFlushLoggerProvider
:: (MonadIO m)
=> LoggerProvider
-> Maybe Int
-> m FlushResult
forceFlushLoggerProvider :: forall (m :: * -> *).
MonadIO m =>
LoggerProvider -> Maybe Int -> m FlushResult
forceFlushLoggerProvider LoggerProvider {Vector LogRecordProcessor
loggerProviderProcessors :: LoggerProvider -> Vector LogRecordProcessor
loggerProviderProcessors :: Vector LogRecordProcessor
loggerProviderProcessors} Maybe Int
mtimeout = IO FlushResult -> m FlushResult
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO FlushResult -> m FlushResult)
-> IO FlushResult -> m FlushResult
forall a b. (a -> b) -> a -> b
$ do
Vector (Async ())
jobs <- Vector LogRecordProcessor
-> (LogRecordProcessor -> IO (Async ())) -> IO (Vector (Async ()))
forall (m :: * -> *) a b.
Monad m =>
Vector a -> (a -> m b) -> m (Vector b)
V.forM Vector LogRecordProcessor
loggerProviderProcessors ((LogRecordProcessor -> IO (Async ())) -> IO (Vector (Async ())))
-> (LogRecordProcessor -> IO (Async ())) -> IO (Vector (Async ()))
forall a b. (a -> b) -> a -> b
$ \LogRecordProcessor
processor -> IO () -> IO (Async ())
forall a. IO a -> IO (Async a)
async (IO () -> IO (Async ())) -> IO () -> IO (Async ())
forall a b. (a -> b) -> a -> b
$ do
LogRecordProcessor -> IO ()
logRecordProcessorForceFlush LogRecordProcessor
processor
Maybe FlushResult
mresult <-
Int -> IO FlushResult -> IO (Maybe FlushResult)
forall a. Int -> IO a -> IO (Maybe a)
timeout (Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
5_000_000 Maybe Int
mtimeout) (IO FlushResult -> IO (Maybe FlushResult))
-> IO FlushResult -> IO (Maybe FlushResult)
forall a b. (a -> b) -> a -> b
$
(FlushResult -> Async () -> IO FlushResult)
-> FlushResult -> Vector (Async ()) -> IO FlushResult
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> m a) -> a -> Vector b -> m a
V.foldM
( \FlushResult
status Async ()
action -> do
Either SomeException ()
res <- Async () -> IO (Either SomeException ())
forall a. Async a -> IO (Either SomeException a)
waitCatch Async ()
action
FlushResult -> IO FlushResult
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FlushResult -> IO FlushResult) -> FlushResult -> IO FlushResult
forall a b. (a -> b) -> a -> b
$! case Either SomeException ()
res of
Left SomeException
_err -> FlushResult
FlushError
Right ()
_ok -> FlushResult
status
)
FlushResult
FlushSuccess
Vector (Async ())
jobs
case Maybe FlushResult
mresult of
Maybe FlushResult
Nothing -> FlushResult -> IO FlushResult
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FlushResult
FlushTimeout
Just FlushResult
res -> FlushResult -> IO FlushResult
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FlushResult
res
makeLogger
:: LoggerProvider
-> InstrumentationLibrary
-> Logger
makeLogger :: LoggerProvider -> InstrumentationLibrary -> Logger
makeLogger LoggerProvider
loggerLoggerProvider InstrumentationLibrary
loggerInstrumentationScope = Logger {InstrumentationLibrary
LoggerProvider
loggerLoggerProvider :: LoggerProvider
loggerInstrumentationScope :: InstrumentationLibrary
loggerInstrumentationScope :: InstrumentationLibrary
loggerLoggerProvider :: LoggerProvider
..}
createImmutableLogRecord
:: (MonadIO m)
=> LA.AttributeLimits
-> LogRecordArguments
-> m ImmutableLogRecord
createImmutableLogRecord :: forall (m :: * -> *).
MonadIO m =>
AttributeLimits -> LogRecordArguments -> m ImmutableLogRecord
createImmutableLogRecord AttributeLimits
attributeLimits LogRecordArguments {Maybe Text
Maybe Timestamp
Maybe Context
Maybe SeverityNumber
HashMap Text AnyValue
AnyValue
timestamp :: Maybe Timestamp
observedTimestamp :: Maybe Timestamp
context :: Maybe Context
severityText :: Maybe Text
severityNumber :: Maybe SeverityNumber
body :: AnyValue
attributes :: HashMap Text AnyValue
timestamp :: LogRecordArguments -> Maybe Timestamp
observedTimestamp :: LogRecordArguments -> Maybe Timestamp
context :: LogRecordArguments -> Maybe Context
severityText :: LogRecordArguments -> Maybe Text
severityNumber :: LogRecordArguments -> Maybe SeverityNumber
body :: LogRecordArguments -> AnyValue
attributes :: LogRecordArguments -> HashMap Text AnyValue
..} = do
Timestamp
currentTimestamp <- m Timestamp
forall (m :: * -> *). MonadIO m => m Timestamp
getCurrentTimestamp
let logRecordObservedTimestamp :: Timestamp
logRecordObservedTimestamp = Timestamp -> Maybe Timestamp -> Timestamp
forall a. a -> Maybe a -> a
fromMaybe Timestamp
currentTimestamp Maybe Timestamp
observedTimestamp
Maybe (TraceId, SpanId, TraceFlags)
logRecordTracingDetails <- MaybeT m (TraceId, SpanId, TraceFlags)
-> m (Maybe (TraceId, SpanId, TraceFlags))
forall (m :: * -> *) a. MaybeT m a -> m (Maybe a)
runMaybeT (MaybeT m (TraceId, SpanId, TraceFlags)
-> m (Maybe (TraceId, SpanId, TraceFlags)))
-> MaybeT m (TraceId, SpanId, TraceFlags)
-> m (Maybe (TraceId, SpanId, TraceFlags))
forall a b. (a -> b) -> a -> b
$ do
Context
currentContext <- IO Context -> MaybeT m Context
forall a. IO a -> MaybeT m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO Context
forall (m :: * -> *). MonadIO m => m Context
getContext
Span
currentSpan <- m (Maybe Span) -> MaybeT m Span
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe Span) -> MaybeT m Span)
-> m (Maybe Span) -> MaybeT m Span
forall a b. (a -> b) -> a -> b
$ Maybe Span -> m (Maybe Span)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Maybe Span -> m (Maybe Span)) -> Maybe Span -> m (Maybe Span)
forall a b. (a -> b) -> a -> b
$ Context -> Maybe Span
lookupSpan (Context -> Maybe Span) -> Context -> Maybe Span
forall a b. (a -> b) -> a -> b
$ Context -> Maybe Context -> Context
forall a. a -> Maybe a -> a
fromMaybe Context
currentContext Maybe Context
context
SpanContext {TraceId
traceId :: TraceId
traceId :: SpanContext -> TraceId
traceId, SpanId
spanId :: SpanId
spanId :: SpanContext -> SpanId
spanId, TraceFlags
traceFlags :: TraceFlags
traceFlags :: SpanContext -> TraceFlags
traceFlags} <- Span -> MaybeT m SpanContext
forall (m :: * -> *). MonadIO m => Span -> m SpanContext
getSpanContext Span
currentSpan
(TraceId, SpanId, TraceFlags)
-> MaybeT m (TraceId, SpanId, TraceFlags)
forall a. a -> MaybeT m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TraceId
traceId, SpanId
spanId, TraceFlags
traceFlags)
let logRecordAttributes :: LogAttributes
logRecordAttributes =
AttributeLimits
-> LogAttributes -> HashMap Text AnyValue -> LogAttributes
forall a.
ToValue a =>
AttributeLimits -> LogAttributes -> HashMap Text a -> LogAttributes
LA.addAttributes
AttributeLimits
attributeLimits
LogAttributes
LA.emptyAttributes
HashMap Text AnyValue
attributes
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (LogAttributes -> Int
LA.attributesDropped LogAttributes
logRecordAttributes Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ m ReadWriteLogRecord -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void m ReadWriteLogRecord
forall (m :: * -> *). MonadIO m => m ReadWriteLogRecord
logDroppedAttributes
ImmutableLogRecord -> m ImmutableLogRecord
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
ImmutableLogRecord
{ logRecordTimestamp :: Maybe Timestamp
logRecordTimestamp = Maybe Timestamp
timestamp
, Timestamp
logRecordObservedTimestamp :: Timestamp
logRecordObservedTimestamp :: Timestamp
logRecordObservedTimestamp
, Maybe (TraceId, SpanId, TraceFlags)
logRecordTracingDetails :: Maybe (TraceId, SpanId, TraceFlags)
logRecordTracingDetails :: Maybe (TraceId, SpanId, TraceFlags)
logRecordTracingDetails
, logRecordSeverityNumber :: Maybe SeverityNumber
logRecordSeverityNumber = Maybe SeverityNumber
severityNumber
, logRecordSeverityText :: Maybe Text
logRecordSeverityText = Maybe Text
severityText Maybe Text -> Maybe Text -> Maybe Text
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (SeverityNumber -> Maybe Text
toShortName (SeverityNumber -> Maybe Text)
-> Maybe SeverityNumber -> Maybe Text
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< Maybe SeverityNumber
severityNumber)
, logRecordBody :: AnyValue
logRecordBody = AnyValue
body
, LogAttributes
logRecordAttributes :: LogAttributes
logRecordAttributes :: LogAttributes
logRecordAttributes
}
logDroppedAttributes :: (MonadIO m) => m ReadWriteLogRecord
logDroppedAttributes :: forall (m :: * -> *). MonadIO m => m ReadWriteLogRecord
logDroppedAttributes = HashMap Text AnyValue
-> SeverityNumber -> Text -> m ReadWriteLogRecord
forall (m :: * -> *).
MonadIO m =>
HashMap Text AnyValue
-> SeverityNumber -> Text -> m ReadWriteLogRecord
emitOTelLogRecord HashMap Text AnyValue
forall k v. HashMap k v
H.empty SeverityNumber
Warn Text
"At least 1 attribute was discarded due to the attribute limits set in the logger provider."
emitOTelLogRecord :: (MonadIO m) => H.HashMap Text LA.AnyValue -> SeverityNumber -> Text -> m ReadWriteLogRecord
emitOTelLogRecord :: forall (m :: * -> *).
MonadIO m =>
HashMap Text AnyValue
-> SeverityNumber -> Text -> m ReadWriteLogRecord
emitOTelLogRecord HashMap Text AnyValue
attrs SeverityNumber
severity Text
bodyText = do
LoggerProvider
glp <- m LoggerProvider
forall (m :: * -> *). MonadIO m => m LoggerProvider
getGlobalLoggerProvider
let gl :: Logger
gl =
LoggerProvider -> InstrumentationLibrary -> Logger
makeLogger LoggerProvider
glp (InstrumentationLibrary -> Logger)
-> InstrumentationLibrary -> Logger
forall a b. (a -> b) -> a -> b
$
InstrumentationLibrary
{ libraryName :: Text
libraryName = Text
"hs-opentelemetry-api"
, libraryVersion :: Text
libraryVersion = String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Version -> String
showVersion Version
version
, librarySchemaUrl :: Text
librarySchemaUrl = Text
""
, libraryAttributes :: Attributes
libraryAttributes = Attributes
A.emptyAttributes
}
Logger -> LogRecordArguments -> m ReadWriteLogRecord
forall (m :: * -> *).
MonadIO m =>
Logger -> LogRecordArguments -> m ReadWriteLogRecord
emitLogRecord Logger
gl (LogRecordArguments -> m ReadWriteLogRecord)
-> LogRecordArguments -> m ReadWriteLogRecord
forall a b. (a -> b) -> a -> b
$
LogRecordArguments
emptyLogRecordArguments
{ severityNumber = Just severity
, body = toValue bodyText
, attributes = attrs
}
emitLogRecord
:: (MonadIO m)
=> Logger
-> LogRecordArguments
-> m ReadWriteLogRecord
emitLogRecord :: forall (m :: * -> *).
MonadIO m =>
Logger -> LogRecordArguments -> m ReadWriteLogRecord
emitLogRecord Logger
l LogRecordArguments
args = do
let LoggerProvider {Vector LogRecordProcessor
loggerProviderProcessors :: LoggerProvider -> Vector LogRecordProcessor
loggerProviderProcessors :: Vector LogRecordProcessor
loggerProviderProcessors, AttributeLimits
loggerProviderAttributeLimits :: LoggerProvider -> AttributeLimits
loggerProviderAttributeLimits :: AttributeLimits
loggerProviderAttributeLimits} = Logger -> LoggerProvider
loggerLoggerProvider Logger
l
ImmutableLogRecord
ilr <- AttributeLimits -> LogRecordArguments -> m ImmutableLogRecord
forall (m :: * -> *).
MonadIO m =>
AttributeLimits -> LogRecordArguments -> m ImmutableLogRecord
createImmutableLogRecord AttributeLimits
loggerProviderAttributeLimits LogRecordArguments
args
ReadWriteLogRecord
lr <- IO ReadWriteLogRecord -> m ReadWriteLogRecord
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ReadWriteLogRecord -> m ReadWriteLogRecord)
-> IO ReadWriteLogRecord -> m ReadWriteLogRecord
forall a b. (a -> b) -> a -> b
$ Logger -> ImmutableLogRecord -> IO ReadWriteLogRecord
mkReadWriteLogRecord Logger
l ImmutableLogRecord
ilr
Context
ctxt <- m Context
forall (m :: * -> *). MonadIO m => m Context
getContext
(LogRecordProcessor -> m ()) -> Vector LogRecordProcessor -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\LogRecordProcessor
processor -> IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ LogRecordProcessor -> ReadWriteLogRecord -> Context -> IO ()
logRecordProcessorOnEmit LogRecordProcessor
processor ReadWriteLogRecord
lr Context
ctxt) Vector LogRecordProcessor
loggerProviderProcessors
ReadWriteLogRecord -> m ReadWriteLogRecord
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ReadWriteLogRecord
lr
addAttribute :: (IsReadWriteLogRecord r, MonadIO m, ToValue a) => r -> Text -> a -> m ()
addAttribute :: forall r (m :: * -> *) a.
(IsReadWriteLogRecord r, MonadIO m, ToValue a) =>
r -> Text -> a -> m ()
addAttribute r
lr Text
k a
v =
let attributeLimits :: AttributeLimits
attributeLimits = r -> AttributeLimits
forall r. IsReadWriteLogRecord r => r -> AttributeLimits
readLogRecordAttributeLimits r
lr
in IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$
r -> (ImmutableLogRecord -> ImmutableLogRecord) -> IO ()
forall r.
IsReadWriteLogRecord r =>
r -> (ImmutableLogRecord -> ImmutableLogRecord) -> IO ()
modifyLogRecord
r
lr
( \ilr :: ImmutableLogRecord
ilr@ImmutableLogRecord {LogAttributes
logRecordAttributes :: ImmutableLogRecord -> LogAttributes
logRecordAttributes :: LogAttributes
logRecordAttributes} ->
ImmutableLogRecord
ilr
{ logRecordAttributes =
LA.addAttribute
attributeLimits
logRecordAttributes
k
v
}
)
addAttributes :: (IsReadWriteLogRecord r, MonadIO m, ToValue a) => r -> HashMap Text a -> m ()
addAttributes :: forall r (m :: * -> *) a.
(IsReadWriteLogRecord r, MonadIO m, ToValue a) =>
r -> HashMap Text a -> m ()
addAttributes r
lr HashMap Text a
attrs =
let attributeLimits :: AttributeLimits
attributeLimits = r -> AttributeLimits
forall r. IsReadWriteLogRecord r => r -> AttributeLimits
readLogRecordAttributeLimits r
lr
in IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$
r -> (ImmutableLogRecord -> ImmutableLogRecord) -> IO ()
forall r.
IsReadWriteLogRecord r =>
r -> (ImmutableLogRecord -> ImmutableLogRecord) -> IO ()
modifyLogRecord
r
lr
( \ilr :: ImmutableLogRecord
ilr@ImmutableLogRecord {LogAttributes
logRecordAttributes :: ImmutableLogRecord -> LogAttributes
logRecordAttributes :: LogAttributes
logRecordAttributes} ->
ImmutableLogRecord
ilr
{ logRecordAttributes =
LA.addAttributes
attributeLimits
logRecordAttributes
attrs
}
)
logRecordGetAttributes :: (IsReadableLogRecord r, MonadIO m) => r -> m LogAttributes
logRecordGetAttributes :: forall r (m :: * -> *).
(IsReadableLogRecord r, MonadIO m) =>
r -> m LogAttributes
logRecordGetAttributes r
lr = IO LogAttributes -> m LogAttributes
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO LogAttributes -> m LogAttributes)
-> IO LogAttributes -> m LogAttributes
forall a b. (a -> b) -> a -> b
$ ImmutableLogRecord -> LogAttributes
logRecordAttributes (ImmutableLogRecord -> LogAttributes)
-> IO ImmutableLogRecord -> IO LogAttributes
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> r -> IO ImmutableLogRecord
forall r. IsReadableLogRecord r => r -> IO ImmutableLogRecord
readLogRecord r
lr