%% Copyright (C) 2024 by sysmocom - s.f.m.c. GmbH %% Author: Pau Espin Pedrol %% %% All Rights Reserved %% %% SPDX-License-Identifier: AGPL-3.0-or-later %% %% This program 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. %% %% This program 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 General Public License for more details. %% %% You should have received a copy of the GNU Affero General Public License %% along with this program. If not, see . %% %% Additional Permission under GNU AGPL version 3 section 7: %% %% If you modify this Program, or any covered work, by linking or %% combining it with runtime libraries of Erlang/OTP as released by %% Ericsson on https://www.erlang.org (or a modified version of these %% libraries), containing parts covered by the terms of the Erlang Public %% License (https://www.erlang.org/EPLICENSE), the licensors of this %% Program grant you additional permission to convey the resulting work %% without the need to license the runtime libraries of Erlang/OTP under %% the GNU Affero General Public License. Corresponding Source for a %% non-source form of such a combination shall include the source code %% for the parts of the runtime libraries of Erlang/OTP used as well as %% that of the covered work. -module(s1gw_metrics). -export([init/0, ctr_reset/1, ctr_inc/1, ctr_inc/2, gauge_reset/1, gauge_set/2, gauge_inc/1, gauge_inc/2, gauge_dec/1]). -include_lib("kernel/include/logger.hrl"). -include("s1gw_metrics.hrl"). -define(S1GW_COUNTERS, [ ?S1GW_CTR_PFCP_HEARTBEAT_REQ_TX, ?S1GW_CTR_PFCP_HEARTBEAT_REQ_TIMEOUT, ?S1GW_CTR_PFCP_HEARTBEAT_RESP_RX, ?S1GW_CTR_PFCP_HEARTBEAT_REQ_RX, ?S1GW_CTR_PFCP_HEARTBEAT_RESP_TX, ?S1GW_CTR_PFCP_ASSOC_SETUP_REQ_TX, ?S1GW_CTR_PFCP_ASSOC_SETUP_REQ_TIMEOUT, ?S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX, ?S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX_ACK, ?S1GW_CTR_PFCP_ASSOC_SETUP_RESP_RX_NACK, ?S1GW_CTR_PFCP_UNEXPECTED_PDU, ?S1GW_CTR_S1AP_ENB_ALL_RX, ?S1GW_CTR_S1AP_ENB_ALL_RX_UNKNOWN_ENB, ?S1GW_CTR_S1AP_PROXY_UPLINK_PACKETS_QUEUED, ?S1GW_CTR_S1AP_PROXY_EXCEPTION, %% exception(s) occurred %% s1ap_proxy: INcoming PDU counters ?S1GW_CTR_S1AP_PROXY_IN_PKT_ALL, %% received total ?S1GW_CTR_S1AP_PROXY_IN_PKT_DECODE_ERROR, %% failed to decode ?S1GW_CTR_S1AP_PROXY_IN_PKT_PROC_ERROR, %% failed to process ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_SETUP_REQ, %% E-RAB SETUP.req PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_SETUP_RSP, %% E-RAB SETUP.rsp PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_CMD, %% E-RAB RELEASE.cmd PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_RSP, %% E-RAB RELEASE.rsp PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_RELEASE_IND, %% E-RAB RELEASE.ind PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_ERAB_MOD_IND, %% E-RAB MODIFY.ind PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_INIT_CTX_REQ, %% INITIAL CONTEXT SETUP.req PDUs ?S1GW_CTR_S1AP_PROXY_IN_PKT_INIT_CTX_RSP, %% INITIAL CONTEXT SETUP.rsp PDUs %% s1ap_proxy: OUTgoing PDU counters ?S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_ALL, %% forwarded: total ?S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_PROC, %% forwarded: processed ?S1GW_CTR_S1AP_PROXY_OUT_PKT_FWD_UNMODIFIED, %% forwarded: unmodified ?S1GW_CTR_S1AP_PROXY_OUT_PKT_REPLY_ALL, %% replied: total ?S1GW_CTR_S1AP_PROXY_OUT_PKT_REPLY_ERAB_SETUP_RSP %% replied: E-RAB SETUP.rsp ]). -define(S1GW_GAUGES, [ ?S1GW_GAUGE_PFCP_ASSOCIATED, ?S1GW_GAUGE_S1AP_ENB_NUM_SCTP_CONNECTIONS, ?S1GW_GAUGE_S1AP_PROXY_UPLINK_PACKETS_QUEUED ]). -type counter() :: [ctr | _]. -type gauge() :: [gauge | _]. -spec new_ctr(counter()) -> ok. new_ctr(Name) -> %%?LOG_INFO("New counter ~p", [Name]), ok = exometer:new(Name, counter). -spec new_ctrs(list(counter())) -> ok. new_ctrs([]) -> ok; new_ctrs([Name | MoreNames]) -> new_ctr(Name), new_ctrs(MoreNames). -spec new_gauge(gauge()) -> ok. new_gauge(Name) -> %%?LOG_INFO("New gauge ~p", [Name]), ok = exometer:new(Name, gauge). -spec new_gauges(list(gauge())) -> ok. new_gauges([]) -> ok; new_gauges([Name | MoreNames]) -> new_gauge(Name), new_gauges(MoreNames). -spec get_current_value(counter() | gauge()) -> integer(). get_current_value(Name) -> Result = exometer:get_value(Name, value), {ok, [{value, PrevVal}]} = Result, PrevVal. %% ------------------------------------------------------------------ %% public API %% ------------------------------------------------------------------ init() -> ?LOG_INFO("Initiating metrics"), new_ctrs(?S1GW_COUNTERS), new_gauges(?S1GW_GAUGES). %%%%%%%%%%%%% %% CTR APIs %%%%%%%%%%%%% -spec ctr_reset(counter()) -> ok | {error, any()}. ctr_reset(Name) -> ?LOG_DEBUG("ctr_reset(~p)", [Name]), exometer:reset(Name). -spec ctr_inc(counter(), integer()) -> ok | {error, any()}. ctr_inc(Name, Value) -> ?LOG_DEBUG("ctr_inc(~p, ~p)", [Name, Value]), exometer:update(Name, Value). -spec ctr_inc(counter()) -> ok | {error, any()}. ctr_inc(Name) -> ctr_inc(Name, 1). %%%%%%%%%%%%% %% GAUGE APIs %%%%%%%%%%%%% -spec gauge_reset(gauge()) -> ok | {error, any()}. gauge_reset(Name) -> ?LOG_DEBUG("gauge_reset(~p)", [Name]), exometer:reset(Name). -spec gauge_set(gauge(), integer()) -> ok | {error, any()}. gauge_set(Name, Value) -> exometer:update(Name, Value). -spec gauge_inc(gauge(), integer()) -> ok | {error, any()}. gauge_inc(Name, Value) -> PrevVal = get_current_value(Name), ?LOG_DEBUG("gauge_inc(~p, ~p): pre_val=~p", [Name, Value, PrevVal]), exometer:update(Name, Value + PrevVal). -spec gauge_inc(gauge()) -> ok | {error, any()}. gauge_inc(Name) -> gauge_inc(Name, 1). -spec gauge_dec(gauge()) -> ok | {error, any()}. gauge_dec(Name) -> gauge_inc(Name, -1). %% vim:set ts=4 sw=4 et: