mirror of https://github.com/pvnis/srsRAN_4G.git
Update srslog to latest version.
parent
b0a7506a8a
commit
98a2c868b5
@ -1,87 +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 SRSLOG_FORMATTER_H
|
||||
#define SRSLOG_FORMATTER_H
|
||||
|
||||
#include "srslte/srslog/bundled/fmt/chrono.h"
|
||||
#include "srslte/srslog/bundled/fmt/ranges.h"
|
||||
#include "srslte/srslog/detail/log_entry.h"
|
||||
|
||||
namespace srslog {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/// Formats into a hex dump a range of elements, storing the result in the input
|
||||
/// buffer.
|
||||
inline void format_hex_dump(const std::vector<uint8_t>& v,
|
||||
fmt::memory_buffer& buffer)
|
||||
{
|
||||
if (v.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t elements_per_line = 16;
|
||||
|
||||
for (auto i = v.cbegin(), e = v.cend(); i != e;) {
|
||||
auto num_elements =
|
||||
std::min<size_t>(elements_per_line, std::distance(i, e));
|
||||
|
||||
fmt::format_to(buffer,
|
||||
" {:04x}: {:02x}\n",
|
||||
std::distance(v.cbegin(), i),
|
||||
fmt::join(i, i + num_elements, " "));
|
||||
|
||||
std::advance(i, num_elements);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// Formats to text all the fields of a log entry,
|
||||
inline std::string format_log_entry_to_text(detail::log_entry&& entry)
|
||||
{
|
||||
fmt::memory_buffer buffer;
|
||||
|
||||
// Time stamp data preparation.
|
||||
std::tm current_time =
|
||||
fmt::gmtime(std::chrono::high_resolution_clock::to_time_t(entry.tp));
|
||||
auto us_fraction = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
entry.tp.time_since_epoch())
|
||||
.count() %
|
||||
1000000u;
|
||||
fmt::format_to(buffer, "{:%H:%M:%S}.{:06} ", current_time, us_fraction);
|
||||
|
||||
// Format optional fields if present.
|
||||
if (!entry.log_name.empty()) {
|
||||
fmt::format_to(buffer, "[{: <4.4}] ", entry.log_name);
|
||||
}
|
||||
if (entry.log_tag != '\0') {
|
||||
fmt::format_to(buffer, "[{}] ", entry.log_tag);
|
||||
}
|
||||
if (entry.context.enabled) {
|
||||
fmt::format_to(buffer, "[{:5}] ", entry.context.value);
|
||||
}
|
||||
|
||||
// Message formatting.
|
||||
fmt::format_to(
|
||||
buffer, "{}\n", fmt::vsprintf(entry.fmtstring, std::move(entry.store)));
|
||||
|
||||
// Optional hex dump formatting.
|
||||
detail::format_hex_dump(entry.hex_dump, buffer);
|
||||
|
||||
return fmt::to_string(buffer);
|
||||
}
|
||||
|
||||
} // namespace srslog
|
||||
|
||||
#endif // SRSLOG_FORMATTER_H
|
@ -1,114 +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 SRSLOG_SINK_REPOSITORY_H
|
||||
#define SRSLOG_SINK_REPOSITORY_H
|
||||
|
||||
#include "object_repository.h"
|
||||
#include "sinks/stream_sink.h"
|
||||
|
||||
namespace srslog {
|
||||
|
||||
/// The sink repository stores sink instances associated to an id. Both stdout
|
||||
/// and stderr stream sinks are created on construction so they accessible
|
||||
/// without the need of creating them previously.
|
||||
/// NOTE: Thread safe class.
|
||||
class sink_repository
|
||||
{
|
||||
/// Identifiers for stdout and stderr sinks.
|
||||
static constexpr char stdout_id[] = "stdout#";
|
||||
static constexpr char stderr_id[] = "stderr#";
|
||||
|
||||
object_repository<std::string, std::unique_ptr<sink> > repo;
|
||||
|
||||
public:
|
||||
sink_repository()
|
||||
{
|
||||
//:TODO: GCC5 or lower versions emits an error if we use the new() expression directly, use redundant
|
||||
//piecewise_construct instead.
|
||||
repo.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(stdout_id),
|
||||
std::forward_as_tuple(new stream_sink(sink_stream_type::stdout)));
|
||||
repo.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(stderr_id),
|
||||
std::forward_as_tuple(new stream_sink(sink_stream_type::stderr)));
|
||||
}
|
||||
|
||||
/// Returns the instance of the sink that writes to stdout.
|
||||
sink& get_stdout_sink()
|
||||
{
|
||||
auto s = repo.find(stdout_id);
|
||||
assert(s && "stdout sink should always exist");
|
||||
return *(s->get());
|
||||
}
|
||||
const sink& get_stdout_sink() const
|
||||
{
|
||||
const auto s = repo.find(stdout_id);
|
||||
assert(s && "stdout sink should always exist");
|
||||
return *(s->get());
|
||||
}
|
||||
|
||||
/// Returns the instance of the sink that writes to stderr.
|
||||
sink& get_stderr_sink()
|
||||
{
|
||||
auto s = repo.find(stderr_id);
|
||||
assert(s && "stderr sink should always exist");
|
||||
return *(s->get());
|
||||
}
|
||||
const sink& get_stderr_sink() const
|
||||
{
|
||||
const auto s = repo.find(stderr_id);
|
||||
assert(s && "stderr sink should always exist");
|
||||
return *(s->get());
|
||||
}
|
||||
|
||||
/// Finds a sink with the specified id in the repository. Returns a pointer to
|
||||
/// the sink, otherwise nullptr if not found.
|
||||
sink* find(const std::string& id)
|
||||
{
|
||||
auto p = repo.find(id);
|
||||
return (p) ? p->get() : nullptr;
|
||||
}
|
||||
const sink* find(const std::string& id) const
|
||||
{
|
||||
const auto p = repo.find(id);
|
||||
return (p) ? p->get() : nullptr;
|
||||
}
|
||||
|
||||
/// Returns an instance of a sink specified by the input arguments.
|
||||
template <typename... Args>
|
||||
sink& fetch_sink(Args&&... args)
|
||||
{
|
||||
return *repo.emplace(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/// Returns a copy of the list of registered sinks.
|
||||
std::vector<sink*> contents() const
|
||||
{
|
||||
auto repo_contents = repo.contents();
|
||||
|
||||
std::vector<sink*> data;
|
||||
data.reserve(repo_contents.size());
|
||||
for (const auto& s : repo_contents) {
|
||||
data.push_back(s->get());
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
constexpr char sink_repository::stdout_id[];
|
||||
constexpr char sink_repository::stderr_id[];
|
||||
|
||||
} // namespace srslog
|
||||
|
||||
#endif // SRSLOG_SINK_REPOSITORY_H
|
@ -1,112 +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 "src/srslog/formatter.h"
|
||||
#include "testing_helpers.h"
|
||||
#include <numeric>
|
||||
|
||||
using namespace srslog;
|
||||
|
||||
/// Helper to build a log entry.
|
||||
static detail::log_entry build_log_entry()
|
||||
{
|
||||
// Create a time point 50000us from epoch.
|
||||
using tp_ty = std::chrono::time_point<std::chrono::high_resolution_clock>;
|
||||
tp_ty tp(std::chrono::microseconds(50000));
|
||||
|
||||
fmt::dynamic_format_arg_store<fmt::printf_context> store;
|
||||
store.push_back(88);
|
||||
|
||||
return {nullptr, tp, {10, true}, "Text %d", std::move(store), "ABC", 'Z'};
|
||||
}
|
||||
|
||||
static bool when_fully_filled_log_entry_then_result_everything_is_formatted()
|
||||
{
|
||||
std::string result = format_log_entry_to_text(build_log_entry());
|
||||
std::string expected = "00:00:00.050000 [ABC ] [Z] [ 10] Text 88\n";
|
||||
|
||||
ASSERT_EQ(result, expected);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool when_log_entry_without_name_is_passed_then_name_is_not_formatted()
|
||||
{
|
||||
auto entry = build_log_entry();
|
||||
entry.log_name = "";
|
||||
|
||||
std::string result = format_log_entry_to_text(std::move(entry));
|
||||
std::string expected = "00:00:00.050000 [Z] [ 10] Text 88\n";
|
||||
|
||||
ASSERT_EQ(result, expected);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool when_log_entry_without_tag_is_passed_then_tag_is_not_formatted()
|
||||
{
|
||||
auto entry = build_log_entry();
|
||||
entry.log_tag = '\0';
|
||||
|
||||
std::string result = format_log_entry_to_text(std::move(entry));
|
||||
std::string expected = "00:00:00.050000 [ABC ] [ 10] Text 88\n";
|
||||
|
||||
ASSERT_EQ(result, expected);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
when_log_entry_without_context_is_passed_then_context_is_not_formatted()
|
||||
{
|
||||
auto entry = build_log_entry();
|
||||
entry.context.enabled = false;
|
||||
|
||||
std::string result = format_log_entry_to_text(std::move(entry));
|
||||
std::string expected = "00:00:00.050000 [ABC ] [Z] Text 88\n";
|
||||
|
||||
ASSERT_EQ(result, expected);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool when_log_entry_with_hex_dump_is_passed_then_hex_dump_is_formatted()
|
||||
{
|
||||
auto entry = build_log_entry();
|
||||
entry.hex_dump.resize(20);
|
||||
std::iota(entry.hex_dump.begin(), entry.hex_dump.end(), 0);
|
||||
|
||||
std::string result = format_log_entry_to_text(std::move(entry));
|
||||
std::string expected =
|
||||
"00:00:00.050000 [ABC ] [Z] [ 10] Text 88\n"
|
||||
" 0000: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"
|
||||
" 0010: 10 11 12 13\n";
|
||||
|
||||
ASSERT_EQ(result, expected);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
TEST_FUNCTION(
|
||||
when_fully_filled_log_entry_then_result_everything_is_formatted);
|
||||
TEST_FUNCTION(
|
||||
when_log_entry_without_name_is_passed_then_name_is_not_formatted);
|
||||
TEST_FUNCTION(when_log_entry_without_tag_is_passed_then_tag_is_not_formatted);
|
||||
TEST_FUNCTION(
|
||||
when_log_entry_without_context_is_passed_then_context_is_not_formatted);
|
||||
TEST_FUNCTION(
|
||||
when_log_entry_with_hex_dump_is_passed_then_hex_dump_is_formatted);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue