Implement UE metrics in JSON format.

Added config options to control this feature.
master
faluco 4 years ago committed by Andre Puschmann
parent 9e1a85afe8
commit 1670124926

@ -0,0 +1,42 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
/******************************************************************************
* File: metrics_json.h
* Description: Metrics class printing to a json file.
*****************************************************************************/
#ifndef SRSUE_METRICS_JSON_H
#define SRSUE_METRICS_JSON_H
#include "srsran/srslog/log_channel.h"
#include "ue_metrics_interface.h"
namespace srsue {
class metrics_json : public srsran::metrics_listener<ue_metrics_t>
{
public:
explicit metrics_json(srslog::log_channel& c) : log_c(c) {}
void set_metrics(const ue_metrics_t& m, const uint32_t period_usec) override;
void set_ue_handle(ue_metrics_interface* ue_);
void stop() override {}
private:
srslog::log_channel& log_c;
ue_metrics_interface* ue = nullptr;
};
} // namespace srsue
#endif // SRSUE_METRICS_JSON_H

@ -61,6 +61,8 @@ typedef struct {
bool metrics_csv_append;
int metrics_csv_flush_period_sec;
std::string metrics_csv_filename;
bool metrics_json_enable;
std::string metrics_json_filename;
bool tracing_enable;
std::string tracing_filename;
std::size_t tracing_buffcapacity;

@ -18,7 +18,7 @@ if (RPATH)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
endif (RPATH)
add_executable(srsue main.cc ue.cc metrics_stdout.cc metrics_csv.cc)
add_executable(srsue main.cc ue.cc metrics_stdout.cc metrics_csv.cc metrics_json.cc)
set(SRSUE_SOURCES srsue_phy srsue_stack srsue_upper srsue_mac srsue_rrc srslog system)
set(SRSRAN_SOURCES srsran_common srsran_mac srsran_phy srsran_radio srsran_upper rrc_asn1 srslog system)

@ -20,6 +20,7 @@
#include "srsran/srsran.h"
#include "srsran/version.h"
#include "srsue/hdr/metrics_csv.h"
#include "srsue/hdr/metrics_json.h"
#include "srsue/hdr/metrics_stdout.h"
#include "srsue/hdr/ue.h"
#include <boost/program_options.hpp>
@ -429,6 +430,14 @@ static int parse_args(all_args_t* args, int argc, char* argv[])
bpo::value<int>(&args->general.metrics_csv_flush_period_sec)->default_value(-1),
"Periodicity in s to flush CSV file to disk (-1 for auto)")
("general.metrics_json_enable",
bpo::value<bool>(&args->general.metrics_json_enable)->default_value(false),
"Write UE metrics to a JSON file")
("general.metrics_json_filename",
bpo::value<string>(&args->general.metrics_json_filename)->default_value("/tmp/ue_metrics.json"),
"Metrics JSON filename")
("general.tracing_enable",
bpo::value<bool>(&args->general.tracing_enable)->default_value(false),
"Events tracing")
@ -704,6 +713,18 @@ int main(int argc, char* argv[])
}
}
// Set up the JSON log channel used by metrics.
srslog::sink& json_sink =
srslog::fetch_file_sink(args.general.metrics_json_filename, 0, srslog::create_json_formatter());
srslog::log_channel& json_channel = srslog::fetch_log_channel("JSON_channel", json_sink, {});
json_channel.set_enabled(args.general.metrics_json_enable);
srsue::metrics_json json_metrics(json_channel);
if (args.general.metrics_json_enable) {
metricshub.add_listener(&json_metrics);
json_metrics.set_ue_handle(&ue);
}
pthread_t input;
pthread_create(&input, nullptr, &input_loop, &args);

