@@ -26,7 +26,6 @@ import Control.Monad.Trans.State
26import Control.Monad.Trans.Writer
26import Control.Monad.Trans.Writer
27import Data.Aeson (ToJSON (..))
27import Data.Aeson (ToJSON (..))
28import qualified Data.Aeson as A
28import qualified Data.Aeson as A
29−import Data.Aeson.Lens
30import Data.Foldable (foldMap)
29import Data.Foldable (foldMap)
31import qualified Data.HashMap.Strict as HM
30import qualified Data.HashMap.Strict as HM
32import Data.List
31import Data.List
@@ -198,6 +197,26 @@ instance Monoid PayloadSelection where
198 mappend _ AllKeys = AllKeys
197 mappend _ AllKeys = AllKeys
199 mappend (SomeKeys as) (SomeKeys bs) = SomeKeys (as++bs)
198 mappend (SomeKeys as) (SomeKeys bs) = SomeKeys (as++bs)
201+-------------------------------------------------------------------------------
202+-- | Katip requires JSON objects to be logged as context. This
203+-- typeclass provides a default instance which uses ToJSON and
204+-- produces an empty object if 'toJSON' results in any type other than
205+-- object. If you have a type you want to log that produces an Array
206+-- or Number for example, you'll want to write an explicit instance
207+-- here. You can trivially add a ToObject instance for something with
208+-- a ToJSON instance like:
210+-- > instance ToObject Foo
211+class ToJSON a => ToObject a where
212+ toObject :: a -> A.Object
213+ toObject v = case toJSON v of
218+instance ToObject A.Object
201-------------------------------------------------------------------------------
220-------------------------------------------------------------------------------
202-- | Payload objects need instances of this class.
221-- | Payload objects need instances of this class.
@@ -205,7 +224,7 @@ instance Monoid PayloadSelection where
205-- keys for higher levels of verbosity. Each level of verbosity
224-- keys for higher levels of verbosity. Each level of verbosity
206-- automatically and recursively contains all keys from the level
225-- automatically and recursively contains all keys from the level
207-- before it.
226-- before it.
208−class ToJSON a => LogContext a where
227+class ToObject a => LogContext a where
210 -- | List of keys in the JSON object that should be included in message.
229 -- | List of keys in the JSON object that should be included in message.
211 payloadKeys :: Verbosity -> a -> PayloadSelection
230 payloadKeys :: Verbosity -> a -> PayloadSelection
@@ -217,11 +236,10 @@ instance LogContext () where payloadKeys _ _ = SomeKeys []
217-------------------------------------------------------------------------------
236-------------------------------------------------------------------------------
218-- | Constrain payload based on verbosity. Backends should use this to
237-- | Constrain payload based on verbosity. Backends should use this to
219-- automatically bubble higher verbosity levels to lower ones.
238-- automatically bubble higher verbosity levels to lower ones.
220−payloadJson :: LogContext a => Verbosity -> a -> A.Value
239+payloadObject :: LogContext a => Verbosity -> a -> A.Object
221−payloadJson verb a = case foldMap (flip payloadKeys a) [(V0)..verb] of
240+payloadObject verb a = case foldMap (flip payloadKeys a) [(V0)..verb] of
222− AllKeys -> toJSON a
241+ AllKeys -> toObject a
223− SomeKeys ks -> toJSON a
224− & _Object %~ HM.filterWithKey (\ k _ -> k `elem` ks)
242+ SomeKeys ks -> HM.filterWithKey (\ k _ -> k `elem` ks) $ toObject a
227-------------------------------------------------------------------------------
245-------------------------------------------------------------------------------
@@ -229,7 +247,7 @@ payloadJson verb a = case foldMap (flip payloadKeys a) [(V0)..verb] of
229-- payload based on the desired verbosity. Backends that push JSON
247-- payload based on the desired verbosity. Backends that push JSON
230-- messages should use this to obtain their payload.
248-- messages should use this to obtain their payload.
231itemJson :: LogContext a => Verbosity -> Item a -> A.Value
249itemJson :: LogContext a => Verbosity -> Item a -> A.Value
232−itemJson verb a = toJSON $ a & itemPayload %~ payloadJson verb
250+itemJson verb a = toJSON $ a & itemPayload %~ payloadObject verb
235-------------------------------------------------------------------------------
253-------------------------------------------------------------------------------