fluxer/fluxer_gateway/src/telemetry/process_memory_stats.erl
2026-01-01 21:05:54 +00:00

98 lines
3.6 KiB
Erlang

%% Copyright (C) 2026 Fluxer Contributors
%%
%% This file is part of Fluxer.
%%
%% Fluxer is free software: you can redistribute it and/or modify
%% it under the terms of the GNU Affero General Public License as published by
%% the Free Software Foundation, either version 3 of the License, or
%% (at your option) any later version.
%%
%% Fluxer is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%% GNU Affero General Public License for more details.
%%
%% You should have received a copy of the GNU Affero General Public License
%% along with Fluxer. If not, see <https://www.gnu.org/licenses/>.
-module(process_memory_stats).
-export([get_guild_memory_stats/1]).
get_guild_memory_stats(Limit) ->
AllProcesses = erlang:processes(),
GuildProcessInfos = lists:filtermap(
fun(Pid) ->
case get_guild_process_info(Pid) of
undefined -> false;
Info -> {true, Info}
end
end,
AllProcesses
),
Sorted = lists:sort(
fun(#{memory := M1}, #{memory := M2}) -> M1 >= M2 end,
GuildProcessInfos
),
lists:sublist(Sorted, Limit).
get_guild_process_info(Pid) ->
case erlang:process_info(Pid, [registered_name, memory, initial_call, dictionary]) of
undefined ->
undefined;
InfoList ->
Memory = proplists:get_value(memory, InfoList, 0),
InitialCall = proplists:get_value(initial_call, InfoList),
Dictionary = proplists:get_value(dictionary, InfoList, []),
Module =
case lists:keyfind('$initial_call', 1, Dictionary) of
{'$initial_call', {M, _, _}} ->
M;
_ ->
case InitialCall of
{M, _, _} -> M;
_ -> undefined
end
end,
case Module of
guild ->
case catch sys:get_state(Pid, 100) of
State when is_map(State) ->
GuildId = maps:get(id, State, undefined),
Data = maps:get(data, State, #{}),
Guild = maps:get(<<"guild">>, Data, #{}),
GuildName = maps:get(<<"name">>, Guild, <<"Unknown">>),
GuildIcon = maps:get(<<"icon">>, Guild, null),
Members = maps:get(<<"members">>, Data, []),
MemberCount = length(Members),
SessionCount = map_size(maps:get(sessions, State, #{})),
PresenceCount = map_size(maps:get(presences, State, #{})),
#{
guild_id =>
case GuildId of
undefined -> null;
Id -> integer_to_binary(Id)
end,
guild_name => GuildName,
guild_icon => GuildIcon,
memory => Memory,
member_count => MemberCount,
session_count => SessionCount,
presence_count => PresenceCount
};
_ ->
undefined
end;
_ ->
undefined
end
end.