• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

esl / MongooseIM / 23044468042

13 Mar 2026 09:24AM UTC coverage: 85.152% (+0.003%) from 85.149%
23044468042

push

github

web-flow
Merge pull request #4656 from esl/traffic-monitor

MIM-2088 GraphQL subscription to receive all stanzas

70 of 74 new or added lines in 7 files covered. (94.59%)

6 existing lines in 4 files now uncovered.

28239 of 33163 relevant lines covered (85.15%)

41387.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.7
/src/service_traffic.erl
1
-module(service_traffic).
2

3
-behaviour(mongoose_service).
4
-behaviour(gen_server).
5

6
-include("mongoose.hrl").
7
-include("jlib.hrl").
8
-include("mongoose_config_spec.hrl").
9

10
-export([register/1]).
11
%% gen_mod API
12
-export([start/1, stop/0]).
13
-export([config_spec/0]).
14
%% hook handler
15
-export([trace_traffic/3]).
16
%% gen_server
17
-export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
18

19
-export_type([traced_packet/0]).
20

21
-type traced_packet() :: {client_to_server, jid:jid() | undefined, exml:element()}
22
                         | {server_to_client, jid:jid(), exml:element()}.
23

24
-spec start(mongoose_service:options()) -> ok.
25
start(_Opts) ->
26
    gen_hook:add_handlers(hooks()),
9✔
27
    Traffic = {service_traffic,
9✔
28
               {gen_server, start_link, [?MODULE, [], []]},
29
               permanent, 1000, supervisor, [?MODULE]},
30
    {ok, _} = ejabberd_sup:start_child(Traffic),
9✔
31
    ok.
9✔
32

33
-spec stop() -> any().
34
stop() ->
35
    gen_hook:delete_handlers(hooks()),
9✔
36
    supervisor:terminate_child(ejabberd_sup, ?MODULE),
9✔
37
    supervisor:delete_child(ejabberd_sup, ?MODULE),
9✔
38
    ok.
9✔
39

40
-spec config_spec() -> mongoose_config_spec:config_section().
41
config_spec() ->
42
    #section{}.
7,459✔
43

44
hooks() ->
45
    [{c2s_debug_traffic, global, fun ?MODULE:trace_traffic/3, #{}, 50}].
18✔
46

47
-spec register(pos_integer()) -> ok.
48
register(Limit) ->
49
    Pid = self(),
18✔
50
    gen_server:call(?MODULE, {register, {Pid, Limit}}).
18✔
51

52
-spec trace_traffic(mongoose_acc:t(), #{arg => traced_packet()}, term()) -> {ok, mongoose_acc:t()}.
53
trace_traffic(Acc, #{arg := {client_to_server, From, El}}, _) ->
54
    traffic(client_to_server, From, El),
423✔
55
    {ok, Acc};
423✔
56
trace_traffic(Acc, #{arg := {server_to_client, To, El}}, _) ->
57
    traffic(server_to_client, To, El),
342✔
58
    {ok, Acc}.
342✔
59

60
traffic(Dir, Jid, El) ->
61
    St = iolist_to_binary(fix_and_format(El)),
765✔
62
    UserPid = self(),
765✔
63
    gen_server:cast(?MODULE, {message, Dir, {UserPid, Jid}, St}),
765✔
64
    ok.
765✔
65

66

67
init([]) ->
68
    register(?MODULE, self()),
9✔
69
    {ok, #{}}.
9✔
70

71
handle_call({register, {Pid, Limit}}, _From, State) ->
72
    monitor(process, Pid),
18✔
73
    {reply, ok, register_pid(Pid, Limit, State)};
18✔
74
handle_call(_, _, State) ->
NEW
75
    {reply, ok, State}.
×
76

77
handle_cast({message, _, _, _} = Msg, State) ->
78
    State1 = maps:fold(fun(Pid, Limit, NewState) ->
765✔
79
                           send_and_count(Msg, Pid, Limit, NewState)
279✔
80
                       end, #{},
81
                       State),
82
    {noreply, State1}.
765✔
83

84
send_and_count(_Msg, Pid, 0, NewState) ->
85
    Pid ! limit_exceeded,
9✔
86
    NewState;
9✔
87
send_and_count(Msg, Pid, Limit, NewState) ->
88
    Pid ! Msg,
270✔
89
    NewState#{Pid => Limit - 1}.
270✔
90

91
handle_info({'DOWN', _, _, Pid, _}, State) ->
92
    {noreply, unregister_pid(Pid, State)}.
18✔
93

94
fix_and_format(El) when is_binary(El) ->
NEW
95
    El;
×
96
fix_and_format({xmlstreamend, _}) ->
97
    <<"</stream:stream>">>;
54✔
98
fix_and_format({Tag, Name}) ->
NEW
99
    exml:to_pretty_iolist({Tag, Name, #{}});
×
100
fix_and_format({Tag, Name, Attrs}) ->
101
    exml:to_pretty_iolist({Tag, Name, fix_attrs(Attrs)});
108✔
102
fix_and_format({Tag, Name, Attrs, Children}) ->
103
    exml:to_pretty_iolist({Tag, Name, fix_attrs(Attrs), Children}).
603✔
104

105
register_pid(Pid, Limit, State) ->
106
    State#{Pid => Limit}.
18✔
107

108
unregister_pid(Pid, State) ->
109
    maps:remove(Pid, State).
18✔
110

111
fix_attrs(Attrs) when is_map(Attrs) ->
112
    maps:filter(fun is_defined/2, Attrs).
711✔
113

NEW
114
is_defined(_, undefined) -> false;
×
115
is_defined(_, _) -> true.
1,503✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc