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
log: Use the coarse real time clock in log timestamps #18141
Conversation
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.
Yay! This looks good.
I don't suppose there's a way to annotate the time_point so that we know whether it's coarse or not? Then we could output only 3 decimal places of precision for coarse stamps and 6 for fine...
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.
i failed to find a caller of _get_val<>().
@@ -162,6 +162,7 @@ struct md_config_t { | |||
int _get_val(const std::string &key, char **buf, int len) const; | |||
Option::value_t get_val_generic(const std::string &key) const; | |||
template<typename T> T get_val(const std::string &key) const; | |||
template<typename T> T _get_val(const std::string &key) const; |
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.
do we have a caller of this function now?
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.
+ if (changed.find("log_coarse_timestamps") != changed.end()) { + log->set_coarse_timestamps(conf->_get_val("log_coarse_timestamps")); + }
src/common/config.h
Outdated
template<typename T> T md_config_t::_get_val(const std::string &key) const { | ||
Option::value_t generic_val = this->get_val_generic(key); | ||
get_typed_value_visitor<T> gtv; | ||
return boost::apply_visitor(gtv, generic_val); |
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.
it's identical to
template<typename T> T md_config_t::get_val(const std::string &key) const
why shall we use it instead of md_config_t::get_val()
?
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.
Thanks for catching this. It was SUPPOSED to _get_val() instead of get_value_generic since _get_val desn't take a lock. I'll push an update in a moment.
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.
@adamemerson it's not changed. am i missing something?
scratch that.
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.
no need to introduce _get_val()
.
We create a new time type to support using coarse timestamps (for performance) by default while still allowing the user to switch to fine timestamps. Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
The tests should, really, get their time from the same source as the log, and also probably use the same interface to creating entries that other people do. So add an optional message argument and have the tests use that rather than using the new operator directly. Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
3609ac4
to
1c00492
Compare
@liewegas Times are marked as coarse or fine and print three or six digits depending. |
When notified by a config observer, the config lock is already held, create a _get_val template to manipulate newstyle options when notified. Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
And set up an observer in CephContext to coarsen/refine time stamps as requested. Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
Have each timestamp know whether it's coarse or fine. Print six figures for fine stamps and three for coarse. Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
1c00492
to
afaf48a
Compare
template<typename T> T md_config_t::_get_val(const std::string &key) const { | ||
Option::value_t generic_val = this->_get_val(key); | ||
get_typed_value_visitor<T> gtv; | ||
return boost::apply_visitor(gtv, generic_val); |
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.
@jcsp @adamemerson why don't we just use boost::get<>
?
// An alternative might be to pass a std::unique_lock to | ||
// handle_conf_change and have a version of get_var that can take it | ||
// by reference and lock as appropriate. | ||
Mutex::Locker l(lock); |
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.
I am late reviewing this, but this looks scary. Holding md_config_t::lock while calling into handle_conf_change of observers: then the observers can't use get_val (it takes the lock) to react to the changes!
The comment in config.h is referring to the old struct-based config, where holding the lock would be a good thing because it would render it safe to read that struct, rather than in the get_val world where holding the lock is a recipe for deadlocks
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.
I did look through the rest of the file as a sanity check. It seems that we acquire the lock in apply_changes before calling _apply_changes which calls handle_conf_change.
So we had observers being called with the lock held in one path and without the lock held in the other path. I wouldn't be against swinging the change in the other direction and releasing the lock before calling the observers from _apply_changes if you think that would be safer.
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.
We need the lock to cover the handle_conf_change methods until all of the strings are gone from legacy_config_opts.h. Since injectargs etc already hold the lock this change seems correct.
The larger/more annoying issue is that the get_val() calls in handle_conf_change. Maybe we can fix those just by marking the mutex recursive?
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.
That was why I added the _get_val template. A recursive mutex would work, too, as would passing a unique_lock reference into handle_conf_change that can be passed to get_val which can just look to see whether to acquire it or not.
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.
The unique_lock approach seems fragile: we'd have to update all current implementations that use get_val(), and going forward developers have to remember that all future calls to get_val() have to pass the unique_lock ref along to a get_val() variant that takes it. And if they don't they'll only notice if they test changing the config option online and deadlock the config update thread.
My vote is recursive mutex, with a plan to remove it if/when legacy_config_opts ever gets emptied out...
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.
Huh. Looks like it already is recursive. I didn't realize that when I was worried about deadlock before. In that case all we really need to do is back out my _get_val change and just call get_val as normal.
With an option to use the higher resolution clock if we want to.
This address a Trello Card or whatever.