./ct_report/coverage/mongoose_log_filter.COVER.html

1 -module(mongoose_log_filter).
2 -export([fill_metadata_filter/2]).
3 -export([format_c2s_state_filter/2]).
4 -export([format_acc_filter/2]).
5 -export([format_packet_filter/2]).
6 -export([format_stacktrace_filter/2]).
7 -export([format_term_filter/2]).
8 -export([preserve_acc_filter/2]).
9 -export([remove_fields_filter/2]).
10 -export([filter_module/2]).
11
12 -ignore_xref([filter_module/2, format_acc_filter/2, format_c2s_state_filter/2,
13 format_packet_filter/2, format_stacktrace_filter/2, format_term_filter/2,
14 preserve_acc_filter/2, remove_fields_filter/2]).
15
16 -include("mongoose.hrl").
17 -include_lib("jid/include/jid.hrl").
18
19 %% The templater in flatlog works with meta fields.
20 %% So, we would need a filter, that takes the interesting fields
21 %% from msg to metadata.
22 -spec fill_metadata_filter(logger:log_event(), term()) -> logger:filter_return().
23 fill_metadata_filter(Event=#{msg := {report, Msg}, meta := Meta}, Fields) ->
24 16136 FieldMap = maps:with(Fields, Msg),
25 %% Remove the fields to not print them twice
26 16136 Msg2 = maps:without(Fields, Msg),
27 16136 Event#{meta => maps:merge(FieldMap, Meta), msg => {report, Msg2}};
28 fill_metadata_filter(Event, _) ->
29 1226 Event.
30
31 format_c2s_state_filter(Event=#{msg := {report, Msg=#{c2s_data := State}}}, _) ->
32
:-(
StateMap = filter_undefined(c2s_data_to_map(State)),
33 %% C2S fields have lower priority, if the field is already present in msg.
34
:-(
Msg2 = maps:merge(StateMap, maps:remove(c2s_data, Msg)),
35
:-(
Event#{msg => {report, Msg2}};
36 format_c2s_state_filter(Event, _) ->
37 8680 Event.
38
39 format_acc_filter(Event=#{msg := {report, Msg=#{acc := Acc}}}, _) ->
40 1258 FormattedAcc = format_acc(Acc),
41 1258 Msg2 = maps:merge(FormattedAcc, maps:remove(acc, Msg)),
42 1258 Event#{msg => {report, Msg2}};
43 format_acc_filter(Event, _) ->
44 7422 Event.
45
46 %% Encodes exml_packet
47 format_packet_filter(Event=#{msg := {report, Msg=#{exml_packet := Packet}}}, _) ->
48
:-(
BinPacket = exml:to_binary(Packet),
49
:-(
Msg2 = maps:put(packet, BinPacket, maps:remove(exml_packet, Msg)),
50
:-(
Event#{msg => {report, Msg2}};
51 format_packet_filter(Event, _) ->
52 8680 Event.
53
54 format_stacktrace_filter(Event=#{msg := {report, Msg=#{stacktrace := S}}}, _) ->
55 155 FmtArgs = format_stacktrace_args(S),
56 155 Msg2 = case FmtArgs of
57 150 <<>> -> Msg;
58 5 _ -> Msg#{stacktrace_args => FmtArgs}
59 end,
60 155 Msg3 = case format_stacktrace(S) of
61 42 <<>> -> Msg2;
62 113 FmtStack -> Msg2#{stacktrace => FmtStack}
63 end,
64 155 Event#{msg => {report, Msg3 }};
65 format_stacktrace_filter(Event, _) ->
66 8525 Event.
67
68 format_term_filter(Event = #{msg := {report, Msg}}, Keys) ->
69 8068 FormattedMsg = lists:foldl(fun format_value/2, Msg, Keys),
70 8068 Event#{msg => {report, FormattedMsg}};
71 format_term_filter(Event, _) ->
72 612 Event.
73
74 format_value(Key, Msg) ->
75 8068 case maps:find(Key, Msg) of
76
:-(
{ok, Value} -> Msg#{Key := format_term(Value)};
77 8068 error -> Msg
78 end.
79
80 format_acc(#{origin_pid := OriginPid, timestamp := TS, stanza := StanzaMap}) ->
81 1249 Map = format_stanza_map(StanzaMap),
82 1249 Map#{acc_timestamp => format_microseconds(TS),
83 origin_pid => format_term(OriginPid)};
84 format_acc(_) ->
85 9 #{}.
86
87 format_stanza_map(#{element := Elem, from_jid := From, to_jid := To}) ->
88 1249 #{packet => exml:to_binary(Elem),
89 from_jid => jid:to_binary(From),
90 to_jid => jid:to_binary(To)};
91 format_stanza_map(_) ->
92
:-(
#{}.
93
94 preserve_acc_filter(Event=#{msg := {report, Msg=#{acc := Acc}}}, _) ->
95
:-(
Event#{msg => {report, Msg#{acc_original => format_term(Acc)}}};
96 preserve_acc_filter(Event, _) ->
97
:-(
Event.
98
99 remove_fields_filter(Event=#{msg := {report, Msg=#{}}}, FieldNames) ->
100 8068 Msg2 = maps:without(FieldNames, Msg),
101 8068 Event#{msg => {report, Msg2}};
102 remove_fields_filter(Event, _) ->
103 612 Event.
104
105
106 c2s_data_to_map(State) ->
107
:-(
SocketMap = format_socket(mongoose_c2s:get_socket(State)),
108
:-(
Jid = mongoose_c2s:get_jid(State),
109
:-(
SocketMap#{
110 streamid => mongoose_c2s:get_stream_id(State),
111 jid => maybe_jid_to_binary(Jid),
112 user => maybe_jid_to_luser(Jid),
113 server => maybe_jid_to_lserver(Jid),
114 resource => maybe_jid_to_lresource(Jid),
115 session_started => maybe_sid_to_timestamp(mongoose_c2s:get_sid(State))}.
116
117 1249 format_term(X) -> iolist_to_binary(io_lib:format("~0p", [X])).
118
119
:-(
maybe_jid_to_binary(Jid = #jid{}) -> jid:to_binary(Jid);
120
:-(
maybe_jid_to_binary(_) -> undefined.
121
122
:-(
maybe_jid_to_luser(#jid{luser = LUser}) -> LUser;
123
:-(
maybe_jid_to_luser(_) -> undefined.
124
125
:-(
maybe_jid_to_lserver(#jid{lserver = LServer}) -> LServer;
126
:-(
maybe_jid_to_lserver(_) -> undefined.
127
128
:-(
maybe_jid_to_lresource(#jid{lresource = LResource}) -> LResource;
129
:-(
maybe_jid_to_lresource(_) -> undefined.
130
131
:-(
maybe_sid_to_timestamp({Timestamp, _Pid}) -> format_microseconds(Timestamp).
132
133 format_microseconds(N) ->
134 1249 calendar:system_time_to_rfc3339(N, [{unit, microsecond},
135 {offset, 0},
136 {time_designator, $T}]).
137
138 format_socket(undefined) ->
139
:-(
#{};
140 format_socket(Socket) ->
141
:-(
DestAddress = mongoose_c2s_socket:get_ip(Socket),
142
:-(
#{
143 transport => mongoose_c2s_socket:get_transport(Socket),
144 conn_type => mongoose_c2s_socket:get_conn_type(Socket),
145 dest_address => format_address(DestAddress)
146 }.
147
148 format_address({Address, Port}) ->
149
:-(
#{
150 address => inet:ntoa(Address),
151 port => Port
152 }.
153
154 format_stacktrace_args([{_Mod,_Fun,Args,_Info}|_]) when is_list(Args) ->
155 5 iolist_to_binary(io_lib:format("~p", [Args]));
156 format_stacktrace_args(_) ->
157 150 <<>>.
158
159 format_stacktrace(Stacktrace) ->
160 155 iolist_to_binary(do_format_stacktrace(Stacktrace)).
161
162 do_format_stacktrace([{Mod,Fun,Args,Info}|T]) when is_list(Args) ->
163 5 Arity = length(Args),
164 5 do_format_stacktrace([{Mod,Fun,Arity,Info}|T]);
165 do_format_stacktrace([{Mod,Fun,Arity,Info}|T]) ->
166 789 Line = proplists:get_value(line, Info, 0),
167 789 H = io_lib:format("~p:~p/~p:~p", [Mod, Fun, Arity, Line]),
168 789 more_format_stacktrace(H, T);
169 do_format_stacktrace([Other|T]) ->
170
:-(
H = io_lib:format("~p", [Other]),
171
:-(
more_format_stacktrace(H, T);
172 do_format_stacktrace([]) ->
173 42 [].
174
175 more_format_stacktrace(H, []) ->
176 113 [H];
177 more_format_stacktrace(H, T) ->
178 676 [H, " "|do_format_stacktrace(T)].
179
180 filter_undefined(Map) ->
181
:-(
maps:filter(fun(_, V) -> V =/= undefined end, Map).
182
183 filter_module(Event = #{meta := #{mfa := {M,_,_}}}, Modules) when is_list(Modules) ->
184
:-(
case lists:member(M, Modules) of
185 true ->
186
:-(
Event;
187 false ->
188
:-(
stop
189 end;
190 filter_module(_Event, _Modules) ->
191
:-(
stop. %% module unknown, drop
Line Hits Source