25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-22 16:20:52 +01:00

Make connected_users_info and user_sessions_info DB-agnostic (#2448)

The result returned by connected_users_info command has changed,
and is now similar to the result of user_sessions_info.

Notice that num_active_users and process_rosteritems still require Mnesia.
This commit is contained in:
Badlop 2018-06-15 11:28:44 +02:00
parent 6c323b729b
commit 3ec623f329
2 changed files with 47 additions and 69 deletions

View File

@ -242,10 +242,12 @@ get_user_info(User, Server) ->
LServer = jid:nameprep(Server), LServer = jid:nameprep(Server),
Mod = get_sm_backend(LServer), Mod = get_sm_backend(LServer),
Ss = online(get_sessions(Mod, LUser, LServer)), Ss = online(get_sessions(Mod, LUser, LServer)),
[{LResource, [{node, node(Pid)}|Info]} [{LResource, [{node, node(Pid)}, {ts, Ts}, {pid, Pid},
{priority, Priority} | Info]}
|| #session{usr = {_, _, LResource}, || #session{usr = {_, _, LResource},
priority = Priority,
info = Info, info = Info,
sid = {_, Pid}} <- clean_session_list(Ss)]. sid = {Ts, Pid}} <- clean_session_list(Ss)].
-spec get_user_info(binary(), binary(), binary()) -> info() | offline. -spec get_user_info(binary(), binary(), binary()) -> info() | offline.
@ -259,8 +261,11 @@ get_user_info(User, Server, Resource) ->
offline; offline;
Ss -> Ss ->
Session = lists:max(Ss), Session = lists:max(Ss),
Node = node(element(2, Session#session.sid)), {Ts, Pid} = Session#session.sid,
[{node, Node}|Session#session.info] Node = node(Pid),
Priority = Session#session.priority,
[{node, Node}, {ts, Ts}, {pid, Pid}, {priority, Priority}
|Session#session.info]
end. end.
-spec set_presence(sid(), binary(), binary(), binary(), -spec set_presence(sid(), binary(), binary(), binary(),

View File

@ -166,7 +166,7 @@ get_commands_spec() ->
" - 1: error: module not loaded\n" " - 1: error: module not loaded\n"
" - 2: code not reloaded, but module restarted"}, " - 2: code not reloaded, but module restarted"},
#ejabberd_commands{name = num_active_users, tags = [accounts, stats], #ejabberd_commands{name = num_active_users, tags = [accounts, stats],
desc = "Get number of users active in the last days", desc = "Get number of users active in the last days (only Mnesia)",
policy = admin, policy = admin,
module = ?MODULE, function = num_active_users, module = ?MODULE, function = num_active_users,
args = [{host, binary}, {days, integer}], args = [{host, binary}, {days, integer}],
@ -341,20 +341,25 @@ get_commands_spec() ->
desc = "List all established sessions and their information", desc = "List all established sessions and their information",
module = ?MODULE, function = connected_users_info, module = ?MODULE, function = connected_users_info,
args = [], args = [],
result_example = [{"user1@myserver.com/tka", "c2s", "127.0.0.1", result_example = [{"user1@myserver.com/tka",
40092, 8, "ejabberd@localhost", 28}], "c2s", "127.0.0.1", 42656,8, "ejabberd@localhost",
231, <<"dnd">>, <<"tka">>, <<>>}],
result = {connected_users_info, result = {connected_users_info,
{list, {list,
{sessions, {tuple, {session, {tuple,
[{jid, string}, [{jid, string},
{connection, string}, {connection, string},
{ip, string}, {ip, string},
{port, integer}, {port, integer},
{priority, integer}, {priority, integer},
{node, string}, {node, string},
{uptime, integer} {uptime, integer},
{status, string},
{resource, string},
{statustext, string}
]}} ]}}
}}}, }}},
#ejabberd_commands{name = connected_users_vhost, #ejabberd_commands{name = connected_users_vhost,
tags = [session], tags = [session],
desc = "Get the list of established sessions in a vhost", desc = "Get the list of established sessions in a vhost",
@ -1046,41 +1051,18 @@ get_status_list(Host, Status_required) ->
apply(Fstatus, [Status, Status_required])]. apply(Fstatus, [Status, Status_required])].
connected_users_info() -> connected_users_info() ->
USRIs = dirty_get_sessions_list2(),
CurrentSec = calendar:datetime_to_gregorian_seconds({date(), time()}),
lists:map( lists:map(
fun([{U, S, R}, {Now, Pid}, Priority, Info]) -> fun({U, S, R}) ->
Conn = proplists:get_value(conn, Info), Info = user_session_info(U, S, R),
{Ip, Port} = proplists:get_value(ip, Info), Jid = jid:encode(jid:make(U, S, R)),
IPS = inet_parse:ntoa(Ip), erlang:insert_element(1, Info, Jid)
NodeS = atom_to_list(node(Pid)),
Uptime = CurrentSec - calendar:datetime_to_gregorian_seconds(
calendar:now_to_local_time(Now)),
PriorityI = case Priority of
PI when is_integer(PI) -> PI;
_ -> nil
end, end,
{binary_to_list(<<U/binary, $@, S/binary, $/, R/binary>>), ejabberd_sm:dirty_get_sessions_list()).
atom_to_list(Conn), IPS, Port, PriorityI, NodeS, Uptime}
end,
USRIs).
connected_users_vhost(Host) -> connected_users_vhost(Host) ->
USRs = ejabberd_sm:get_vh_session_list(Host), USRs = ejabberd_sm:get_vh_session_list(Host),
[ jid:encode(jid:make(USR)) || USR <- USRs]. [ jid:encode(jid:make(USR)) || USR <- USRs].
%% Code copied from ejabberd_sm.erl and customized
dirty_get_sessions_list2() ->
Ss = mnesia:dirty_select(
session,
[{#session{usr = '$1', sid = '$2', priority = '$3', info = '$4',
_ = '_'},
[],
[['$1', '$2', '$3', '$4']]}]),
lists:filter(fun([_USR, _SID, _Priority, Info]) ->
not proplists:get_bool(offline, Info)
end, Ss).
%% Make string more print-friendly %% Make string more print-friendly
stringize(String) -> stringize(String) ->
%% Replace newline characters with other code %% Replace newline characters with other code
@ -1129,32 +1111,23 @@ set_presence(User, Host, Resource, Type, Show, Status, Priority0) ->
ejabberd_c2s:set_presence(Ref, Pres). ejabberd_c2s:set_presence(Ref, Pres).
user_sessions_info(User, Host) -> user_sessions_info(User, Host) ->
[user_session_info(User, Host, Resource) ||
Resource <- ejabberd_sm:get_user_resources(User, Host)].
user_session_info(User, Host, Resource) ->
CurrentSec = calendar:datetime_to_gregorian_seconds({date(), time()}), CurrentSec = calendar:datetime_to_gregorian_seconds({date(), time()}),
US = {User, Host}, Info = ejabberd_sm:get_user_info(User, Host, Resource),
Sessions = case catch mnesia:dirty_index_read(session, US, #session.us) of Now = proplists:get_value(ts, Info),
{'EXIT', _Reason} -> Pid = proplists:get_value(pid, Info),
[];
Ss ->
lists:filter(fun(#session{info = Info}) ->
not proplists:get_bool(offline, Info)
end, Ss)
end,
lists:map(
fun(Session) ->
{_U, _S, Resource} = Session#session.usr,
{Now, Pid} = Session#session.sid,
{_U, _Resource, Status, StatusText} = get_presence(Pid), {_U, _Resource, Status, StatusText} = get_presence(Pid),
Info = Session#session.info, Priority = proplists:get_value(priority, Info),
Priority = Session#session.priority,
Conn = proplists:get_value(conn, Info), Conn = proplists:get_value(conn, Info),
{Ip, Port} = proplists:get_value(ip, Info), {Ip, Port} = proplists:get_value(ip, Info),
IPS = inet_parse:ntoa(Ip), IPS = inet_parse:ntoa(Ip),
NodeS = atom_to_list(node(Pid)), NodeS = atom_to_list(node(Pid)),
Uptime = CurrentSec - calendar:datetime_to_gregorian_seconds( Uptime = CurrentSec - calendar:datetime_to_gregorian_seconds(
calendar:now_to_local_time(Now)), calendar:now_to_local_time(Now)),
{atom_to_list(Conn), IPS, Port, Priority, NodeS, Uptime, Status, Resource, StatusText} {atom_to_list(Conn), IPS, Port, Priority, NodeS, Uptime, Status, Resource, StatusText}.
end,
Sessions).
%%% %%%