1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
let = []
let protect s =
let len = String.length s in
let buf = Buffer.create len in
String.iter
(fun ch ->
match ch with
| '<' -> Buffer.add_string buf "<"
| '>' -> Buffer.add_string buf ">"
| '\"' -> Buffer.add_string buf """
| '&' -> Buffer.add_string buf "&"
| _ -> Buffer.add_char buf ch)
s;
Buffer.contents buf
let protect_cdata s =
let len = String.length s in
let buf = Buffer.create len in
let i = ref 0 in
while (!i < len) do
if (!i >= 2) && (s.[!i - 2] = ']') && (s.[!i - 1] = ']') && (s.[!i] = '>') then
Buffer.add_string buf " >"
else
Buffer.add_char buf s.[!i];
incr i
done;
Buffer.contents buf
let render e =
let properties =
List.map
(fun (k, v) ->
Printf.sprintf " <log4j:data name=\"%s\" value=\"%s\"/>\n"
(protect k)
(protect v))
e.Event.properties in
Event.render_bindings
(List.map
(fun (k, v) -> (k, (if k = "message" then protect_cdata v else protect v)))
(Event.bindings e))
("<log4j:event logger=\"$(logger)\" level=\"$(level)\" thread=\"$(thread)\" timestamp=\"$(time)\">\n" ^
"<log4j:message><![CDATA[$(message)]]></log4j:message>\n" ^
(match e.Event.error with
| Some (_, s) -> "<log4j:throwable><![CDATA[" ^ (protect_cdata s) ^ "]]></log4j:throwable>\n"
| None -> "") ^
"<log4j:locationInfo class=\"Unknown\" method=\"unknown()\" file=\"$(file)\" line=\"$(line)\"/>\n" ^
"<log4j:properties>\n" ^
(String.concat "" properties) ^
"</log4j:properties>\n" ^
"</log4j:event>\n")
let layout = header, [], render
let () =
List.iter
(fun (x, y) -> Layout.register x y)
[ "xml", layout ;
"log4j", layout ]