-
Notifications
You must be signed in to change notification settings - Fork 440
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] C++ Example Logging Statements #356
Comments
The main thing that stands out is that structured logging should cover semi-structured data, i.e. JSON/XML/YAML type structures that contain lists, maps, and sub-structures. For example things like https://github.com/nlohmann/json may be represented:
but this could likewise be an XML or YAML document. I don't think references need to be taken into account, but something like the XML infoset or a JsonGenerator builder may be helpful. https://docs.oracle.com/javaee/7/api/javax/json/stream/JsonGenerator.html When you talk about formats, are you talking about things like logfmt https://www.brandur.org/logfmt? There are frameworks that render the same logging statements to different outputs, so the same logging event gets rendered as logfmt on console, but written as JSON on the backend. |
Thoughts:
// lp - LoggerProvider
auto logger = lp.GetLogger(loggerName); // with optional 2nd logger parameters
Event event = { {"uint32Key", (uint32_t)123456}, {"uint64Key", (uint64_t)123456}, {"strKey", "someValue"} };
logger->LogEvent(event); With overloads, like: logger->LogEvent(name); // simple event by name and logger->LogEvent(name, event); // name and event property list and logger->LogEvent(T); // templated method, where T - is anything. Could be `nlohmann::json` object. User provides conversion While passing objects across the ABI boundary - we use collection of AttributeValue and KeyValueIterable, which we use for I believe we need to move the I would also suggest to add higher-order primitives, in addition to foundation types supported by OTEL protocol. This is example of what may come in handy, in addition to basic types covered by
For the unstructured logging, I believe we have to make sure we support C-style debug macros that can be turned off at compile time.. The usual suspects, like: #define LOG_DEBUG(fmt_, ...) MY_LOG_(MyLog::Debug, getMyLogComponent(), fmt_, ##__VA_ARGS__)
#endif
#define LOG_TRACE(fmt_, ...) MY_LOG_(MyLog::Trace, getMyLogComponent(), fmt_, ##__VA_ARGS__)
#define LOG_INFO(fmt_, ...) MY_LOG_(MyLog::Info, getMyLogComponent(), fmt_, ##__VA_ARGS__)
#define LOG_WARN(fmt_, ...) MY_LOG_(MyLog::Warning, getMyLogComponent(), fmt_, ##__VA_ARGS__)
#define LOG_ERROR(fmt_, ...) MY_LOG_(MyLog::Error, getMyLogComponent(), fmt_, ##__VA_ARGS__) With no strong preference how we name them.
And possibly with:
levels too. |
Would log initialization/configuration also be part of logging API instead of log statement, or we are going to put the into different RFC? For the thoughts from @maxgolov , I suggest that the API doesn't depend on any other library like Also I think we want to avoid referencing any STL types in our API, as @maxgolov mentioned, they are not ABI compliant. And add implicit cast of STL types to If we wrap all the APIs into log class, are they going to be virtual functions and allowed to be overloaded by user code? |
The other thing that stands out (but may be optional) is the use of markers. For example, a logging statement may have
and be given a specialized HTTP header without changing the body of the The concept was added by Logback to indicate when additional filtering / alerting needs to take place "out of band" of the logging event data, but it's useful as a general purpose escape hatch. For example, you can associate markers with audio clips or build up context through a series of markers. |
@ThomsonTan - yeah, just to clarify - I'm not actually saying we should support JSON in API. I'm saying we can have a template method and a higher-level abstraction that transforms the JSON into "property list of variants" ( |
I think we need to have something like |
Re. I think we need to have |
I support the idea of having logging methods as below.
Also, if we can support
Of-course, this may need backporting std::format from C++20, or else using fmtlib.
I like the concept of log4j having one logger associated with multiple destination, each destination accepting data of certain importance level, different from that associated with logger. |
Closing as this was design discussion. |
This RFC aims to collect a variety of use cases of logging statements, that will be used to establish the convention and design of the C++ Logging API/SDK in #337.
The goal is to obtain a collection of observability-specific logging statements that:
Example Submission
Simple structured logging of a map:
Write the map to the logger, along with the severity and message:
This code snippet creates a log with a map attached to it. This is a type of structured logging, since the data holds a relationship with itself through key/value pairs. If this log were converted to JSON, it may have the following structure:
Request for Comments
Please comment below to add examples of log formats and the different ways logging can be performed in C++, with the relevant data definitions (if applicable).
cc: @MarkSeufert @alolita @reyang @maxgolov @ThomsonTan
The text was updated successfully, but these errors were encountered: