mirror of https://github.com/pvnis/srsRAN_4G.git
Merge branch 'next' into agpl_next
# Conflicts: # lib/include/srslte/common/log.h # lib/include/srslte/common/log_filter.h # lib/include/srslte/common/logger.h # lib/include/srslte/common/logger_srslog_wrapper.h # lib/include/srslte/common/logmap.h # lib/src/common/log_filter.cc # lib/src/common/logger_srslog_wrapper.cc # lib/src/common/logmap.cc # lib/test/common/log_filter_test.cc # lib/test/common/test_common_test.ccmaster
commit
6ccccade9e
@ -0,0 +1,450 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* \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_CIRCULAR_BUFFER_H
|
||||||
|
#define SRSLTE_CIRCULAR_BUFFER_H
|
||||||
|
|
||||||
|
#include "srslte/adt/expected.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
size_t get_max_size(const std::array<T, N>& a)
|
||||||
|
{
|
||||||
|
return a.max_size();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
size_t get_max_size(const std::vector<T>& a)
|
||||||
|
{
|
||||||
|
return a.capacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base common class for definition of circular buffer data structures with the following features:
|
||||||
|
* - no allocations while pushing/popping new elements. Just an internal index update
|
||||||
|
* - it provides helper methods to add/remove objects
|
||||||
|
* - it provides an iterator interface to iterate over added elements in the buffer
|
||||||
|
* - not thread-safe
|
||||||
|
* @tparam Container underlying container type used as buffer (e.g. std::array<T, N> or std::vector<T>)
|
||||||
|
*/
|
||||||
|
template <typename Container>
|
||||||
|
class base_circular_buffer
|
||||||
|
{
|
||||||
|
using T = typename Container::value_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using difference_type = typename Container::difference_type;
|
||||||
|
|
||||||
|
struct iterator {
|
||||||
|
iterator(base_circular_buffer<Container>& parent_, size_t i) : parent(&parent_), idx(i) {}
|
||||||
|
iterator& operator++()
|
||||||
|
{
|
||||||
|
idx = (idx + 1) % parent->max_size();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
iterator operator++(int)
|
||||||
|
{
|
||||||
|
iterator tmp(*this);
|
||||||
|
++(*this);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
iterator operator+(difference_type n)
|
||||||
|
{
|
||||||
|
iterator tmp(*this);
|
||||||
|
tmp += n;
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
iterator& operator+=(difference_type n)
|
||||||
|
{
|
||||||
|
idx = (idx + n) % parent->max_size();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
value_type* operator->() { return &parent->buffer[idx]; }
|
||||||
|
const value_type* operator->() const { return &parent->buffer[idx]; }
|
||||||
|
value_type& operator*() { return parent->buffer[idx]; }
|
||||||
|
const value_type& operator*() const { return parent->buffer[idx]; }
|
||||||
|
bool operator==(const iterator& it) const { return it.parent == parent and it.idx == idx; }
|
||||||
|
bool operator!=(const iterator& it) const { return not(*this == it); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
base_circular_buffer<Container>* parent;
|
||||||
|
size_t idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
explicit base_circular_buffer(Args&&... args) : buffer(std::forward<Args>(args)...)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool try_push(T&& t)
|
||||||
|
{
|
||||||
|
if (full()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
push(std::move(t));
|
||||||
|
}
|
||||||
|
void push(T&& t)
|
||||||
|
{
|
||||||
|
assert(not full());
|
||||||
|
size_t wpos = (rpos + count) % max_size();
|
||||||
|
buffer[wpos] = std::move(t);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
bool try_push(const T& t)
|
||||||
|
{
|
||||||
|
if (full()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
push(t);
|
||||||
|
}
|
||||||
|
void push(const T& t)
|
||||||
|
{
|
||||||
|
assert(not full());
|
||||||
|
size_t wpos = (rpos + count) % max_size();
|
||||||
|
buffer[wpos] = t;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
void pop()
|
||||||
|
{
|
||||||
|
assert(not empty());
|
||||||
|
rpos = (rpos + 1) % max_size();
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
T& top()
|
||||||
|
{
|
||||||
|
assert(not empty());
|
||||||
|
return buffer[rpos];
|
||||||
|
}
|
||||||
|
const T& top() const
|
||||||
|
{
|
||||||
|
assert(not empty());
|
||||||
|
return buffer[rpos];
|
||||||
|
}
|
||||||
|
void clear() { count = 0; }
|
||||||
|
|
||||||
|
bool full() const { return count == max_size(); }
|
||||||
|
bool empty() const { return count == 0; }
|
||||||
|
size_t size() const { return count; }
|
||||||
|
size_t max_size() const { return detail::get_max_size(buffer); }
|
||||||
|
|
||||||
|
iterator begin() { return iterator(*this, rpos); }
|
||||||
|
iterator end() { return iterator(*this, (rpos + count) % max_size()); }
|
||||||
|
|
||||||
|
template <typename = std::enable_if<std::is_same<Container, std::vector<T> >::value> >
|
||||||
|
void set_size(size_t size)
|
||||||
|
{
|
||||||
|
buffer.resize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Container buffer;
|
||||||
|
size_t rpos = 0;
|
||||||
|
size_t count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct noop_operator {
|
||||||
|
template <typename T>
|
||||||
|
void operator()(const T&)
|
||||||
|
{
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base common class for definition of blocking queue data structures with the following features:
|
||||||
|
* - it stores pushed/popped samples in an internal circular buffer
|
||||||
|
* - provides blocking and non-blocking push/pop APIs
|
||||||
|
* - thread-safe
|
||||||
|
* @tparam CircBuffer underlying circular buffer data type (e.g. static_circular_buffer<T, N> or dyn_circular_buffer<T>)
|
||||||
|
* @tparam PushingFunc function void(const T&) called while pushing an element to the queue
|
||||||
|
* @tparam PoppingFunc function void(const T&) called while popping an element from the queue
|
||||||
|
*/
|
||||||
|
template <typename CircBuffer, typename PushingFunc, typename PoppingFunc>
|
||||||
|
class base_blocking_queue
|
||||||
|
{
|
||||||
|
using T = typename CircBuffer::value_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <typename... Args>
|
||||||
|
base_blocking_queue(PushingFunc push_func_, PoppingFunc pop_func_, Args&&... args) :
|
||||||
|
circ_buffer(std::forward<Args>(args)...), push_func(push_func_), pop_func(pop_func_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void stop()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
if (active) {
|
||||||
|
active = false;
|
||||||
|
if (nof_waiting == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
lock.unlock();
|
||||||
|
cvar_empty.notify_all();
|
||||||
|
cvar_full.notify_all();
|
||||||
|
std::this_thread::yield();
|
||||||
|
lock.lock();
|
||||||
|
} while (nof_waiting > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_push(const T& t) { return push_(t, false); }
|
||||||
|
srslte::error_type<T> try_push(T&& t) { return push_(std::move(t), false); }
|
||||||
|
bool push_blocking(const T& t) { return push_(t, true); }
|
||||||
|
srslte::error_type<T> push_blocking(T&& t) { return push_(std::move(t), true); }
|
||||||
|
bool try_pop(T& obj) { return pop_(obj, false); }
|
||||||
|
T pop_blocking()
|
||||||
|
{
|
||||||
|
T obj{};
|
||||||
|
pop_(obj, true);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
bool pop_wait_until(T& obj, const std::chrono::system_clock::time_point& until) { return pop_(obj, true, &until); }
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
T obj;
|
||||||
|
while (pop_(obj, false)) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
return circ_buffer.size();
|
||||||
|
}
|
||||||
|
bool empty() const
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
return circ_buffer.empty();
|
||||||
|
}
|
||||||
|
bool full() const
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
return circ_buffer.full();
|
||||||
|
}
|
||||||
|
size_t max_size() const
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
return circ_buffer.max_size();
|
||||||
|
}
|
||||||
|
bool is_stopped() const
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
return not active;
|
||||||
|
}
|
||||||
|
template <typename F>
|
||||||
|
bool try_call_on_front(F&& f)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
if (not circ_buffer.empty()) {
|
||||||
|
f(circ_buffer.top());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool active = true;
|
||||||
|
uint8_t nof_waiting = 0;
|
||||||
|
mutable std::mutex mutex;
|
||||||
|
std::condition_variable cvar_empty, cvar_full;
|
||||||
|
PushingFunc push_func;
|
||||||
|
PoppingFunc pop_func;
|
||||||
|
CircBuffer circ_buffer;
|
||||||
|
|
||||||
|
~base_blocking_queue() { stop(); }
|
||||||
|
|
||||||
|
bool push_(const T& t, bool block_mode)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
if (not active) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (circ_buffer.full()) {
|
||||||
|
if (not block_mode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nof_waiting++;
|
||||||
|
while (circ_buffer.full() and active) {
|
||||||
|
cvar_full.wait(lock);
|
||||||
|
}
|
||||||
|
nof_waiting--;
|
||||||
|
if (not active) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
push_func(t);
|
||||||
|
circ_buffer.push(t);
|
||||||
|
lock.unlock();
|
||||||
|
cvar_empty.notify_one();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
srslte::error_type<T> push_(T&& t, bool block_mode)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
if (not active) {
|
||||||
|
return std::move(t);
|
||||||
|
}
|
||||||
|
if (circ_buffer.full()) {
|
||||||
|
if (not block_mode) {
|
||||||
|
return std::move(t);
|
||||||
|
}
|
||||||
|
nof_waiting++;
|
||||||
|
while (circ_buffer.full() and active) {
|
||||||
|
cvar_full.wait(lock);
|
||||||
|
}
|
||||||
|
nof_waiting--;
|
||||||
|
if (not active) {
|
||||||
|
return std::move(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
push_func(t);
|
||||||
|
circ_buffer.push(std::move(t));
|
||||||
|
lock.unlock();
|
||||||
|
cvar_empty.notify_one();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool pop_(T& obj, bool block, const std::chrono::system_clock::time_point* until = nullptr)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
|
if (not active) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (circ_buffer.empty()) {
|
||||||
|
if (not block) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nof_waiting++;
|
||||||
|
if (until == nullptr) {
|
||||||
|
cvar_empty.wait(lock, [this]() { return not circ_buffer.empty() or not active; });
|
||||||
|
} else {
|
||||||
|
cvar_empty.wait_until(lock, *until, [this]() { return not circ_buffer.empty() or not active; });
|
||||||
|
}
|
||||||
|
nof_waiting--;
|
||||||
|
if (circ_buffer.empty()) {
|
||||||
|
// either queue got deactivated or there was a timeout
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
obj = std::move(circ_buffer.top());
|
||||||
|
pop_func(obj);
|
||||||
|
circ_buffer.pop();
|
||||||
|
lock.unlock();
|
||||||
|
cvar_full.notify_one();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Circular buffer with fixed, embedded buffer storage via a std::array<T, N>.
|
||||||
|
* - Single allocation at object creation for std::array. Given that the buffer size is known at compile-time, the
|
||||||
|
* circular iteration over the buffer may be more optimized (e.g. when N is a power of 2, % operator can be avoided)
|
||||||
|
* - not thread-safe
|
||||||
|
* @tparam T value type stored by buffer
|
||||||
|
* @tparam N size of the queue
|
||||||
|
*/
|
||||||
|
template <typename T, size_t N>
|
||||||
|
class static_circular_buffer : public detail::base_circular_buffer<std::array<T, N> >
|
||||||
|
{};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Circular buffer with buffer storage via a std::vector<T>.
|
||||||
|
* - size can be defined at run-time.
|
||||||
|
* - not thread-safe
|
||||||
|
* @tparam T value type stored by buffer
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
class dyn_circular_buffer : public detail::base_circular_buffer<std::vector<T> >
|
||||||
|
{
|
||||||
|
using base_t = detail::base_circular_buffer<std::vector<T> >;
|
||||||
|
|
||||||
|
public:
|
||||||
|
dyn_circular_buffer() = default;
|
||||||
|
explicit dyn_circular_buffer(size_t size) : base_t(size) {}
|
||||||
|
|
||||||
|
void set_size(size_t size)
|
||||||
|
{
|
||||||
|
// Note: dynamic resizes not supported.
|
||||||
|
assert(base_t::empty());
|
||||||
|
base_t::set_size(size);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocking queue with fixed, embedded buffer storage via a std::array<T, N>.
|
||||||
|
* - Blocking push/pop API via push_blocking(...) and pop_blocking(...) methods
|
||||||
|
* - Non-blocking push/pop API via try_push(...) and try_pop(...) methods
|
||||||
|
* - Only one initial allocation for the std::array<T, N>
|
||||||
|
* - thread-safe
|
||||||
|
* @tparam T value type stored by buffer
|
||||||
|
* @tparam N size of queue
|
||||||
|
* @tparam PushingCallback function void(const T&) called while pushing an element to the queue
|
||||||
|
* @tparam PoppingCallback function void(const T&) called while popping an element from the queue
|
||||||
|
*/
|
||||||
|
template <typename T,
|
||||||
|
size_t N,
|
||||||
|
typename PushingCallback = detail::noop_operator,
|
||||||
|
typename PoppingCallback = detail::noop_operator>
|
||||||
|
class static_blocking_queue
|
||||||
|
: public detail::base_blocking_queue<static_circular_buffer<T, N>, PushingCallback, PoppingCallback>
|
||||||
|
{
|
||||||
|
using base_t = detail::base_blocking_queue<static_circular_buffer<T, N>, PushingCallback, PoppingCallback>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit static_blocking_queue(PushingCallback push_callback = {}, PoppingCallback pop_callback = {}) :
|
||||||
|
base_t(push_callback, pop_callback)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocking queue with buffer storage represented via a std::vector<T>. Features:
|
||||||
|
* - Blocking push/pop API via push_blocking(...) and pop_blocking(...) methods
|
||||||
|
* - Non-blocking push/pop API via try_push(...) and try_pop(...) methods
|
||||||
|
* - Size can be defined at runtime.
|
||||||
|
* - thread-safe
|
||||||
|
* @tparam T value type stored by buffer
|
||||||
|
* @tparam PushingCallback function void(const T&) called while pushing an element to the queue
|
||||||
|
* @tparam PoppingCallback function void(const T&) called while popping an element from the queue
|
||||||
|
*/
|
||||||
|
template <typename T,
|
||||||
|
typename PushingCallback = detail::noop_operator,
|
||||||
|
typename PoppingCallback = detail::noop_operator>
|
||||||
|
class dyn_blocking_queue : public detail::base_blocking_queue<dyn_circular_buffer<T>, PushingCallback, PoppingCallback>
|
||||||
|
{
|
||||||
|
using base_t = detail::base_blocking_queue<dyn_circular_buffer<T>, PushingCallback, PoppingCallback>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
dyn_blocking_queue() = default;
|
||||||
|
explicit dyn_blocking_queue(size_t size, PushingCallback push_callback = {}, PoppingCallback pop_callback = {}) :
|
||||||
|
base_t(push_callback, pop_callback, size)
|
||||||
|
{}
|
||||||
|
void set_size(size_t size) { base_t::circ_buffer.set_size(size); }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srslte
|
||||||
|
|
||||||
|
#endif // SRSLTE_CIRCULAR_BUFFER_H
|
@ -1,159 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2013-2021 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* This file is part of srsLTE.
|
|
||||||
*
|
|
||||||
* srsLTE 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.
|
|
||||||
*
|
|
||||||
* srsLTE 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: 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,99 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2013-2021 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* This file is part of srsLTE.
|
|
||||||
*
|
|
||||||
* srsLTE 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.
|
|
||||||
*
|
|
||||||
* srsLTE 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: 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,112 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2013-2021 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* This file is part of srsLTE.
|
|
||||||
*
|
|
||||||
* srsLTE 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.
|
|
||||||
*
|
|
||||||
* srsLTE 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: 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,49 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2013-2021 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* This file is part of srsLTE.
|
|
||||||
*
|
|
||||||
* srsLTE 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.
|
|
||||||
*
|
|
||||||
* srsLTE 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/.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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,103 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2013-2021 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* This file is part of srsLTE.
|
|
||||||
*
|
|
||||||
* srsLTE 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.
|
|
||||||
*
|
|
||||||
* srsLTE 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/.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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,307 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2013-2021 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* This file is part of srsLTE.
|
|
||||||
*
|
|
||||||
* srsLTE 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.
|
|
||||||
*
|
|
||||||
* srsLTE 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 <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,30 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2013-2021 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* This file is part of srsLTE.
|
|
||||||
*
|
|
||||||
* srsLTE 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.
|
|
||||||
*
|
|
||||||
* srsLTE 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 "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,129 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright 2013-2021 Software Radio Systems Limited
|
|
||||||
*
|
|
||||||
* This file is part of srsLTE.
|
|
||||||
*
|
|
||||||
* srsLTE 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.
|
|
||||||
*
|
|
||||||
* srsLTE 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 "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};
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue