mirror of https://github.com/pvnis/srsRAN_4G.git
refactor - remove old log_filter and logmap libraries from the codebase
parent
d35d7aef76
commit
3e9f93eb8a
@ -1,150 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 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: log.h
|
||||
*
|
||||
* Description: Abstract logging service
|
||||
*
|
||||
* Reference:
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef SRSLTE_LOG_H
|
||||
#define SRSLTE_LOG_H
|
||||
|
||||
#include "srslte/common/standard_streams.h"
|
||||
#include <algorithm>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
namespace srslte {
|
||||
|
||||
typedef enum {
|
||||
LOG_LEVEL_NONE = 0,
|
||||
LOG_LEVEL_ERROR,
|
||||
LOG_LEVEL_WARNING,
|
||||
LOG_LEVEL_INFO,
|
||||
LOG_LEVEL_DEBUG,
|
||||
LOG_LEVEL_N_ITEMS
|
||||
} LOG_LEVEL_ENUM;
|
||||
static const char log_level_text[LOG_LEVEL_N_ITEMS][16] = {"None ", "Error ", "Warning", "Info ", "Debug "};
|
||||
|
||||
static const char log_level_text_short[LOG_LEVEL_N_ITEMS][16] = {"[-]", "[E]", "[W]", "[I]", "[D]"};
|
||||
|
||||
class log
|
||||
{
|
||||
public:
|
||||
log()
|
||||
{
|
||||
service_name = "";
|
||||
tti = 0;
|
||||
level = LOG_LEVEL_NONE;
|
||||
hex_limit = 0;
|
||||
add_string_en = false;
|
||||
}
|
||||
|
||||
explicit log(std::string service_name_)
|
||||
{
|
||||
service_name = std::move(service_name_);
|
||||
tti = 0;
|
||||
level = LOG_LEVEL_NONE;
|
||||
hex_limit = 0;
|
||||
add_string_en = false;
|
||||
}
|
||||
|
||||
log(const log&) = delete;
|
||||
log& operator=(const log&) = delete;
|
||||
|
||||
virtual ~log() = default;
|
||||
|
||||
// This function shall be called at the start of every tti for printing tti
|
||||
void step(uint32_t tti_)
|
||||
{
|
||||
tti = tti_;
|
||||
add_string_en = false;
|
||||
}
|
||||
|
||||
void prepend_string(std::string s)
|
||||
{
|
||||
add_string_en = true;
|
||||
add_string_val = std::move(s);
|
||||
}
|
||||
|
||||
uint32_t get_tti() { return tti; }
|
||||
|
||||
void set_level(LOG_LEVEL_ENUM l) { level = l; }
|
||||
|
||||
void set_level(std::string l) { set_level(get_level_from_string(std::move(l))); }
|
||||
|
||||
static srslte::LOG_LEVEL_ENUM get_level_from_string(std::string l)
|
||||
{
|
||||
std::transform(l.begin(), l.end(), l.begin(), ::toupper);
|
||||
if ("NONE" == l) {
|
||||
return srslte::LOG_LEVEL_NONE;
|
||||
} else if ("ERROR" == l) {
|
||||
return srslte::LOG_LEVEL_ERROR;
|
||||
} else if ("WARNING" == l) {
|
||||
return srslte::LOG_LEVEL_WARNING;
|
||||
} else if ("INFO" == l) {
|
||||
return srslte::LOG_LEVEL_INFO;
|
||||
} else if ("DEBUG" == l) {
|
||||
return srslte::LOG_LEVEL_DEBUG;
|
||||
} else {
|
||||
return srslte::LOG_LEVEL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_LEVEL_ENUM get_level() { return level; }
|
||||
const std::string& get_service_name() const { return service_name; }
|
||||
|
||||
void set_hex_limit(int limit) { hex_limit = limit; }
|
||||
int get_hex_limit() { return hex_limit; }
|
||||
|
||||
// Pure virtual methods for logging
|
||||
virtual void error(const char* message, ...) __attribute__((format(printf, 2, 3))) = 0;
|
||||
virtual void warning(const char* message, ...) __attribute__((format(printf, 2, 3))) = 0;
|
||||
virtual void info(const char* message, ...) __attribute__((format(printf, 2, 3))) = 0;
|
||||
virtual void info_long(const char* message, ...) __attribute__((format(printf, 2, 3))) = 0;
|
||||
virtual void debug(const char* message, ...) __attribute__((format(printf, 2, 3))) = 0;
|
||||
virtual void debug_long(const char* message, ...) __attribute__((format(printf, 2, 3))) = 0;
|
||||
|
||||
// Same with hex dump
|
||||
virtual void error_hex(const uint8_t*, int, const char*, ...) __attribute__((format(printf, 4, 5)))
|
||||
{
|
||||
error("error_hex not implemented.\n");
|
||||
}
|
||||
virtual void warning_hex(const uint8_t*, int, const char*, ...) __attribute__((format(printf, 4, 5)))
|
||||
{
|
||||
error("warning_hex not implemented.\n");
|
||||
}
|
||||
virtual void info_hex(const uint8_t*, int, const char*, ...) __attribute__((format(printf, 4, 5)))
|
||||
{
|
||||
error("info_hex not implemented.\n");
|
||||
}
|
||||
virtual void debug_hex(const uint8_t*, int, const char*, ...) __attribute__((format(printf, 4, 5)))
|
||||
{
|
||||
error("debug_hex not implemented.\n");
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t tti;
|
||||
LOG_LEVEL_ENUM level;
|
||||
int hex_limit;
|
||||
|
||||
bool add_string_en;
|
||||
std::string add_string_val;
|
||||
std::string service_name;
|
||||
};
|
||||
|
||||
} // namespace srslte
|
||||
|
||||
#endif // SRSLTE_LOG_H
|
@ -1,90 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 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: log_filter.h
|
||||
* Description: Log filter for a specific layer or element.
|
||||
* Performs filtering based on log level, generates
|
||||
* timestamped log strings and passes them to the
|
||||
* common logger object.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef SRSLTE_LOG_FILTER_H
|
||||
#define SRSLTE_LOG_FILTER_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
|
||||
#include "srslte/common/log.h"
|
||||
#include "srslte/common/logger.h"
|
||||
#include "srslte/common/logger_srslog_wrapper.h"
|
||||
#include "srslte/phy/common/timestamp.h"
|
||||
|
||||
namespace srslte {
|
||||
|
||||
typedef std::string* str_ptr;
|
||||
|
||||
class log_filter : public srslte::log
|
||||
{
|
||||
public:
|
||||
log_filter();
|
||||
log_filter(std::string layer);
|
||||
log_filter(std::string layer, logger* logger_, bool tti = false);
|
||||
|
||||
void init(std::string layer, logger* logger_, bool tti = false);
|
||||
|
||||
void error(const char* message, ...) __attribute__((format(printf, 2, 3)));
|
||||
void warning(const char* message, ...) __attribute__((format(printf, 2, 3)));
|
||||
void info(const char* message, ...) __attribute__((format(printf, 2, 3)));
|
||||
void info_long(const char* message, ...) __attribute__((format(printf, 2, 3)));
|
||||
void debug(const char* message, ...) __attribute__((format(printf, 2, 3)));
|
||||
void debug_long(const char* message, ...) __attribute__((format(printf, 2, 3)));
|
||||
|
||||
void error_hex(const uint8_t* hex, int size, const char* message, ...) __attribute__((format(printf, 4, 5)));
|
||||
void warning_hex(const uint8_t* hex, int size, const char* message, ...) __attribute__((format(printf, 4, 5)));
|
||||
void info_hex(const uint8_t* hex, int size, const char* message, ...) __attribute__((format(printf, 4, 5)));
|
||||
void debug_hex(const uint8_t* hex, int size, const char* message, ...) __attribute__((format(printf, 4, 5)));
|
||||
|
||||
class time_itf
|
||||
{
|
||||
public:
|
||||
virtual srslte_timestamp_t get_time() = 0;
|
||||
};
|
||||
|
||||
typedef enum { TIME, EPOCH } time_format_t;
|
||||
|
||||
void set_time_src(time_itf* source, time_format_t format);
|
||||
|
||||
protected:
|
||||
std::unique_ptr<logger> default_logger;
|
||||
logger* logger_h;
|
||||
bool do_tti;
|
||||
|
||||
static const int char_buff_size = logger::preallocated_log_str_size - 64 * 3;
|
||||
|
||||
time_itf* time_src;
|
||||
time_format_t time_format;
|
||||
|
||||
void all_log(srslte::LOG_LEVEL_ENUM level,
|
||||
uint32_t tti,
|
||||
char* msg,
|
||||
const uint8_t* hex = nullptr,
|
||||
int size = 0,
|
||||
bool long_msg = false);
|
||||
void now_time(char* buffer, const uint32_t buffer_len);
|
||||
void get_tti_str(const uint32_t tti_, char* buffer, const uint32_t buffer_len);
|
||||
std::string hex_string(const uint8_t* hex, int size);
|
||||
};
|
||||
|
||||
} // namespace srslte
|
||||
|
||||
#endif // SRSLTE_LOG_FILTER_H
|
@ -1,103 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 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: logger.h
|
||||
* Description: Interface for logging output
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef SRSLTE_LOGGER_H
|
||||
#define SRSLTE_LOGGER_H
|
||||
|
||||
#include "buffer_pool.h"
|
||||
#include <memory>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
namespace srslte {
|
||||
|
||||
class logger
|
||||
{
|
||||
public:
|
||||
const static uint32_t preallocated_log_str_size = 1024;
|
||||
|
||||
logger() : pool(16 * 1024) {}
|
||||
virtual ~logger() = default;
|
||||
|
||||
class log_str
|
||||
{
|
||||
public:
|
||||
log_str(const char* msg_ = nullptr, uint32_t size_ = 0)
|
||||
{
|
||||
size = size_ ? size_ : preallocated_log_str_size;
|
||||
msg = new char[size];
|
||||
if (msg_) {
|
||||
strncpy(msg, msg_, size);
|
||||
} else {
|
||||
msg[0] = '\0';
|
||||
}
|
||||
}
|
||||
log_str(const log_str&) = delete;
|
||||
log_str& operator=(const log_str&) = delete;
|
||||
~log_str() { delete[] msg; }
|
||||
void reset() { msg[0] = '\0'; }
|
||||
char* str() { return msg; }
|
||||
uint32_t get_buffer_size() { return size; }
|
||||
#ifdef SRSLTE_BUFFER_POOL_LOG_ENABLED
|
||||
char debug_name[SRSLTE_BUFFER_POOL_LOG_NAME_LEN] = {};
|
||||
#endif
|
||||
|
||||
private:
|
||||
uint32_t size;
|
||||
char* msg;
|
||||
};
|
||||
|
||||
typedef buffer_pool<log_str> log_str_pool_t;
|
||||
|
||||
class log_str_deleter
|
||||
{
|
||||
public:
|
||||
explicit log_str_deleter(log_str_pool_t* pool_ = nullptr) : pool(pool_) {}
|
||||
void operator()(log_str* buf)
|
||||
{
|
||||
if (buf) {
|
||||
if (pool) {
|
||||
buf->reset();
|
||||
pool->deallocate(buf);
|
||||
} else {
|
||||
delete buf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
log_str_pool_t* pool;
|
||||
};
|
||||
typedef std::unique_ptr<log_str, log_str_deleter> unique_log_str_t;
|
||||
|
||||
void log_char(const char* msg) { log(unique_log_str_t(new log_str(msg), log_str_deleter())); }
|
||||
|
||||
virtual void log(unique_log_str_t msg) = 0;
|
||||
|
||||
log_str_pool_t& get_pool() { return pool; }
|
||||
unique_log_str_t allocate_unique_log_str()
|
||||
{
|
||||
return unique_log_str_t(pool.allocate(), logger::log_str_deleter(&pool));
|
||||
}
|
||||
|
||||
private:
|
||||
log_str_pool_t pool;
|
||||
};
|
||||
|
||||
} // namespace srslte
|
||||
|
||||
#endif // SRSLTE_LOGGER_H
|
@ -1,40 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSLTE_LOGGER_SRSLOG_WRAPPER_H
|
||||
#define SRSLTE_LOGGER_SRSLOG_WRAPPER_H
|
||||
|
||||
#include "srslte/common/logger.h"
|
||||
|
||||
namespace srslog {
|
||||
|
||||
class log_channel;
|
||||
|
||||
} // namespace srslog
|
||||
|
||||
namespace srslte {
|
||||
|
||||
/// This logger implementation uses the srsLog framework to write log entries.
|
||||
class srslog_wrapper : public logger
|
||||
{
|
||||
public:
|
||||
explicit srslog_wrapper(srslog::log_channel& chan) : chan(chan) {}
|
||||
|
||||
void log(unique_log_str_t msg) override;
|
||||
|
||||
private:
|
||||
srslog::log_channel& chan;
|
||||
};
|
||||
|
||||
} // namespace srslte
|
||||
|
||||
#endif // SRSLTE_LOGGER_SRSLOG_WRAPPER_H
|
@ -1,94 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSLTE_LOGMAP_H
|
||||
#define SRSLTE_LOGMAP_H
|
||||
|
||||
#include "srslte/common/log.h"
|
||||
#include "srslte/common/logger.h"
|
||||
#include "srslte/common/logger_srslog_wrapper.h"
|
||||
#include "srslte/common/singleton.h"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace srslte {
|
||||
|
||||
class log_ref
|
||||
{
|
||||
using ptr_type = std::unique_ptr<log>*;
|
||||
|
||||
public:
|
||||
log_ref() = default;
|
||||
explicit log_ref(ptr_type p) : ptr_(p) {}
|
||||
explicit log_ref(const char* name);
|
||||
|
||||
// works like a log*
|
||||
log* operator->() { return ptr_->get(); }
|
||||
log* operator->() const { return ptr_->get(); }
|
||||
|
||||
// in case we want to obtain log*
|
||||
log* operator*() { return ptr_->get(); }
|
||||
log* get() { return ptr_->get(); }
|
||||
|
||||
// identity defined by ref address
|
||||
bool operator==(const log_ref& l) { return ptr_ == l.ptr_; }
|
||||
|
||||
// to do checks like if(log_ref)
|
||||
operator bool() { return ptr_ != nullptr; }
|
||||
|
||||
private:
|
||||
ptr_type ptr_ = nullptr;
|
||||
};
|
||||
|
||||
class logmap : public singleton_t<logmap>
|
||||
{
|
||||
public:
|
||||
// Access to log map by servicename. If servicename does not exist, create a new log_filter with default cfg
|
||||
// Access to the map is protected by a mutex
|
||||
static log_ref get(std::string servicename);
|
||||
|
||||
// register manually created log
|
||||
static void register_log(std::unique_ptr<log> log_ptr);
|
||||
|
||||
static std::unique_ptr<srslte::log> deregister_log(const std::string& servicename);
|
||||
|
||||
// set default logger
|
||||
static void set_default_logger(logger* logger_);
|
||||
|
||||
// set default log level
|
||||
static void set_default_log_level(LOG_LEVEL_ENUM l);
|
||||
|
||||
// set default hex limit
|
||||
static void set_default_hex_limit(int hex_limit);
|
||||
|
||||
protected:
|
||||
logmap();
|
||||
|
||||
private:
|
||||
log_ref get_impl(std::string servicename);
|
||||
|
||||
// default cfg
|
||||
std::unique_ptr<srslog_wrapper> stdout_channel;
|
||||
logger* default_logger = nullptr;
|
||||
srslte::LOG_LEVEL_ENUM default_log_level = LOG_LEVEL_WARNING;
|
||||
int default_hex_limit = 1024;
|
||||
|
||||
// state
|
||||
std::mutex mutex;
|
||||
std::unordered_map<std::string, std::unique_ptr<log> > log_map;
|
||||
};
|
||||
|
||||
} // namespace srslte
|
||||
|
||||
#endif // SRSLTE_LOGMAP_H
|
@ -1,298 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 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 <cstdlib>
|
||||
#include <inttypes.h>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "srslte/common/log_filter.h"
|
||||
#include "srslte/srslog/srslog.h"
|
||||
|
||||
namespace srslte {
|
||||
|
||||
#define CHARS_FOR_HEX_DUMP(size) \
|
||||
(3 * size + size / 16 * 20) // 3 chars per byte, plus 20 per line for position and newline)
|
||||
|
||||
log_filter::log_filter() : log()
|
||||
{
|
||||
do_tti = false;
|
||||
time_src = NULL;
|
||||
time_format = TIME;
|
||||
logger_h = NULL;
|
||||
}
|
||||
|
||||
/// Creates a log channel that writes to stdout.
|
||||
static srslog::log_channel* create_or_get_default_logger()
|
||||
{
|
||||
srslog::sink* s = srslog::create_stdout_sink();
|
||||
if (!s) {
|
||||
s = srslog::find_sink("stdout");
|
||||
}
|
||||
srslog::log_channel* log = srslog::create_log_channel("log_filter_default", *s);
|
||||
if (!log) {
|
||||
log = srslog::find_log_channel("log_filter_default");
|
||||
}
|
||||
|
||||
srslog::init();
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
log_filter::log_filter(std::string layer) : log()
|
||||
{
|
||||
do_tti = false;
|
||||
time_src = NULL;
|
||||
time_format = TIME;
|
||||
default_logger = std::unique_ptr<srslog_wrapper>(new srslog_wrapper(*create_or_get_default_logger()));
|
||||
init(layer, default_logger.get(), do_tti);
|
||||
}
|
||||
|
||||
log_filter::log_filter(std::string layer, logger* logger_, bool tti) : log()
|
||||
{
|
||||
do_tti = false;
|
||||
time_src = NULL;
|
||||
time_format = TIME;
|
||||
|
||||
if (!logger_) {
|
||||
default_logger = std::unique_ptr<srslog_wrapper>(new srslog_wrapper(*create_or_get_default_logger()));
|
||||
logger_ = default_logger.get();
|
||||
}
|
||||
|
||||
init(std::move(layer), logger_, tti);
|
||||
}
|
||||
|
||||
void log_filter::init(std::string layer, logger* logger_, bool tti)
|
||||
{
|
||||
// strip trailing white spaces
|
||||
size_t last_char_pos = layer.find_last_not_of(' ');
|
||||
if (last_char_pos != layer.size() - 1) {
|
||||
layer.erase(last_char_pos + 1, layer.size());
|
||||
}
|
||||
service_name = std::move(layer);
|
||||
logger_h = logger_;
|
||||
do_tti = tti;
|
||||
}
|
||||
|
||||
void log_filter::all_log(srslte::LOG_LEVEL_ENUM level,
|
||||
uint32_t tti,
|
||||
char* msg,
|
||||
const uint8_t* hex,
|
||||
int size,
|
||||
bool long_msg)
|
||||
{
|
||||
char buffer_tti[16] = {};
|
||||
|
||||
if (logger_h) {
|
||||
logger::unique_log_str_t log_str = nullptr;
|
||||
|
||||
if (long_msg || hex) {
|
||||
// For long messages, dynamically allocate a new log_str with enough size outside the pool.
|
||||
uint32_t log_str_msg_len = sizeof(buffer_tti) + 20 + strlen(msg) + CHARS_FOR_HEX_DUMP(size);
|
||||
log_str = logger::unique_log_str_t(new logger::log_str(nullptr, log_str_msg_len), logger::log_str_deleter());
|
||||
} else {
|
||||
log_str = logger_h->allocate_unique_log_str();
|
||||
}
|
||||
|
||||
if (log_str) {
|
||||
if (do_tti) {
|
||||
get_tti_str(tti, buffer_tti, sizeof(buffer_tti));
|
||||
}
|
||||
|
||||
// Trim away a newline character at the end of the message.
|
||||
if (msg[strlen(msg) - 1] == '\n') {
|
||||
msg[strlen(msg) - 1] = '\0';
|
||||
}
|
||||
|
||||
snprintf(log_str->str(),
|
||||
log_str->get_buffer_size(),
|
||||
"[%-4s] %s %s%s%s%s",
|
||||
get_service_name().c_str(),
|
||||
log_level_text_short[level],
|
||||
do_tti ? buffer_tti : "",
|
||||
add_string_en ? add_string_val.c_str() : "",
|
||||
msg,
|
||||
(hex_limit > 0 && hex && size > 0) ? hex_string(hex, size).c_str() : "");
|
||||
|
||||
logger_h->log(std::move(log_str));
|
||||
} else {
|
||||
logger_h->log_char("Error in Log: Not enough buffers in pool\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define all_log_expand(log_level) \
|
||||
do { \
|
||||
if (level >= log_level) { \
|
||||
char args_msg[char_buff_size]; \
|
||||
va_list args; \
|
||||
va_start(args, message); \
|
||||
if (vsnprintf(args_msg, char_buff_size, message, args) > 0) \
|
||||
all_log(log_level, tti, args_msg); \
|
||||
va_end(args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define all_log_hex_expand(log_level) \
|
||||
do { \
|
||||
if (level >= log_level) { \
|
||||
char args_msg[char_buff_size]; \
|
||||
va_list args; \
|
||||
va_start(args, message); \
|
||||
if (vsnprintf(args_msg, char_buff_size, message, args) > 0) \
|
||||
all_log(log_level, tti, args_msg, hex, size); \
|
||||
va_end(args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void log_filter::error(const char* message, ...)
|
||||
{
|
||||
all_log_expand(LOG_LEVEL_ERROR);
|
||||
}
|
||||
|
||||
void log_filter::warning(const char* message, ...)
|
||||
{
|
||||
all_log_expand(LOG_LEVEL_WARNING);
|
||||
}
|
||||
|
||||
void log_filter::info(const char* message, ...)
|
||||
{
|
||||
all_log_expand(LOG_LEVEL_INFO);
|
||||
}
|
||||
|
||||
void log_filter::info_long(const char* message, ...)
|
||||
{
|
||||
if (level >= LOG_LEVEL_INFO) {
|
||||
char* args_msg = NULL;
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
if (vasprintf(&args_msg, message, args) > 0)
|
||||
all_log(LOG_LEVEL_INFO, tti, args_msg, nullptr, strlen(args_msg), true);
|
||||
va_end(args);
|
||||
free(args_msg);
|
||||
}
|
||||
}
|
||||
|
||||
void log_filter::debug(const char* message, ...)
|
||||
{
|
||||
all_log_expand(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
|
||||
void log_filter::debug_long(const char* message, ...)
|
||||
{
|
||||
if (level >= LOG_LEVEL_DEBUG) {
|
||||
char* args_msg = NULL;
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
if (vasprintf(&args_msg, message, args) > 0)
|
||||
all_log(LOG_LEVEL_DEBUG, tti, args_msg, nullptr, strlen(args_msg), true);
|
||||
va_end(args);
|
||||
free(args_msg);
|
||||
}
|
||||
}
|
||||
|
||||
void log_filter::error_hex(const uint8_t* hex, int size, const char* message, ...)
|
||||
{
|
||||
all_log_hex_expand(LOG_LEVEL_ERROR);
|
||||
}
|
||||
|
||||
void log_filter::warning_hex(const uint8_t* hex, int size, const char* message, ...)
|
||||
{
|
||||
all_log_hex_expand(LOG_LEVEL_WARNING);
|
||||
}
|
||||
|
||||
void log_filter::info_hex(const uint8_t* hex, int size, const char* message, ...)
|
||||
{
|
||||
all_log_hex_expand(LOG_LEVEL_INFO);
|
||||
}
|
||||
|
||||
void log_filter::debug_hex(const uint8_t* hex, int size, const char* message, ...)
|
||||
{
|
||||
all_log_hex_expand(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
|
||||
void log_filter::set_time_src(time_itf* source, time_format_t format)
|
||||
{
|
||||
this->time_src = source;
|
||||
this->time_format = format;
|
||||
}
|
||||
void log_filter::get_tti_str(const uint32_t tti_, char* buffer, const uint32_t buffer_len)
|
||||
{
|
||||
snprintf(buffer, buffer_len, "[%5d] ", tti_);
|
||||
}
|
||||
|
||||
void log_filter::now_time(char* buffer, const uint32_t buffer_len)
|
||||
{
|
||||
timeval rawtime = {};
|
||||
tm timeinfo = {};
|
||||
char us[16];
|
||||
|
||||
srslte_timestamp_t now;
|
||||
uint64_t usec_epoch;
|
||||
|
||||
if (buffer_len < 16) {
|
||||
fprintf(stderr, "Error buffer provided for time too small\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!time_src) {
|
||||
gettimeofday(&rawtime, nullptr);
|
||||
gmtime_r(&rawtime.tv_sec, &timeinfo);
|
||||
|
||||
if (time_format == TIME) {
|
||||
strftime(buffer, buffer_len, "%H:%M:%S.", &timeinfo);
|
||||
snprintf(us, 16, "%06ld", rawtime.tv_usec);
|
||||
uint32_t dest_len = (uint32_t)strlen(buffer);
|
||||
strncat(buffer, us, buffer_len - dest_len - 1);
|
||||
} else {
|
||||
usec_epoch = rawtime.tv_sec * 1000000UL + rawtime.tv_usec;
|
||||
snprintf(buffer, buffer_len, "%" PRIu64, usec_epoch);
|
||||
}
|
||||
} else {
|
||||
now = time_src->get_time();
|
||||
|
||||
if (time_format == TIME) {
|
||||
snprintf(buffer, buffer_len, "%ld:%06u", now.full_secs, (uint32_t)(now.frac_secs * 1e6));
|
||||
} else {
|
||||
usec_epoch = now.full_secs * 1000000UL + (uint64_t)(now.frac_secs * 1e6);
|
||||
snprintf(buffer, buffer_len, "%" PRIu64, usec_epoch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string log_filter::hex_string(const uint8_t* hex, int size)
|
||||
{
|
||||
std::stringstream ss;
|
||||
int c = 0;
|
||||
|
||||
ss << '\n' << std::hex << std::setfill('0');
|
||||
if (hex_limit >= 0) {
|
||||
size = (size > hex_limit) ? hex_limit : size;
|
||||
}
|
||||
while (c < size) {
|
||||
ss << " " << std::setw(4) << static_cast<unsigned>(c) << ": ";
|
||||
int tmp = (size - c < 16) ? size - c : 16;
|
||||
for (int i = 0; i < tmp; i++) {
|
||||
ss << std::setw(2) << static_cast<unsigned>(hex[c++]) << " ";
|
||||
}
|
||||
if (c != size) {
|
||||
ss << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
} // namespace srslte
|
@ -1,21 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 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 "srslte/common/logger_srslog_wrapper.h"
|
||||
#include "srslte/srslog/log_channel.h"
|
||||
|
||||
using namespace srslte;
|
||||
|
||||
void srslog_wrapper::log(unique_log_str_t msg)
|
||||
{
|
||||
chan("%s", msg->str());
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 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 "srslte/common/logmap.h"
|
||||
#include "srslte/common/log_filter.h"
|
||||
#include "srslte/srslog/srslog.h"
|
||||
|
||||
using namespace srslte;
|
||||
|
||||
log_ref::log_ref(const char* name)
|
||||
{
|
||||
ptr_ = srslte::logmap::get(name).ptr_;
|
||||
}
|
||||
|
||||
/// Creates a log channel that writes to stdout.
|
||||
static srslog::log_channel* create_or_get_default_logger()
|
||||
{
|
||||
srslog::sink* s = srslog::create_stdout_sink();
|
||||
if (!s) {
|
||||
s = srslog::find_sink("stdout");
|
||||
}
|
||||
srslog::log_channel* log = srslog::create_log_channel("logmap_default", *s);
|
||||
if (!log) {
|
||||
log = srslog::find_log_channel("logmap_default");
|
||||
}
|
||||
|
||||
srslog::init();
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
logmap::logmap()
|
||||
{
|
||||
stdout_channel = std::unique_ptr<srslog_wrapper>(new srslog_wrapper(*create_or_get_default_logger()));
|
||||
default_logger = stdout_channel.get();
|
||||
}
|
||||
|
||||
// Access to log map by servicename. If servicename does not exist, create a new log_filter with default cfg
|
||||
// Access to the map is protected by a mutex
|
||||
log_ref SRSLTE_EXPORT logmap::get(std::string servicename)
|
||||
{
|
||||
logmap* pool = get_instance();
|
||||
// strip trailing white spaces
|
||||
size_t last_char_pos = servicename.find_last_not_of(' ');
|
||||
if (last_char_pos != servicename.size() - 1) {
|
||||
servicename.erase(last_char_pos + 1, servicename.size());
|
||||
}
|
||||
return pool->get_impl(std::move(servicename));
|
||||
}
|
||||
|
||||
// register manually created log
|
||||
void SRSLTE_EXPORT logmap::register_log(std::unique_ptr<log> log_ptr)
|
||||
{
|
||||
logmap* pool = get_instance();
|
||||
std::lock_guard<std::mutex> lock(pool->mutex);
|
||||
if (log_ptr != nullptr) {
|
||||
pool->log_map[log_ptr->get_service_name()] = std::move(log_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<srslte::log> SRSLTE_EXPORT logmap::deregister_log(const std::string& servicename)
|
||||
{
|
||||
logmap* pool = get_instance();
|
||||
std::unique_ptr<srslte::log> ret;
|
||||
std::lock_guard<std::mutex> lock(pool->mutex);
|
||||
auto it = pool->log_map.find(servicename);
|
||||
if (it != pool->log_map.end()) {
|
||||
ret = std::move(it->second);
|
||||
pool->log_map.erase(it);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// set default logger
|
||||
void SRSLTE_EXPORT logmap::set_default_logger(logger* logger_)
|
||||
{
|
||||
logmap* pool = get_instance();
|
||||
std::lock_guard<std::mutex> lock(pool->mutex);
|
||||
pool->default_logger = logger_;
|
||||
}
|
||||
|
||||
// set default log level
|
||||
void SRSLTE_EXPORT logmap::set_default_log_level(LOG_LEVEL_ENUM l)
|
||||
{
|
||||
logmap* pool = get_instance();
|
||||
std::lock_guard<std::mutex> lock(pool->mutex);
|
||||
pool->default_log_level = l;
|
||||
}
|
||||
|
||||
// set default hex limit
|
||||
void SRSLTE_EXPORT logmap::set_default_hex_limit(int hex_limit)
|
||||
{
|
||||
logmap* pool = get_instance();
|
||||
std::lock_guard<std::mutex> lock(pool->mutex);
|
||||
pool->default_hex_limit = hex_limit;
|
||||
}
|
||||
|
||||
log_ref logmap::get_impl(std::string servicename)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
auto it = log_map.find(servicename);
|
||||
if (it == log_map.end()) {
|
||||
// create a new logger with default cfg
|
||||
std::unique_ptr<log_filter> filter(new log_filter{std::move(servicename), default_logger});
|
||||
filter->set_level(default_log_level);
|
||||
filter->set_hex_limit(default_hex_limit);
|
||||
auto ret = log_map.insert(std::make_pair(filter->get_service_name(), std::move(filter)));
|
||||
return log_ref{&ret.first->second};
|
||||
}
|
||||
return log_ref{&it->second};
|
||||
}
|
@ -1,219 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#define NTHREADS 100
|
||||
#define NMSGS 100
|
||||
|
||||
#include "srslte/common/log_filter.h"
|
||||
#include "srslte/common/logger_srslog_wrapper.h"
|
||||
#include "srslte/common/logmap.h"
|
||||
#include "srslte/common/test_common.h"
|
||||
#include "srslte/srslog/srslog.h"
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace srslte;
|
||||
|
||||
typedef struct {
|
||||
logger* l;
|
||||
int thread_id;
|
||||
} args_t;
|
||||
|
||||
void* thread_loop(void* a)
|
||||
{
|
||||
args_t* args = (args_t*)a;
|
||||
char buf[100];
|
||||
|
||||
sprintf(buf, "LAYER%d", args->thread_id);
|
||||
log_filter filter(buf, args->l);
|
||||
filter.set_level(LOG_LEVEL_INFO);
|
||||
|
||||
for (int i = 0; i < NMSGS; i++) {
|
||||
filter.error("Thread %d: %d", args->thread_id, i);
|
||||
filter.warning("Thread %d: %d", args->thread_id, i);
|
||||
filter.info("Thread %d: %d", args->thread_id, i);
|
||||
filter.debug("Thread %d: %d", args->thread_id, i);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* thread_loop_hex(void* a)
|
||||
{
|
||||
args_t* args = (args_t*)a;
|
||||
char buf[100];
|
||||
uint8_t hex[100];
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
hex[i] = i & 0xFF;
|
||||
}
|
||||
sprintf(buf, "LAYER%d", args->thread_id);
|
||||
log_filter filter(buf, args->l);
|
||||
filter.set_level(LOG_LEVEL_DEBUG);
|
||||
filter.set_hex_limit(32);
|
||||
|
||||
for (int i = 0; i < NMSGS; i++) {
|
||||
filter.error_hex(hex, 100, "Thread %d: %d", args->thread_id, i);
|
||||
filter.warning_hex(hex, 100, "Thread %d: %d", args->thread_id, i);
|
||||
filter.info_hex(hex, 100, "Thread %d: %d", args->thread_id, i);
|
||||
filter.debug_hex(hex, 100, "Thread %d: %d", args->thread_id, i);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void write(std::string filename)
|
||||
{
|
||||
srslog::sink* s = srslog::create_file_sink(filename);
|
||||
srslog::log_channel* chan = srslog::create_log_channel("write", *s);
|
||||
srslte::srslog_wrapper l(*chan);
|
||||
|
||||
pthread_t threads[NTHREADS];
|
||||
args_t args[NTHREADS];
|
||||
for (int i = 0; i < NTHREADS; i++) {
|
||||
args[i].l = &l;
|
||||
args[i].thread_id = i;
|
||||
pthread_create(&threads[i], NULL, &thread_loop_hex, &args[i]);
|
||||
}
|
||||
for (int i = 0; i < NTHREADS; i++) {
|
||||
pthread_join(threads[i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
bool read(std::string filename)
|
||||
{
|
||||
bool pass = true;
|
||||
bool written[NTHREADS][NMSGS];
|
||||
int thread, msg;
|
||||
|
||||
for (int i = 0; i < NTHREADS; i++) {
|
||||
for (int j = 0; j < NMSGS; j++) {
|
||||
written[i][j] = false;
|
||||
}
|
||||
}
|
||||
FILE* f = fopen(filename.c_str(), "r");
|
||||
if (f != NULL) {
|
||||
while (fscanf(f, "Thread %d: %d\n", &thread, &msg)) {
|
||||
written[thread][msg] = true;
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
for (int i = 0; i < NTHREADS; i++) {
|
||||
for (int j = 0; j < NMSGS; j++) {
|
||||
if (!written[i][j])
|
||||
pass = false;
|
||||
}
|
||||
}
|
||||
return pass;
|
||||
}
|
||||
|
||||
int basic_hex_test()
|
||||
{
|
||||
srslog::sink* s = srslog::find_sink("stdout");
|
||||
if (!s) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslog::log_channel* chan = srslog::create_log_channel("basic_hex_test", *s);
|
||||
if (!chan) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
srslte::srslog_wrapper l(*chan);
|
||||
|
||||
log_filter filter("layer", &l);
|
||||
filter.set_level(LOG_LEVEL_DEBUG);
|
||||
filter.set_hex_limit(500);
|
||||
|
||||
const uint32_t hex_len = 497;
|
||||
|
||||
uint8_t hex[hex_len];
|
||||
for (uint32_t i = 0; i < hex_len; i++) {
|
||||
hex[i] = i & 0xFF;
|
||||
}
|
||||
|
||||
filter.debug_hex(hex, hex_len, "This is the long hex msg (%d B)\n", hex_len);
|
||||
filter.debug("This is a message after the long hex msg that should not be cut\n");
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int test_log_singleton()
|
||||
{
|
||||
srslte::logmap::set_default_log_level(LOG_LEVEL_DEBUG);
|
||||
|
||||
// TEST: Check if default setters are working
|
||||
srslte::log_ref log1 = srslte::logmap::get("LAYER1");
|
||||
TESTASSERT(log1->get_service_name() == "LAYER1");
|
||||
TESTASSERT(log1->get_level() == LOG_LEVEL_DEBUG);
|
||||
|
||||
// TEST: register logger manually. Verify log_ref stays valid after overwrite
|
||||
std::unique_ptr<srslte::log_filter> log_ptr2(new srslte::log_filter("LAYER2"));
|
||||
log_ptr2->set_level(LOG_LEVEL_WARNING);
|
||||
srslte::log_ref old_ref = srslte::logmap::get("LAYER2");
|
||||
TESTASSERT(old_ref->get_level() == LOG_LEVEL_DEBUG);
|
||||
srslte::logmap::register_log(std::move(log_ptr2));
|
||||
srslte::log_ref new_ref = srslte::logmap::get("LAYER2");
|
||||
TESTASSERT(new_ref->get_level() == LOG_LEVEL_WARNING);
|
||||
TESTASSERT(old_ref == new_ref);
|
||||
|
||||
// TEST: padding working correctly
|
||||
TESTASSERT(srslte::logmap::get("MAC").get() == srslte::logmap::get("MAC ").get());
|
||||
|
||||
log1->info("logmap test finished successfully\n");
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int test_log_ref()
|
||||
{
|
||||
// Check if trailing whitespaces are correctly removed
|
||||
srslte::log_ref t1_log{"T1"};
|
||||
TESTASSERT(t1_log->get_service_name() == "T1");
|
||||
TESTASSERT(t1_log.get() == srslte::logmap::get("T1").get());
|
||||
TESTASSERT(t1_log.get() == srslte::logmap::get("T1 ").get());
|
||||
{
|
||||
scoped_log<srslte::nullsink_log> null_log{"T2"};
|
||||
TESTASSERT(null_log->get_service_name() == "T2");
|
||||
}
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int full_test()
|
||||
{
|
||||
std::string f("log.txt");
|
||||
write(f);
|
||||
#if 0
|
||||
bool result = read(f);
|
||||
remove(f.c_str());
|
||||
if(result) {
|
||||
printf("Passed\n");
|
||||
exit(0);
|
||||
}else{
|
||||
printf("Failed\n;");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
// Setup logging.
|
||||
srslog::sink* log_sink = srslog::create_stdout_sink();
|
||||
if (!log_sink) {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
|
||||
TESTASSERT(basic_hex_test() == SRSLTE_SUCCESS);
|
||||
TESTASSERT(full_test() == SRSLTE_SUCCESS);
|
||||
TESTASSERT(test_log_singleton() == SRSLTE_SUCCESS);
|
||||
TESTASSERT(test_log_ref() == SRSLTE_SUCCESS);
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2020 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 "srslte/common/test_common.h"
|
||||
|
||||
using srslte::nullsink_log;
|
||||
using srslte::scoped_log;
|
||||
|
||||
int test_nullsink_log()
|
||||
{
|
||||
// Description: Test nullsink_log that only stores the last log message in a local std::string that can be checked
|
||||
// This logger is useful to confirm that a certain action produced an expected error/warning,
|
||||
// without contaminating the console/log file, and to check what error message was stored
|
||||
scoped_log<nullsink_log> null_log("TEST");
|
||||
|
||||
TESTASSERT(srslte::logmap::get("TEST").get() == null_log.get());
|
||||
TESTASSERT(null_log->error_counter == 0);
|
||||
TESTASSERT(null_log->last_log_level == srslte::LOG_LEVEL_NONE);
|
||||
TESTASSERT(null_log->last_log_msg.empty());
|
||||
null_log->error("ERROR MESSAGE"); // This message should not be seen in the console
|
||||
TESTASSERT(null_log->error_counter == 1);
|
||||
TESTASSERT(null_log->last_log_level == srslte::LOG_LEVEL_ERROR);
|
||||
TESTASSERT(null_log->last_log_msg == "ERROR MESSAGE");
|
||||
|
||||
return SRSLTE_SUCCESS;
|
||||
}
|
||||
|
||||
int test_log_scoping()
|
||||
{
|
||||
// Description: Test whether we can use different global TEST loggers in different scopes
|
||||
// on scope exit the previous logger should be recovered
|
||||
// This behavior is useful for the cases we have one generic logger for all tests, but in a specific test
|
||||
// we want to use a different one
|
||||
scoped_log<nullsink_log> log1("TEST");
|
||||
TESTASSERT(srslte::logmap::get("TEST").get() == log1.get());
|
||||
|
||||
log1->error("message1");
|
||||
log1->error("message2");
|
||||
TESTASSERT(log1->last_log_msg == "message2");
|
||||
TESTASSERT(log1->error_counter == 2);
|
||||
|
||||
{
|
||||
// the global test log should be overwriten here, and used by TESTASSERT macro
|
||||
scoped_log<nullsink_log> log2("TEST");
|
||||
TESTASSERT(srslte::logmap::get("TEST").get() == log2.get());
|
||||
TESTASSERT(log2->error_counter == 0);
|
||||
log2->error("error message in logger2\n");
|
||||
TESTASSERT(log2->last_log_msg == "error message in logger2\n");
|
||||
TESTASSERT(log2->error_counter == 1);
|
||||
}
|
||||
// the last logger should be recovered
|
||||
|
||||
TESTASSERT(srslte::logmap::get("TEST").get() == log1.get());
|
||||
TESTASSERT(log1->error_counter == 2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
TESTASSERT(test_nullsink_log() == 0);
|
||||
TESTASSERT(test_log_scoping() == 0);
|
||||
return 0;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue