-
Notifications
You must be signed in to change notification settings - Fork 438
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
Fix GlobalLogHandler singleton creation order #1767
Fix GlobalLogHandler singleton creation order #1767
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## main #1767 +/- ##
==========================================
- Coverage 85.79% 85.74% -0.05%
==========================================
Files 171 171
Lines 5212 5214 +2
==========================================
- Hits 4471 4470 -1
- Misses 741 744 +3
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks ok to me.
Please also fix this comment:
/**
* We can not decide the destroying order of signaltons.
* Which means, the destructors of other singletons (GlobalLogHandler,TracerProvider and etc.)
* may be called after destroying of global LogHandler and use OTEL_INTERNAL_LOG_* in it.We can do
* nothing but ignore the log in this situation.
*/
#define OTEL_INTERNAL_LOG_DISPATCH(level, message, attributes) \
Good point, have rephrased the comment now. |
@@ -26,6 +27,7 @@ LoggerProvider::LoggerProvider(std::unique_ptr<LogRecordProcessor> &&processor, | |||
std::vector<std::unique_ptr<LogRecordProcessor>> processors; | |||
processors.emplace_back(std::move(processor)); | |||
context_ = std::make_shared<sdk::logs::LoggerContext>(std::move(processors), std::move(resource)); | |||
OTEL_INTERNAL_LOG_DEBUG("[LoggerProvider] LoggerProvider created."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about other ctors? Didn't add the log there because they are not used by lazy singleton pattern? Probably add the log for consistency as the log message is provider instance created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean to enhance our debug logging in general by adding logs in all the constructors? That's good feedback, will create a separate issue for it, as it is not directly related to this fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about other ctors? Didn't add the log there because they are not used by lazy singleton pattern? Probably add the log for consistency as the log message is provider instance created.
The per signal singletons are the entry points to the SDK. No other code in the SDK can be executed before building these per signal singletons.
So, by definition, once these singletons are executed, it is guaranteed that every other class used in the SDK implementation will see an already initialized global log handler.
There is not need, to fix this bug, to add log statements in every classes, even if another class uses a lazy singleton pattern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for the investigation and fix.
@@ -26,6 +27,7 @@ LoggerProvider::LoggerProvider(std::unique_ptr<LogRecordProcessor> &&processor, | |||
std::vector<std::unique_ptr<LogRecordProcessor>> processors; | |||
processors.emplace_back(std::move(processor)); | |||
context_ = std::make_shared<sdk::logs::LoggerContext>(std::move(processors), std::move(resource)); | |||
OTEL_INTERNAL_LOG_DEBUG("[LoggerProvider] LoggerProvider created."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about other ctors? Didn't add the log there because they are not used by lazy singleton pattern? Probably add the log for consistency as the log message is provider instance created.
The per signal singletons are the entry points to the SDK. No other code in the SDK can be executed before building these per signal singletons.
So, by definition, once these singletons are executed, it is guaranteed that every other class used in the SDK implementation will see an already initialized global log handler.
There is not need, to fix this bug, to add log statements in every classes, even if another class uses a lazy singleton pattern.
Thanks @lalitb for the fix! |
Fixes #1718
Changes
GlobalLogHandler
andMeterProvider
are lazy singletons. As of now,MeterProvider
singleton is first initialized, followed byGlobalLogHandler
(when the first message is logged). This order of initialization meansGlobalLogHandler
is destroyed beforeMeterProvider
, which further results in segfault when trying to use the logger from MeterProvider destructor.The easy solution would be to use
GlobalLogHandler
to log message from inside theMeterProvider
constructor. This makes the complier to guarantee that the GlobalLogHandler is constructed before MeterProvider, and so destroyed after MeterProvider. Have tested the changes locally by reproducing the segfault, and then ensuring there is no segfault with the change.To demonstrate the order of initialization, refer to the sample code here - https://godbolt.org/z/K8x1dcPW5
The order of initiation and destruction in sample is:
And order of initialization and destruction after replacing line 32 with
std::cout << "MeterProvider\n"
in the sample code is:Please provide a brief description of the changes here.
For significant contributions please make sure you have completed the following items:
CHANGELOG.md
updated for non-trivial changes