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
rgw: add abstraction for ops log destination and add file logger #43329
rgw: add abstraction for ops log destination and add file logger #43329
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.
I think this is cogently written. My main questions are about buffering options on the output file. Am I missing where that is handled?
| @@ -589,10 +588,17 @@ namespace rgw { | |||
|
|
|||
| // XXX ex-RGWRESTMgr_lib, mgr->set_logging(true) | |||
|
|
|||
| OpsLogManifold* olog_manifold = new OpsLogManifold(); | |||
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.
ok, I think this is a sane design
src/rgw/rgw_log.cc
Outdated
|
|
||
| bl.append(s); | ||
| void OpsLogManifold::add_sink(OpsLogSink *sink) |
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.
for consistency and Stroustrupness, "OpsLogSink* sink"
src/rgw/rgw_log.cc
Outdated
| int OpsLogFile::log_json(struct req_state* s, bufferlist& bl) | ||
| { | ||
| lock.lock(); | ||
| bl.write_stream(file); |
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.
when we do this, is the buffer being written out synchronously?
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 socket version allows for a configurable amount of data to be in the socket buffer before being flushed--this is important for performance
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.
@mattbenjamin Yeah that was a question that I intended to ask. For our use case, we don't want to lose these ops logs in the case of a process crash, so we prefer that they be written out synchronously. I can imagine that this might be less important for other users and that it might be desirable to have a knob to turn in order to control whether (and how much) buffering is used. Since you're confirming that this is important, I'll go ahead and work on that piece and update the PR.
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.
these synchronous writes are unfortunately in conflict with the async refactoring project, where we're trying to eliminate all blocking waits from frontend threads. beast frontend requests run as coroutines, so when we can suspend that coroutine instead of blocking, that allows the thread to process other requests in the meantime
i'd eventually like to see this use something like libaio to make the file writes asynchronous
| int log(struct req_state* s, struct rgw_log_entry& entry) override; | ||
| }; | ||
|
|
||
| class JsonOpsLogSink : public OpsLogSink { |
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.
ok, that's expected
| ceph::Formatter *formatter; | ||
| ceph::mutex lock = ceph::make_mutex("OpsLogSocket"); | ||
| ceph::mutex lock = ceph::make_mutex("JsonOpsLogSink"); |
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 guess this is too...
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 guess this may be where writing to the unix socket and attaching something to consume it and relay it to a file may have some advantage, but, it's still a valid choice
| @@ -518,12 +518,16 @@ int radosgw_Main(int argc, const char **argv) | |||
|
|
|||
| rgw::dmclock::SchedulerCtx sched_ctx{cct.get()}; | |||
|
|
|||
| OpsLogSocket *olog = NULL; | |||
|
|
|||
| OpsLogManifold *olog = new OpsLogManifold(); | |||
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.
OpsLogManifold seems like a verbose, but valid name :)
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.
Seems fine to me, once the buffering bits get in.
cd07218
to
8e07cf1
Compare
| OpsLogSocket::~OpsLogSocket() | ||
| void OpsLogFile::flush() | ||
| { | ||
| std::scoped_lock flush_lock(flush_mutex); |
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.
can the log buffer append while the flush buffer is flushed?
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 think iow that maybe you could get that behavior by introducing a flag and dropping this mutex during flush (apologies if I'm missing something)
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 log_mutex is only held while swapping log_buffer and flush_buffer, so request threads can continue to append to the log buffer while the flush_buffer is actually being written out to disk. There should be minimal contention here between the loggers and the flusher. Let me know if I'm missing something, though! :)
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.
ok, i see; this is basically fine, I think.
Adds an OpsLogSink abstraction for ops log destinations. Also implements this abstraction for a file logger since it's easier to use files vs. sockets with containers. Fixes: https://tracker.ceph.com/issues/48752 Signed-off-by: Cory Snyder <csnyder@iland.com>
8e07cf1
to
c4c9f39
Compare
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.
can you set up an rgw suite run in teuthology?
| OpsLogSocket::~OpsLogSocket() | ||
| void OpsLogFile::flush() | ||
| { | ||
| std::scoped_lock flush_lock(flush_mutex); |
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.
ok, i see; this is basically fine, I think.
@mattbenjamin I haven't run teuthology suites myself yet. Any references or pointers on how to go about that? |
|
hi @cfsnyder well, you need sepia (ceph test lab creds), and then you push your branch to ceph-ci.git, and then you request a teuthology run. There's detail here: |
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.
approving, setting needs-qa
Thanks @mattbenjamin, I'll look into getting access to Sepia and figuring out how to do this for myself in the future. So far I've just been adding the needs-qa flag and letting Yuri handle that testing. |
|
Anything that I can do to get this included in a QA run so that it can be back-ported in time for the next Pacific release @mattbenjamin ? |
I'll try to send one today Matt |
|
Ok, so I've re-reviewed this in view of @cbodley's comment regarding the in-progress async/non-blocking request processing refactor that we expect to land immanently in 2022. I do want the functionality that this PR offers, and I don't want to be anything less than welcoming of good and new work. But I think Casey has a point here, in that even the top-half/request threads are at least infrequently doing blocking operations and waiting for bottom-half flush operations to finalize. I would like to ask: is there a way we could potentially revise the i/o strategy to be explicitly non-blocking in the request path? I think ordinary non-blocking i/o, but also libaio or similar as Casey noted, would be sound ways to approach this. @cfsnyder is that something you could consider helping with? |
|
@cbodley maybe the semantics of the existing ops-log path need some review discussion as well; iirc, the ops log socket is potentially lossy, if the receiver is unable to keep its queue under its max size. Maybe we could discuss all this more in the refactoring meeting? I think you've come to those, @cfsnyder? |
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.
per casey's feedback
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.
per discussion in refactoring call, restoring approval
|
@cfsnyder wip-opslog-48752 created in ceph-ci; will start an rgw suite run when it's built |
|
@mattbenjamin I'm guessing the QA failures are unrelated to these changes but let me know if you think otherwise? |
|
@cfsnyder I don't think any of the failures here are due to the ops-log change. |
|
ok, this passed; merging; opening a tracker issue for the new list-buckets failure on cleanup |
|
Clang/FreeBSD is not happy with this one: Trying to fix, but keep running in all kinds of variations for this |
|
thanks @wjwithagen, #43751 should fix |
Adds an OpsLogSink abstraction for ops log destinations. Also implements
this abstraction for a file logger since it's easier to use files vs.
sockets with containers.
Fixes: https://tracker.ceph.com/issues/48752
Signed-off-by: Cory Snyder csnyder@iland.com