-
Notifications
You must be signed in to change notification settings - Fork 70
/
logging.cpp
144 lines (116 loc) · 4.23 KB
/
logging.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/* Copyright (C) 2010-2023 by Arm Limited. All rights reserved. */
#include "Logging.h"
#include "lib/Assert.h"
#include "lib/Time.h"
#include "logging/configuration.h"
#include "logging/global_log.h"
#include <atomic>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <memory>
#include <google/protobuf/stubs/logging.h>
#include <sys/syscall.h>
#include <unistd.h>
namespace logging {
namespace {
std::shared_ptr<logger_t> current_logger {};
void protobuf_log_handler(google::protobuf::LogLevel level,
const char * filename,
int line,
const std::string & message)
{
auto remapped_level = log_level_t::info;
switch (level) {
case google::protobuf::LOGLEVEL_WARNING:
remapped_level = log_level_t::warning;
break;
case google::protobuf::LOGLEVEL_ERROR:
remapped_level = log_level_t::error;
break;
case google::protobuf::LOGLEVEL_FATAL:
remapped_level = log_level_t::fatal;
break; //
default:
break;
}
log_item(remapped_level, {filename, static_cast<unsigned>(line)}, message);
}
}
namespace detail {
bool enabled_log_trace = false;
//NOLINTNEXTLINE(cert-dcl50-cpp)
void do_log_item(log_level_t level, source_loc_t const & location, const char * format, ...)
{
// format the string
va_list varargs;
va_start(varargs, format);
char * buffer_ptr = nullptr;
auto n = vasprintf(&buffer_ptr, format, varargs);
va_end(varargs);
if (n < 0) {
return;
}
// make sure it is safely freed
//NOLINTNEXTLINE(modernize-avoid-c-arrays)
std::unique_ptr<char[], void (*)(void *)> buffer {buffer_ptr, std::free};
// write it out
log_item(level, location, std::string_view(buffer.get(), n));
}
void do_log_item(log_level_t level, source_loc_t const & location, std::string_view msg)
{
// write it out
log_item(level, location, msg);
}
void do_log_item(pid_t tid, log_level_t level, source_loc_t const & location, std::string_view msg)
{
// write it out
log_item(thread_id_t(tid), level, location, msg);
}
}
void log_item(log_level_t level, source_loc_t const & location, std::string_view message)
{
std::shared_ptr<logger_t> sink = current_logger;
if (sink != nullptr) {
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
sink->log_item(thread_id_t(syscall(SYS_gettid)), level, {t.tv_sec, t.tv_nsec}, location, message);
}
}
void log_item(thread_id_t tid, log_level_t level, source_loc_t const & location, std::string_view message)
{
std::shared_ptr<logger_t> sink = current_logger;
if (sink != nullptr) {
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
sink->log_item(tid, level, {t.tv_sec, t.tv_nsec}, location, message);
}
}
void log_item(thread_id_t tid,
log_level_t level,
log_timestamp_t timestamp,
source_loc_t const & location,
std::string_view message)
{
std::shared_ptr<logger_t> sink = current_logger;
if (sink != nullptr) {
sink->log_item(tid, level, timestamp, location, message);
}
}
void set_logger(std::shared_ptr<logger_t> sink)
{
current_logger = std::move(sink);
google::protobuf::SetLogHandler(current_logger ? protobuf_log_handler : nullptr);
}
/** @return true if trace logging is enabled */
bool is_log_enable_trace() noexcept
{
return detail::enabled_log_trace;
}
/** Enable trace logging (which also enables debug) */
void set_log_enable_trace(bool enabled) noexcept
{
detail::enabled_log_trace = enabled;
}
}