@ -0,0 +1,229 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2021 Software Radio Systems Limited
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the distribution.
*
*/
#include "srsue/hdr/metrics_json.h"
#include "srsran/srslog/context.h"
using namespace srsue;
void metrics_json::set_ue_handle(ue_metrics_interface* ue_)
{
ue = ue_;
}
namespace {
/// Shared metrics between containers.
DECLARE_METRIC("pci", metric_pci, uint32_t, "");
DECLARE_METRIC("dl_bitrate", metric_dl_brate, float, "");
DECLARE_METRIC("ul_bitrate", metric_ul_brate, float, "");
DECLARE_METRIC("rsrp", metric_rsrp, float, "");
/// MAC container.
DECLARE_METRIC("dl_bler", metric_dl_bler, float, "");
DECLARE_METRIC("ul_bler", metric_ul_bler, float, "");
DECLARE_METRIC("ul_buff", metric_ul_buff, uint32_t, "");
DECLARE_METRIC_SET("mac_container",
mset_mac_container,
metric_dl_brate,
metric_dl_bler,
metric_ul_brate,
metric_ul_bler,
metric_ul_buff);
/// Carrier container.
DECLARE_METRIC("earfcn", metric_earfcn, uint32_t, "");
DECLARE_METRIC("pathloss", metric_pathloss, float, "");
DECLARE_METRIC("cfo", metric_cfo, float, "");
DECLARE_METRIC("dl_snr", metric_dl_snr, float, "");
DECLARE_METRIC("dl_mcs", metric_dl_mcs, float, "");
DECLARE_METRIC("ul_mcs", metric_ul_mcs, float, "");
DECLARE_METRIC("ul_ta", metric_ul_ta, float, "");
DECLARE_METRIC("distance_km", metric_distance_km, float, "");
DECLARE_METRIC("speed_kmph", metric_speed_kmph, float, "");
DECLARE_METRIC_SET("carrier_container",
mset_carrier_container,
metric_earfcn,
metric_pci,
metric_rsrp,
metric_pathloss,
metric_cfo,
metric_dl_snr,
metric_dl_mcs,
metric_ul_mcs,
metric_ul_ta,
metric_distance_km,
metric_speed_kmph,
mset_mac_container);
DECLARE_METRIC_LIST("carrier_list", mlist_carriers, std::vector<mset_carrier_container>);
/// GW container.
DECLARE_METRIC_SET("gw_container", mset_gw_container, metric_dl_brate, metric_ul_brate);
/// RRC container.
DECLARE_METRIC("rrc_state", metric_rrc_state, std::string, "");
DECLARE_METRIC_SET("rrc_container", mset_rrc_container, metric_rrc_state);
/// Neighbour cell list.
DECLARE_METRIC_SET("neighbour_cell_container", mset_neighbour_cell_container, metric_pci, metric_rsrp, metric_cfo);
DECLARE_METRIC_LIST("neighbour_cell_list", mlist_neighbours, std::vector<mset_neighbour_cell_container>);
/// NAS container.
DECLARE_METRIC("emm_state", metric_emm_state, std::string, "");
DECLARE_METRIC_SET("nas_container", mset_nas_container, metric_emm_state);
/// RF container.
DECLARE_METRIC("rf_o", metric_rf_o, uint32_t, "");
DECLARE_METRIC("rf_u", metric_rf_u, uint32_t, "");
DECLARE_METRIC("rf_l", metric_rf_l, uint32_t, "");
DECLARE_METRIC_SET("rf_container", mset_rf_container, metric_rf_o, metric_rf_u, metric_rf_l);
/// System memory container.
DECLARE_METRIC("proc_realmem_percent", metric_proc_rmem_percent, uint32_t, "");
DECLARE_METRIC("proc_realmem_kB", metric_proc_rmem_kB, uint32_t, "");
DECLARE_METRIC("proc_vmem_kB", metric_proc_vmem_kB, uint32_t, "");
DECLARE_METRIC("sys_mem_usage_percent", metric_sys_mem_percent, uint32_t, "");
DECLARE_METRIC_SET("sys_memory_container",
mset_sys_mem_container,
metric_proc_rmem_percent,
metric_proc_rmem_kB,
metric_proc_vmem_kB,
metric_sys_mem_percent);
/// System CPU container
DECLARE_METRIC("proc_cpu_usage", metric_proc_cpu_usage, uint32_t, "");
DECLARE_METRIC("proc_thread_count", metric_thread_count, uint32_t, "");
DECLARE_METRIC("sys_core_usage", metric_proc_core_usage, uint32_t, "");
DECLARE_METRIC_SET("cpu_core_container", mset_cpu_core_container, metric_proc_core_usage);
DECLARE_METRIC_LIST("cpu_core_list", mlist_cpu_core_list, std::vector<mset_cpu_core_container>);
DECLARE_METRIC_SET("sys_cpu_container",
mset_sys_cpu_container,
metric_proc_cpu_usage,
metric_thread_count,
mlist_cpu_core_list);
/// Metrics root object.
DECLARE_METRIC("type", metric_type_tag, std::string, "");
DECLARE_METRIC("timestamp", metric_timestamp_tag, double, "");
/// Metrics context.
using metric_context_t = srslog::build_context_type<metric_type_tag,
metric_timestamp_tag,
mlist_carriers,
mset_gw_container,
mset_rrc_container,
mlist_neighbours,
mset_nas_container,
mset_rf_container,
mset_sys_mem_container,
mset_sys_cpu_container>;
} // namespace
/// Returns the current time in seconds with ms precision since UNIX epoch.
static double get_time_stamp()
{
auto tp = std::chrono::system_clock::now().time_since_epoch();
return std::chrono::duration_cast<std::chrono::milliseconds>(tp).count() * 1e-3;
}
void metrics_json::set_metrics(const ue_metrics_t& metrics, const uint32_t period_usec)
{
if (!ue) {
return;
}
metric_context_t ctx("JSON Metrics");
// Fill root object.
ctx.write<metric_type_tag>("metrics");
// Fill cc container.
auto& carrier_list = ctx.get<mlist_carriers>();
carrier_list.resize(metrics.phy.nof_active_cc);
for (uint32_t i = 0, e = carrier_list.size(); i != e; ++i) {
auto& carrier = carrier_list[i];
// PHY.
carrier.write<metric_earfcn>(metrics.phy.info[i].dl_earfcn);
carrier.write<metric_pci>(metrics.phy.info[i].pci);
carrier.write<metric_rsrp>(metrics.phy.ch[i].rsrp);
carrier.write<metric_pathloss>(metrics.phy.ch[i].pathloss);
carrier.write<metric_cfo>(metrics.phy.sync[i].cfo);
carrier.write<metric_dl_snr>(metrics.phy.ch[i].sinr);
carrier.write<metric_dl_mcs>(metrics.phy.dl[i].mcs);
carrier.write<metric_ul_mcs>(metrics.phy.ul[i].mcs);
carrier.write<metric_ul_ta>(metrics.phy.sync[i].ta_us);
carrier.write<metric_distance_km>(metrics.phy.sync[i].distance_km);
carrier.write<metric_speed_kmph>(metrics.phy.sync[i].speed_kmph);
// MAC
carrier.get<mset_mac_container>().write<metric_dl_brate>(metrics.stack.mac[i].rx_brate /
metrics.stack.mac[i].nof_tti * 1e-3);
carrier.get<mset_mac_container>().write<metric_dl_bler>(
(metrics.stack.mac[i].rx_pkts > 0) ? (float)100 * metrics.stack.mac[i].rx_errors / metrics.stack.mac[i].rx_pkts
: 0);
carrier.get<mset_mac_container>().write<metric_ul_brate>(metrics.stack.mac[i].tx_brate /
metrics.stack.mac[i].nof_tti * 1e-3);
carrier.get<mset_mac_container>().write<metric_ul_bler>(
(metrics.stack.mac[i].tx_pkts > 0) ? (float)100 * metrics.stack.mac[i].tx_errors / metrics.stack.mac[i].tx_pkts
: 0);
carrier.get<mset_mac_container>().write<metric_ul_buff>(metrics.stack.mac[i].ul_buffer);
}
// Fill GW container.
ctx.get<mset_gw_container>().write<metric_dl_brate>(metrics.gw.dl_tput_mbps);
ctx.get<mset_gw_container>().write<metric_ul_brate>(metrics.gw.ul_tput_mbps);
// Fill RRC container.
ctx.get<mset_rrc_container>().write<metric_rrc_state>(rrc_state_text[metrics.stack.rrc.state]);
// Fill neighbour list.
auto& neighbour_list = ctx.get<mlist_neighbours>();
neighbour_list.resize(metrics.stack.rrc.neighbour_cells.size());
for (uint32_t i = 0, e = neighbour_list.size(); i != e; ++i) {
auto& neigbour = neighbour_list[i];
neigbour.write<metric_pci>(metrics.stack.rrc.neighbour_cells[i].pci);
neigbour.write<metric_rsrp>(metrics.stack.rrc.neighbour_cells[i].rsrp);
neigbour.write<metric_cfo>(metrics.stack.rrc.neighbour_cells[i].cfo_hz);
}
// Fill NAS container.
ctx.get<mset_nas_container>().write<metric_emm_state>(emm_state_text(metrics.stack.nas.state));
// Fill RF container.
ctx.get<mset_rf_container>().write<metric_rf_o>(metrics.rf.rf_o);
ctx.get<mset_rf_container>().write<metric_rf_u>(metrics.rf.rf_u);
ctx.get<mset_rf_container>().write<metric_rf_l>(metrics.rf.rf_l);
// Fill system memory container.
ctx.get<mset_sys_mem_container>().write<metric_proc_rmem_percent>(metrics.sys.process_realmem);
ctx.get<mset_sys_mem_container>().write<metric_proc_rmem_kB>(metrics.sys.process_realmem_kB);
ctx.get<mset_sys_mem_container>().write<metric_proc_vmem_kB>(metrics.sys.process_virtualmem_kB);
ctx.get<mset_sys_mem_container>().write<metric_sys_mem_percent>(metrics.sys.system_mem);
// Fill system CPU container.
ctx.get<mset_sys_cpu_container>().write<metric_proc_cpu_usage>(metrics.sys.process_cpu_usage);
ctx.get<mset_sys_cpu_container>().write<metric_thread_count>(metrics.sys.thread_count);
auto& core_list = ctx.get<mset_sys_cpu_container>().get<mlist_cpu_core_list>();
core_list.resize(metrics.sys.cpu_count);
for (uint32_t i = 0, e = core_list.size(); i != e; ++i) {
core_list[i].write<metric_proc_core_usage>(metrics.sys.cpu_load[i]);
}
// Log the context.
ctx.write<metric_timestamp_tag>(get_time_stamp());
log_c(ctx);
}

