<commit_before>%%%-------------------------------------------------------------------
%%% @author <NAME>
%%% @author <NAME>
%%% @copyright (C) 2015 ACK CYFRONET AGH
%%% This software is released under the MIT license
%%% cited in 'LICENSE.txt'.
%%% @end
%%%-------------------------------------------------------------------
%%% @doc
%%% This module provides functions for gathering and calculating
%%% statistical data. They are invoked by node_manager.
%%% Some statistics require previous measurements to be calculated.
%%% In order to encapsulate this aspect inside this module, there is a
%%% dedicated record that shall be passed to all function calls.
%%% @end
%%%-------------------------------------------------------------------
-module(monitoring).
-author("<NAME>").
-author("<NAME>").

-include("logging.hrl").
-include("monitoring/monitoring.hrl").

-ifdef(TEST).
-compile(export_all).
-endif.

% Record holding all monitoring info and required measurement history.
-record(node_monitoring_state, {
    cpu_stats = [] :: [{Name :: binary(), Value :: float()}],
    mem_stats = [] :: [{Name :: binary(), Value :: float()}],
    net_stats = [] :: [{Name :: binary(), Value :: float()}],
    cpu_last = [] :: [{Name :: binary(), WorkJiffies :: integer(), TotalJiffies :: integer()}],
    net_last = [] :: [{rx_b | tx_b | rx_p | tx_p | maxthp, Name :: binary(), Value :: integer()}],
    erlang_vm_cpu = 0.0 :: float(),
    erlang_vm_mem = [] :: [{Type :: atom(), Size :: non_neg_integer()}],
    erlang_vm_processes_num = 0 :: non_neg_integer(),
    last_update_timer :: stopwatch:instance()
}).

-type node_monitoring_state() :: #node_monitoring_state{}.
-export_type([node_monitoring_state/0]).

% Files to read system stats from
-define(CPU_STATS_FILE, "/proc/stat").
-define(MEM_STATS_FILE, "/proc/meminfo").
-define(NET_STATS_FILE(_Interface, _Type), "/sys/class/net/" ++ _Interface ++ "/statistics/" ++ _Type).
-define(NET_SPEED_FILE(_Interface), "/sys/class/net/" ++ _Interface ++ "/speed").
-define(NET_DUPLEX_FILE(_Interface), "/sys/class/net/" ++ _Interface ++ "/duplex").

%% API
-export([start/0, update/1]).
-export([get_node_state/1, get_memory_stats/0]).
-export([cpu_usage/1, mem_usage/1, net_usage/1, erlang_vm_stats/1]).

%%%===================================================================
%%% API
%%%===================================================================

%%--------------------------------------------------------------------
%% @doc
%% Initializes monitoring and returns the node_monitoring_state record
%% that will be used throughout the monitoring process.
%% @end
%%--------------------------------------------------------------------
-spec start() -> #node_monitoring_state{}.
start() ->
    update(#node_monitoring_state{last_update_timer = stopwatch:start()}).


%%--------------------------------------------------------------------
%% @doc
%% Updates monitoring statistics.
%% @end
%%--------------------------------------------------------------------
-spec update(MonitoringState :: #node_monitoring_state{}) -> #node_monitoring_state{}.
update(MonitoringState) ->
    #node_monitoring_state{
        last_update_timer = LastUpdateTimer,
        cpu_last = CPULast,
        net_last = NetLast
    } = MonitoringState,

    % make sure the time difference is not zero in case the update function is
    % called twice in a very short interval, float is required for better accuracy
    TimeDiffSeconds = max(0.001, stopwatch:read_seconds(LastUpdateTimer, float)),

    {CPUStats, NewCPULast} = get_cpu_stats(CPULast),
    {NetStats, NewNetLast} = get_network_stats(NetLast, TimeDiffSeconds),
    MemStats = get_memory_stats(),
    MonitoringState#node_monitoring_state{
        last_update_timer = stopwatch:start(),
        cpu_stats = CPUStats,
        cpu_last = NewCPULast,
        mem_stats = MemStats,
        net_stats = NetStats,
        net_last = NewNetLast,
        erlang_vm_cpu = cpu_sup:util(),
        erlang_vm_mem = erlang:memory(),
        erlang_vm_processes_num = length(erlang:processes())}.


%%--------------------------------------------------------------------
%% @doc
%% Returns a #node_state{} record that contains all required information
%% about current node state and load.
%% @end
%%--------------------------------------------------------------------
-spec get_node_state(MonitoringState :: #node_monitoring_state{}) -> #node_state{}.
get_node_state(MonitoringState) ->
    CPUUsage = cpu_usage(MonitoringState),<commit_msg>VFS-8935 Minor fix in monitoring<commit_after>%%%-------------------------------------------------------------------
%%% @author <NAME>
%%% @author <NAME>
%%% @copyright (C) 2015 ACK CYFRONET AGH
%%% This software is released under the MIT license
%%% cited in 'LICENSE.txt'.
%%% @end
%%%-------------------------------------------------------------------
%%% @doc
%%% This module provides functions for gathering and calculating
%%% statistical data. They are invoked by node_manager.
%%% Some statistics require previous measurements to be calculated.
%%% In order to encapsulate this aspect inside this module, there is a
%%% dedicated record that shall be passed to all function calls.
%%% @end
%%%-------------------------------------------------------------------
-module(monitoring).
-author("<NAME>").
-author("<NAME>").

-include("logging.hrl").
-include("monitoring/monitoring.hrl").

-ifdef(TEST).
-compile(export_all).
-endif.

% Record holding all monitoring info and required measurement history.
-record(node_monitoring_state, {
    cpu_stats = [] :: [{Name :: binary(), Value :: float()}],
    mem_stats = [] :: [{Name :: binary(), Value :: float()}],
    net_stats = [] :: [{Name :: binary(), Value :: float()}],
    cpu_last = [] :: [{Name :: binary(), WorkJiffies :: integer(), TotalJiffies :: integer()}],
    net_last = [] :: [{rx_b | tx_b | rx_p | tx_p | maxthp, Name :: binary(), Value :: integer()}],
    erlang_vm_cpu = 0.0 :: float(),
    erlang_vm_mem = [] :: [{Type :: atom(), Size :: non_neg_integer()}],
    erlang_vm_processes_num = 0 :: non_neg_integer(),
    last_update_timer :: stopwatch:instance()
}).

-type node_monitoring_state() :: #node_monitoring_state{}.
-export_type([node_monitoring_state/0]).

% Files to read system stats from
-define(CPU_STATS_FILE, "/proc/stat").
-define(MEM_STATS_FILE, "/proc/meminfo").
-define(NET_STATS_FILE(_Interface, _Type), "/sys/class/net/" ++ _Interface ++ "/statistics/" ++ _Type).
-define(NET_SPEED_FILE(_Interface), "/sys/class/net/" ++ _Interface ++ "/speed").
-define(NET_DUPLEX_FILE(_Interface), "/sys/class/net/" ++ _Interface ++ "/duplex").

%% API
-export([start/0, update/1]).
-export([get_node_state/1, get_memory_stats/0]).
-export([cpu_usage/1, mem_usage/1, net_usage/1, erlang_vm_stats/1]).

%%%===================================================================
%%% API
%%%===================================================================

%%--------------------------------------------------------------------
%% @doc
%% Initializes monitoring and returns the node_monitoring_state record
%% that will be used throughout the monitoring process.
%% @end
%%--------------------------------------------------------------------
-spec start() -> #node_monitoring_state{}.
start() ->
    update(#node_monitoring_state{last_update_timer = stopwatch:start()}).


%%--------------------------------------------------------------------
%% @doc
%% Updates monitoring statistics.
%% @end
%%--------------------------------------------------------------------
-spec update(MonitoringState :: #node_monitoring_state{}) -> #node_monitoring_state{}.
update(MonitoringState) ->
    #node_monitoring_state{
        last_update_timer = LastUpdateTimer,
        cpu_last = CPULast,
        net_last = NetLast,
        erlang_vm_cpu = VM_CPU
    } = MonitoringState,

    % make sure the time difference is not zero in case the update function is
    % called twice in a very short interval, float is required for better accuracy
    TimeDiffSeconds = max(0.001, stopwatch:read_seconds(LastUpdateTimer, float)),

    {CPUStats, NewCPULast} = get_cpu_stats(CPULast),
    {NetStats, NewNetLast} = get_network_stats(NetLast, TimeDiffSeconds),
    MemStats = get_memory_stats(),
    NewVM_CPU = case cpu_sup:util() of
        {error, _} -> VM_CPU;
        Other -> Other
    end,
    MonitoringState#node_monitoring_state{
        last_update_timer = stopwatch:start(),
        cpu_stats = CPUStats,
        cpu_last = NewCPULast,
        mem_stats = MemStats,
        net_stats = NetStats,
        net_last = NewNetLast,
        erlang_vm_cpu = NewVM_CPU,
        erlang_vm_mem = erlang:memory(),
        erlang_vm_processes_num = length(erlang:processes())}.


%%--------------------------------------------------------------------
%% @doc
%% Returns a #node_state{} record that contains all required information
%% about current node state and load.
%% @end
%%--------------------------------------------------------------------
-spec get_node_state(MonitoringState :: #node_monitoring_state{}) -> #node_state{}.
get_node_state(MonitoringState) ->
    CPUUsage = cpu_usage(MonitoringState),
{'fraction_non_alphanumeric': 0.2930151465620573, 'fraction_numerical': 0.004794595183611202, 'mean_word_length': 2.4374531835205993, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1659081', 'n_tokens_mistral': 2525, 'n_tokens_neox': 2482, 'n_words': 604}