Flow 1.0.2
Flow project: Public API.
|
Simple data store containing all of the information generated at every logging call site by flow::log, except the message itself, which is passed to Logger::do_log() assuming Logger::should_log() had returned true
.
More...
#include <log.hpp>
Public Attributes | |
Component | m_msg_component |
Component of message, as of this writing coming from either Log_context constructor or FLOW_LOG_SET_CONTEXT(). | |
Sev | m_msg_sev |
Severity of message, typically determined by choice of macro (e.g., FLOW_LOG_WARNING() vs. More... | |
util::String_view | m_msg_src_file |
Pointer/length into static-storage string that would have come from built-in __FILE__ macro which is auto-invoked by all FLOW_LOG_*() logging call sites. More... | |
unsigned int | m_msg_src_line |
Copy of integer that would have come from built-in __LINE__ macro which is auto-invoked by all FLOW_LOG_*() logging call sites. | |
util::String_view | m_msg_src_function |
Analogous to m_msg_src_file but coming from __FUNCTION__ , not __FILE__ . See m_msg_src_file perf notes. | |
std::chrono::system_clock::time_point | m_called_when |
Time stamp from as close as possible to entry into the log call site (usually FLOW_LOG_WARNING() or similar). More... | |
std::string | m_call_thread_nickname |
Thread nickname, as for Logger::this_thread_set_logged_nickname(), of the thread from which the log call was invoked; or an empty string if the thread had no such nickname set at the time. More... | |
util::Thread_id | m_call_thread_id |
Thread ID of the thread from which the log call was invoked; or a default-constructed (no-thread) such thread ID if the thread has a nickname, meaning !m_call_thread_nickname.empty() . More... | |
Simple data store containing all of the information generated at every logging call site by flow::log, except the message itself, which is passed to Logger::do_log() assuming Logger::should_log() had returned true
.
User only need to worry about this when dealing with the internals of a Logger implementation. Copying is to be avoided, as there are some non-trivial data stored here; though it is not too bad.
deep_copy(const Msg_metadata&)
remains accurate.util::Thread_id flow::log::Msg_metadata::m_call_thread_id |
Thread ID of the thread from which the log call was invoked; or a default-constructed (no-thread) such thread ID if the thread has a nickname, meaning !m_call_thread_nickname.empty()
.
The working assumption is that (1) both members are met for direct log output only and no other logic; and (2) the nickname is preferable when set, the thread ID being the fallback. (If this sounds meh, consider that it's entirely reasonable to make the nickname contain some nice info and the original thread ID as well in string form. However, mind the length – the Performance Note in m_call_thread_nickname doc header.)
std::string flow::log::Msg_metadata::m_call_thread_nickname |
Thread nickname, as for Logger::this_thread_set_logged_nickname(), of the thread from which the log call was invoked; or an empty string if the thread had no such nickname set at the time.
Setting this involves an std::string
copy; the cost of this is worth considering given that this is done for every single log call site, if the nickname is indeed set. See performance note in doc header of Logger::this_thread_set_logged_nickname() for the recommendation and details. (Long story short, if you keep it at N char
s or fewer, the cost of a non-empty m_call_thread_nickname becomes equal to that of an empty one. N might be 15 in gcc 5.)
std::chrono::system_clock::time_point flow::log::Msg_metadata::m_called_when |
Time stamp from as close as possible to entry into the log call site (usually FLOW_LOG_WARNING()
or similar).
std::chrono
is used instead of boost.chrono for certain internal output reasons in Ostream_log_msg_writer.
Sev flow::log::Msg_metadata::m_msg_sev |
Severity of message, typically determined by choice of macro (e.g., FLOW_LOG_WARNING() vs.
FLOW_LOG_INFO()) at the call site; though it can also be supplied manually via FLOW_LOG_WITH[OUT]_CHECKING()
macro arg.
util::String_view flow::log::Msg_metadata::m_msg_src_file |
Pointer/length into static-storage string that would have come from built-in __FILE__
macro which is auto-invoked by all FLOW_LOG_*()
logging call sites.
Formally this should be the pointer/length representing the substring of __FILE__
that you wish to be logged in its entirely, no more and no less. For example the pointer might be to the first character, the lengh equal to strlen()
; or more practically it might be one past the right-most dir separator character (and the length decremented accordingly).
To be explicit: The underlying memory must never be deallocated, in that it should never have been allocated on the heap but in static storage.
We store a util::String_view, not a const char*
, which means not only a pointer but a length is stored here internally. That's fine (we discuss trade-offs just below); it should barely affect the perf of copying Msg_metadata. However the length must be initialized. To initialize it in the most optimized way, recognize that it will come from __FILE__
which is really a string literal substituted by preprocessor; therefore the length can be obtained at compile time via sizeof()
. Hence use the 2-arg String_view
ctor which takes the pointer and the length instead of figuring the latter out via strlen()
which is linear-time. Update: The util::String_view in use as of this writing declares the 1-arg ctor as constexpr
which indicates it might be able to do the strlen()
(or equivalent) at compile-time. Nevertheless, this feels (and I say this with some related experience) like something that may or may not actually be implemented by a given compiler. So it's probably safer (in terms of portability) to still follow the 2-arg ctor advice above.
If it is desired (as suggested in an example above) to represent a mere substring of that, then as long as the computation of the appropriate first character past index 0 satisfies constexpr
requirements (meaning, it will be computed at compile time, not runtime) – as does the according decrement of the length – then you're still fine. If it is done at runtime, then that's a hit to perf, so avoid it if at all possible.
If indeed you do want ultimately to output a substring of __FILE__
, then in order to guarantee or at least increase the chance of compile-time computation of that substring you should in fact do it as early as possible at the log call site as opposed to later/nearer the time of final output to device/whatever by Logger. In other words in that case do try to set this value to the substring from the start; don't leave it to the Logger.
const char*
instead?(This is arguably very nitpicky anyway, but these objects are generated and passed around at every single log call site, so we should try to save every little bit.) Let's stipulate that the cost of storing (RAM; and copying) the length is negligible. The next concern is initializing the length; the above shows that's free in practice. Finally, when output to the final device/whatever occurs within Logger impl, there are two possibilities of how it might realistically act. One, it might search for the NUL char anyway – in which case we've changed nothing perf-wise – as it copies for output purposes. Two, it might require the length of the string and hence use String_view::size()
and then perform the copy; in that case we have saved a linear search. (For example, if the Logger is printing to an ostream
, then there exists an operator<<(ostream, String_view)
that'd be automatically used and would of course use the saved length properly.) So, it's a win or at worst a tie.