Skip to content
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

Add support for customizing the prefix format #554

Merged
merged 1 commit into from
Apr 9, 2021

Conversation

santigl
Copy link
Contributor

@santigl santigl commented May 14, 2020

This PR proposes a way of adding support to customize the prefix format used by glog.

With it users can declare a callback (PrefixAttacherFunction(std::ostream&, const LogMessageInfo&)) that will receive the relevant log details for the line and a stream to write a corresponding prefix.

That callback is enabled by passing it to a new overloaded InitGoogleLogging(). (The callback cannot be changed once the instance is initialized.)

If no callback is specified, LogMessage will follow the same path as it does now and write the current hardcoded format.

For an example use case, see the unit tests in src/logging_custom_prefix_unittest.cc.

@santigl
Copy link
Contributor Author

santigl commented May 15, 2020

This currently fails the CI step that builds with C++98, which does not provide std::function. The changes in this PR could be made conditional on the value of CXX_STANDARD, only providing the new functionality for C++11 and later.

@RippeR37
Copy link

@santigl great work, I really wanted that functionality as well.

For the whole C++11 thing - why not just use a function pointer instead of std::function<>? Since this is a global state you don't really need any stateful callback here and wouldn't it be noticably faster? And it would be C++98 compatible as well.

Also, why using std::string for log-specific data like severity (instead of enum/index), filename (instead of const char*)? There can be a noticeable performance penalty because of this.

@santigl
Copy link
Contributor Author

santigl commented Aug 19, 2020

Thanks for your input, @RippeR37!

An std::function gives more flexibility, For example, if you are implementing a wrapper around glog for a logging facility in a library, you could easily customize the callable with information that you gathered at runtime right before calling InitGoogleLogging().

Having said that, I have not done any performance testing (I was hoping to get reviews on the overall idea first). But, if benchmarks show that it's faster, I'm happy to add support/make it a raw pointer across all implementations.

+1 on the const char pointers. Since that is how they are stored internally, that will reduce the overhead. And the reason why I didn't add the enum value for the severity is that I felt that it was exposing an implementation detail from glog's internals.

@RippeR37
Copy link

RippeR37 commented Aug 19, 2020

An std::function gives more flexibility, For example, if you are implementing a wrapper around glog for a logging facility in a library, you could easily customize the callable with information that you gathered at runtime right before calling InitGoogleLogging().

Yes, but as far as I know, glog is "static"/global anyway (i.e. you can't have two instances at the same tme) so you can do the same by having global state and a free function which reads that state (instead of using std::function<>) and - as a bonus - not depend on C++11 in any way (which would also be nice for pre-C++11 users of this library).

Having said that, I have not done any performance testing (I was hoping to get reviews on the overall idea first). But, if benchmarks show that it's faster, I'm happy to add support/make it a raw pointer across all implementations.

I did a quick benchmark of overhead of calling function via std::function versus function pointer. In the field it might be bigger or smaller difference (and might depend on compiler/stdlib/switches/...) but in some cases I've seen a difference of function pointers being up to 7x faster then std::function.

https://quick-bench.com/q/5VlPI3I0QPW3-RT_Ywvc8g3ZT_E

+1 on the const char pointers. Since that is how they are stored internally, that will reduce the overhead. And the reason why I didn't add the enum value for the severity is that I felt that it was exposing an implementation detail from glog's internals.

IMHO it would still be better to not waste cpu cycles on enum=>string conversion. Exposing level as an int (0=INFO, 1=WARNING, 2=ERROR, 3=FATAL, verbose(N)=-N) or enum (+ something for verbose levels, e.g. old plain enum with predefined values only for named levels but also allowing for unnamed levels like verbose ones?) would be much better, especially for systems which can log hundreds of MBs or even GBs of data. It would be very bad to lose performance due to using this functionality.

@santigl
Copy link
Contributor Author

santigl commented Aug 21, 2020

That is a quite a big difference, I'll be happy to change the callback parameter to a pointer.

For the log levels strings, glog already has an array with the human-readable representations. If we pass a pointer to them there wouldn't be an additional cost, since glog currently indexes into that array to generate the prefix.

src/glog/logging.h.in Outdated Show resolved Hide resolved
@RippeR37
Copy link

Thanks for the change! Now it looks like it shouldn't have a noticeable performance regression and does introduce much better flexibility for the users. 👍

@santigl
Copy link
Contributor Author

santigl commented Aug 22, 2020

Thanks for the feedback, @RippeR37!

@ukai
Copy link
Contributor

ukai commented Sep 14, 2020

I'm not convinced to have a feature to change logging format.
better to file issue first to explain the needs?

@santigl
Copy link
Contributor Author

santigl commented Sep 14, 2020

Ok, @ukai. I opened #578.

@cheshirekow
Copy link

Personally, I would like to see a customizable log message format. Logging frameworks that I use in other languages can be customized. For an organization that creates software in multiple languages, it can be hugely beneficial (and perhaps a requirement) that messages are logged in a consistent way regardless of which language that software is written in.

@sergiud sergiud requested a review from ukai October 5, 2020 11:33
@edbaunton
Copy link
Contributor

@ukai There are many other logging libraries available in C++, all of which have the functionality to customise logging. This is a sorely missing feature of glog.

Allowing the user to customise the format would make for a really portable, performant and feature rich logging library. What is the downside that concerns you with this feature?

@sergiud sergiud linked an issue Mar 31, 2021 that may be closed by this pull request
@sergiud
Copy link
Collaborator

sergiud commented Mar 31, 2021

@ukai Unless you are strongly opposed to this feature, I will go forward and merge it once it's ready.

@santigl It would be nice to have an example how to setup a custom prefix, preferably somewhere in README.rst.

CMakeLists.txt Outdated Show resolved Hide resolved
src/glog/logging.h.in Outdated Show resolved Hide resolved
src/logging.cc Outdated Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
src/logging.cc Outdated Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
@santigl
Copy link
Contributor Author

santigl commented Mar 31, 2021

That'd be great! Thank you, @sergiud.

I will address those comments and document the feature in the README.

src/glog/logging.h.in Outdated Show resolved Hide resolved
README.rst Outdated Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
CMakeLists.txt Outdated Show resolved Hide resolved
@sergiud sergiud self-assigned this Apr 4, 2021
@sergiud sergiud added this to the 0.5 milestone Apr 4, 2021
@sergiud sergiud requested a review from drigz April 4, 2021 01:46
@sergiud sergiud force-pushed the santigl/custom-prefixer branch 2 times, most recently from 9a27b4e to 078d5c5 Compare April 6, 2021 18:30
@Arfrever
Copy link

Arfrever commented Apr 6, 2021

If I read this correctly, even with -DWITH_CUSTOM_PREFIX=ON, behavior is not changed by default, when new variant of InitGoogleLogging function is not used, so I wonder why this feature is disabled by default or why there is even cmake option for this feature...

@sergiud
Copy link
Collaborator

sergiud commented Apr 6, 2021

Since there are some reservations regarding this feature e.g. from @ukai, the compromise is to declare it experimental and allow future (potentially breaking) changes based on user comments. Meanwhile, users (and package maintainers) still have the ability to enable the option at anytime. Hence, I don't see any issue here.

@sergiud sergiud merged commit 7d4eeb1 into google:master Apr 9, 2021
@sergiud sergiud mentioned this pull request May 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
9 participants