0 | ||| The Loggable interface for structured log values.
  1 | |||
  2 | ||| `Loggable` describes how a type renders into structured log fields,
  3 | ||| independent of the output format. A single `Loggable` instance works
  4 | ||| with any `LogRenderer` -- JSON, text, key-value pairs, etc.
  5 | module Log4Types.Core.Loggable
  6 |
  7 | import Data.List
  8 | import Log4Types.Core.Value
  9 | import Log4Types.Core.Renderer
 10 |
 11 | %default total
 12 |
 13 | ----------------------------------------------------------------------
 14 | -- Loggable interface
 15 | ----------------------------------------------------------------------
 16 |
 17 | ||| Typeclass for types that can be rendered as structured log data.
 18 | |||
 19 | ||| Implement `logFields` to describe how your type contributes fields
 20 | ||| to a log entry, and `logShow` for human-readable display.
 21 | public export
 22 | interface Loggable a where
 23 |   ||| Render all structured fields of this value into the renderer.
 24 |   logFields : LogRenderer r -> a -> r -> r
 25 |
 26 |   ||| Human-readable string representation for log messages.
 27 |   logShow : a -> String
 28 |
 29 | ----------------------------------------------------------------------
 30 | -- LoggedValue existential
 31 | ----------------------------------------------------------------------
 32 |
 33 | ||| An existentially-wrapped loggable value.
 34 | |||
 35 | ||| Packages a value together with its `Loggable` evidence so it can
 36 | ||| be stored in heterogeneous collections and passed without carrying
 37 | ||| the type parameter.
 38 | public export
 39 | data LoggedValue : Type where
 40 |   MkLoggedValue : Loggable a => (val : a) -> LoggedValue
 41 |
 42 | ||| Render the fields of a LoggedValue using the given renderer.
 43 | public export
 44 | loggedValueFields : LogRenderer r -> LoggedValue -> r -> r
 45 | loggedValueFields renderer (MkLoggedValue val) = logFields renderer val
 46 |
 47 | ||| Show a LoggedValue using its Loggable instance.
 48 | public export
 49 | loggedValueShow : LoggedValue -> String
 50 | loggedValueShow (MkLoggedValue val) = logShow val
 51 |
 52 | public export
 53 | Show LoggedValue where
 54 |   show = loggedValueShow
 55 |
 56 | ----------------------------------------------------------------------
 57 | -- Built-in instances
 58 | ----------------------------------------------------------------------
 59 |
 60 | public export
 61 | Loggable String where
 62 |   logFields renderer s acc = renderer.addField "value" (StrVal s) acc
 63 |   logShow = id
 64 |
 65 | public export
 66 | Loggable Int where
 67 |   logFields renderer i acc = renderer.addField "value" (IntVal $ cast i) acc
 68 |   logShow = show
 69 |
 70 | public export
 71 | Loggable Integer where
 72 |   logFields renderer i acc = renderer.addField "value" (IntVal i) acc
 73 |   logShow = show
 74 |
 75 | public export
 76 | Loggable Nat where
 77 |   logFields renderer n acc = renderer.addField "value" (IntVal $ cast n) acc
 78 |   logShow = show
 79 |
 80 | public export
 81 | Loggable Double where
 82 |   logFields renderer d acc = renderer.addField "value" (FloatVal d) acc
 83 |   logShow = show
 84 |
 85 | public export
 86 | Loggable Bool where
 87 |   logFields renderer b acc = renderer.addField "value" (BoolVal b) acc
 88 |   logShow = show
 89 |
 90 | public export
 91 | Loggable a => Loggable (Maybe a) where
 92 |   logFields renderer Nothing  acc = acc
 93 |   logFields renderer (Just x) acc = logFields renderer x acc
 94 |   logShow Nothing  = "Nothing"
 95 |   logShow (Just x) = logShow x
 96 |
 97 | public export
 98 | Loggable a => Loggable (List a) where
 99 |   logFields renderer xs acc = foldl (\a, x => logFields renderer x a) acc xs
100 |   logShow xs = "[" ++ concat (intersperse ", " (map logShow xs)) ++ "]"
101 |
102 | public export
103 | Loggable LogParamValue where
104 |   logFields renderer v acc = renderer.addField "value" v acc
105 |   logShow = show
106 |