0 | ||| JSON backend for log4types structured logging.
 1 | |||
 2 | ||| Provides a `LogRenderer` that builds `Language.JSON.JSON` values,
 3 | ||| and encoding functions for producing JSON log lines from messages.
 4 | module Log4Types.JSON
 5 |
 6 | import Language.JSON
 7 | import Log4Types.Core
 8 |
 9 | %default total
10 |
11 | ----------------------------------------------------------------------
12 | -- JSON Renderer
13 | ----------------------------------------------------------------------
14 |
15 | ||| A LogRenderer that builds JSON objects.
16 | |||
17 | ||| Fields are accumulated as key-value pairs in a `JObject`.
18 | ||| Nested objects are represented as sub-objects.
19 | public export
20 | jsonRenderer : LogRenderer JSON
21 | jsonRenderer = MkLogRenderer
22 |   { addField  = \name, val, acc => mergeField name (paramToJSON val) acc
23 |   , addNested = \name, build, acc => mergeField name (build JNull) acc
24 |   , empty     = JObject []
25 |   , combine   = mergeJSON
26 |   }
27 |   where
28 |     paramToJSON : LogParamValue -> JSON
29 |     paramToJSON (StrVal s)   = JString s
30 |     paramToJSON (IntVal i)   = JNumber (cast i)
31 |     paramToJSON (FloatVal f) = JNumber f
32 |     paramToJSON (BoolVal b)  = JBoolean b
33 |     paramToJSON NullVal      = JNull
34 |
35 |     mergeField : String -> JSON -> JSON -> JSON
36 |     mergeField name val (JObject fields) = JObject (fields ++ [(name, val)])
37 |     mergeField name val _                = JObject [(name, val)]
38 |
39 |     mergeJSON : JSON -> JSON -> JSON
40 |     mergeJSON (JObject xs) (JObject ys) = JObject (xs ++ ys)
41 |     mergeJSON (JObject xs) _            = JObject xs
42 |     mergeJSON _            (JObject ys) = JObject ys
43 |     mergeJSON _            _            = JObject []
44 |
45 | ----------------------------------------------------------------------
46 | -- Encoding
47 | ----------------------------------------------------------------------
48 |
49 | ||| Convert a LogParamValue to a JSON value.
50 | public export
51 | paramValueToJSON : LogParamValue -> JSON
52 | paramValueToJSON (StrVal s)   = JString s
53 | paramValueToJSON (IntVal i)   = JNumber (cast i)
54 | paramValueToJSON (FloatVal f) = JNumber f
55 | paramValueToJSON (BoolVal b)  = JBoolean b
56 | paramValueToJSON NullVal      = JNull
57 |
58 | ||| Encode any Loggable value as a JSON object.
59 | public export
60 | encodeLoggable : Loggable a => a -> JSON
61 | encodeLoggable val = logFields jsonRenderer val (JObject [])
62 |
63 | ||| Encode any Loggable value as a JSON string.
64 | public export
65 | encodeLoggableStr : Loggable a => a -> String
66 | encodeLoggableStr = show . encodeLoggable
67 |
68 | ----------------------------------------------------------------------
69 | -- JSON Log Action
70 | ----------------------------------------------------------------------
71 |
72 | ||| A log action that encodes Loggable values as JSON lines to stdout.
73 | public export
74 | jsonLogStdout : (HasIO io, Loggable a) => LogAction io a
75 | jsonLogStdout = MkLogAction $ putStrLn . encodeLoggableStr
76 |