@ -391,26 +391,32 @@ enable = false
#####################################################################
# General configuration options
#
# metrics_csv_enable: Write UE metrics to CSV file.
# metrics_csv_enable: Write UE metrics to CSV file.
#
# metrics_period_secs: Sets the period at which metrics are requested from the UE.
# metrics_period_secs: Sets the period at which metrics are requested from the UE.
#
# metrics_csv_filename: File path to use for CSV metrics.
# metrics_csv_filename: File path to use for CSV metrics.
#
# tracing_enable: Write source code tracing information to a file.
# tracing_enable: Write source code tracing information to a file.
#
# tracing_filename: File path to use for tracing information.
# tracing_filename: File path to use for tracing information.
#
# tracing_buffcapacity: Maximum capacity in bytes the tracing framework can store.
# tracing_buffcapacity: Maximum capacity in bytes the tracing framework can store.
#
# have_tti_time_stats: Calculate TTI execution statistics using system clock
# have_tti_time_stats: Calculate TTI execution statistics using system clock
#
# metrics_json_enable: Write UE metrics to JSON file.
#
# metrics_json_filename: File path to use for JSON metrics.
#
#####################################################################
[general]
#metrics_csv_enable = false
#metrics_period_secs = 1
#metrics_csv_filename = /tmp/ue_metrics.csv
#have_tti_time_stats = true
#tracing_enable = true
#tracing_filename = /tmp/ue_tracing.log
#tracing_buffcapacity = 1000000
#metrics_csv_enable = false
#metrics_period_secs = 1
#metrics_csv_filename = /tmp/ue_metrics.csv
#have_tti_time_stats = true
#tracing_enable = true
#tracing_filename = /tmp/ue_tracing.log
#tracing_buffcapacity = 1000000
#metrics_json_enable = false
#metrics_json_filename = /tmp/ue_metrics.json

Loading…
Cancel
Save