From 6eb6468ba99e040cf33ffdd2096f0bf84035ca00 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Sat, 23 Sep 2017 22:24:37 +0200 Subject: [PATCH] add CSV metrics object --- srsue/hdr/metrics_csv.h | 64 ++++++++++++++++++++++ srsue/src/CMakeLists.txt | 2 +- srsue/src/metrics_csv.cc | 109 +++++++++++++++++++++++++++++++++++++ srsue/test/CMakeLists.txt | 4 +- srsue/test/metrics_test.cc | 41 ++++++++++++++ 5 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 srsue/hdr/metrics_csv.h create mode 100644 srsue/src/metrics_csv.cc diff --git a/srsue/hdr/metrics_csv.h b/srsue/hdr/metrics_csv.h new file mode 100644 index 000000000..a897265d2 --- /dev/null +++ b/srsue/hdr/metrics_csv.h @@ -0,0 +1,64 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2013-2015 Software Radio Systems Limited + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE 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. + * + * srsUE 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. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +/****************************************************************************** + * File: metrics_csv.h + * Description: Metrics class writing to CSV file. + *****************************************************************************/ + +#ifndef METRICS_CSV_H +#define METRICS_CSV_H + +#include +#include +#include +#include +#include + +#include "srslte/common/metrics_hub.h" +#include "ue_metrics_interface.h" + +namespace srsue { + +class metrics_csv : public srslte::metrics_listener +{ +public: + metrics_csv(std::string filename); + + void set_metrics(ue_metrics_t &m, float report_period_secs); + void set_ue_handle(ue_metrics_interface *ue_); + +private: + std::string float_to_string(float f, int digits, bool add_semicolon = true); + + std::ofstream file; + ue_metrics_interface* ue; + uint32_t n_reports; +}; + +} // namespace srsue + +#endif // METRICS_CSV_H diff --git a/srsue/src/CMakeLists.txt b/srsue/src/CMakeLists.txt index 5c6000f63..0755a6490 100644 --- a/srsue/src/CMakeLists.txt +++ b/srsue/src/CMakeLists.txt @@ -31,7 +31,7 @@ if (RPATH) set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) endif (RPATH) -add_executable(srsue main.cc ue_base.cc ue.cc metrics_stdout.cc) +add_executable(srsue main.cc ue_base.cc ue.cc metrics_stdout.cc metrics_csv.cc) target_link_libraries(srsue srsue_mac srsue_phy srsue_upper diff --git a/srsue/src/metrics_csv.cc b/srsue/src/metrics_csv.cc new file mode 100644 index 000000000..18c761263 --- /dev/null +++ b/srsue/src/metrics_csv.cc @@ -0,0 +1,109 @@ +/** + * + * \section COPYRIGHT + * + * Copyright 2015 The srsUE Developers. See the + * COPYRIGHT file at the top-level directory of this distribution. + * + * \section LICENSE + * + * This file is part of the srsUE library. + * + * srsUE 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. + * + * srsUE 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. + * + * A copy of the GNU Affero General Public License can be found in + * the LICENSE file in the top-level directory of this distribution + * and at http://www.gnu.org/licenses/. + * + */ + +#include "metrics_csv.h" + +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; + +namespace srsue{ + +metrics_csv::metrics_csv(std::string filename) + :n_reports(0) + ,ue(NULL) +{ + file.open(filename.c_str()); +} + +void metrics_csv::set_ue_handle(ue_metrics_interface *ue_) +{ + ue = ue_; +} + +void metrics_csv::set_metrics(ue_metrics_t &metrics, float metrics_report_period) +{ + if (file.is_open()) { + if (!ue->is_attached()) { + file << "# disconnected" << endl; + return; + } + + if(n_reports == 0) { + file << "time;rsrp;pl;cfo;dl_mcs;dl_snr;dl_turbo;dl_brate;dl_bler;ul_mcs;ul_buff;ul_brate;ul_bler;rf_o;rf_u;rf_l" << endl; + } + file << (metrics_report_period*n_reports) << ";"; + file << float_to_string(metrics.phy.dl.rsrp, 2); + file << float_to_string(metrics.phy.dl.pathloss, 2); + file << float_to_string(metrics.phy.sync.cfo, 2); + file << float_to_string(metrics.phy.dl.mcs, 2); + file << float_to_string(metrics.phy.dl.sinr, 2); + file << float_to_string(metrics.phy.dl.turbo_iters, 2); + file << float_to_string((float) metrics.mac.rx_brate/metrics_report_period, 2); + if (metrics.mac.rx_pkts > 0) { + file << float_to_string((float) 100*metrics.mac.rx_errors/metrics.mac.rx_pkts, 1); + } else { + file << float_to_string(0, 2); + } + file << float_to_string(metrics.phy.ul.mcs, 2); + file << float_to_string((float) metrics.mac.ul_buffer, 2); + file << float_to_string((float) metrics.mac.tx_brate/metrics_report_period, 2); + if (metrics.mac.tx_pkts > 0) { + file << float_to_string((float) 100*metrics.mac.tx_errors/metrics.mac.tx_pkts, 1); + } else { + file << float_to_string(0, 2); + } + file << float_to_string(metrics.rf.rf_o, 2); + file << float_to_string(metrics.rf.rf_u, 2); + file << float_to_string(metrics.rf.rf_l, 2, false); + file << endl; + + n_reports++; + } else { + std::cout << "Error, couldn't write CSV file." << std::endl; + } +} + +std::string metrics_csv::float_to_string(float f, int digits, bool add_semicolon) +{ + std::ostringstream os; + const int precision = (f == 0.0) ? digits-1 : digits - log10(fabs(f))-2*DBL_EPSILON; + os << std::fixed << std::setprecision(precision) << f; + if (add_semicolon) + os << ';'; + return os.str(); +} + +} // namespace srsue diff --git a/srsue/test/CMakeLists.txt b/srsue/test/CMakeLists.txt index c83b99413..217c369ee 100644 --- a/srsue/test/CMakeLists.txt +++ b/srsue/test/CMakeLists.txt @@ -22,6 +22,6 @@ add_subdirectory(phy) add_subdirectory(mac) add_subdirectory(upper) -add_executable(metrics_test metrics_test.cc ../src/metrics_stdout.cc) +add_executable(metrics_test metrics_test.cc ../src/metrics_stdout.cc ../src/metrics_csv.cc) target_link_libraries(metrics_test srslte_phy srslte_common) -add_test(metrics_test metrics_test) +add_test(metrics_test metrics_test -o ${CMAKE_CURRENT_BINARY_DIR}/ue_metrics.csv) diff --git a/srsue/test/metrics_test.cc b/srsue/test/metrics_test.cc index fbca7e1a4..9cd17f824 100644 --- a/srsue/test/metrics_test.cc +++ b/srsue/test/metrics_test.cc @@ -25,16 +25,21 @@ */ #include +#include +#include #include #include #include "ue_metrics_interface.h" #include "srslte/common/metrics_hub.h" #include "metrics_stdout.h" +#include "metrics_csv.h" using namespace srsue; namespace srsue { +char *csv_file_name = NULL; + // fake classes class ue_dummy : public ue_metrics_interface { @@ -56,19 +61,55 @@ public: }; } +void usage(char *prog) { + printf("Usage: %s -o csv_output_file\n", prog); +} + +void parse_args(int argc, char **argv) { + int opt; + + while ((opt = getopt(argc, argv, "o")) != -1) { + switch(opt) { + case 'o': + csv_file_name = argv[optind]; + break; + default: + usage(argv[0]); + exit(-1); + } + } + if (!csv_file_name) { + usage(argv[0]); + exit(-1); + } +} + + int main(int argc, char **argv) { float period = 1.0; ue_dummy ue; + if (argc < 3) { + usage(argv[0]); + exit(-1); + } + + parse_args(argc,argv); + // the default metrics type for stdout output metrics_stdout metrics_screen; metrics_screen.set_ue_handle(&ue); + // the CSV file writer + metrics_csv metrics_file(csv_file_name); + metrics_file.set_ue_handle(&ue); + // create metrics hub and register metrics for stdout srslte::metrics_hub metricshub; metricshub.init(&ue, period); metricshub.add_listener(&metrics_screen); + metricshub.add_listener(&metrics_file); // enable printing metrics_screen.toggle_print(true);