-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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 buffered write syncer #952
Conversation
Codecov Report
@@ Coverage Diff @@
## master #952 +/- ##
==========================================
+ Coverage 98.12% 98.16% +0.03%
==========================================
Files 44 45 +1
Lines 1975 2014 +39
==========================================
+ Hits 1938 1977 +39
Misses 29 29
Partials 8 8
Continue to review full report at Codecov.
|
fc8195f
to
d335a50
Compare
Co-authored-by: Prashant Varanasi <github@prashantv.com>
Co-authored-by: Abhinav Gupta <mail@abhinavg.net>
d335a50
to
2312b39
Compare
Co-authored-by: Abhinav Gupta <mail@abhinavg.net>
Co-authored-by: Abhinav Gupta <mail@abhinavg.net>
…k on loadConfig if needed
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.
Sorry for the delay. I'll look at the next iteration quicker!
zapcore/buffered_write_syncer.go
Outdated
// The default values are; Size 256kb, FlushInterval 30s. | ||
type BufferedWriteSyncer struct { | ||
WriteSyncer | ||
|
||
Size int | ||
FlushInterval time.Duration |
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.
minor nit: we should specify the defaults above the fields as we document the fields:
// Size specifies the maximum amount of data the writer will buffer before
// flushing. Defaults to 256 kB.
// FlushInterval specifies how often the writer should flush data if there
// have been no writes. Defaults to 30 seconds.
zapcore/buffered_write_syncer.go
Outdated
_defaultFlushInterval = 30 * time.Second | ||
) | ||
|
||
func (s *BufferedWriteSyncer) loadConfig() { |
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.
minor naming: can we name this init or initialize because the bool is called initialize. Or we can name the bool "loaded" and call this "load", but I'm more in favor of init or initialize.
zapcore/buffered_write_syncer.go
Outdated
} | ||
s.ticker = s.Clock.NewTicker(flushInterval) | ||
|
||
s.writer = bufio.NewWriterSize(s.WriteSyncer, size) |
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.
minor optimization on the WriteSyncer:
since BufferedWriteSyncer is already thread-safe, we can optimize this a bit if s.WriteSyncer was wrapped with zapcore.Lock
.
writer := s.WriteSyncer
if w, ok := writer.(*lockedWriteSyncer); ok {
writer = w.ws // don't double lock
}
s.writer = bufio.NewWriterSize(writer, size)
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.
Mostly LGTM. For the wrap-twice case, can we add a test with an explicit sync to verify that the inner BufWriter was also 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.
lgtm, just nits about closing files in tests and not needing to manually closing files.
Co-authored-by: Abhinav Gupta <mail@abhinavg.net>
Co-authored-by: Abhinav Gupta <mail@abhinavg.net>
…case for wrap twice sync
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 but wait for @abhinav 's stamp too.
No, we don't want a merge commit for this. Reverting. |
close(s.stop) | ||
return s.Sync() |
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 we wait for the background goroutine to stop before returning here? It leads to:
- no goroutine running after
Close
guaranteed - avoids odd cases where a
Sync
can happen after theClose
returns
// remaining, unwritten data. This will not close the underlying WriteSyncer. | ||
func (s *BufferedWriteSyncer) Close() error { | ||
s.ticker.Stop() | ||
close(s.stop) |
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.
Since this will panic if we do it twice, do we want to explicitly call out that Close
must only be called once, or put some protection here in case Close
is called twice?
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.
Going with a doc for now. Guarding against it is possible but seems unnecessary given that standard usage will probably be:
ws := zapcore.BufferedWriteSyncer{...}
defer ws.Stop()
(we do need to guard against Stop without Start, so going to add that too.)
} | ||
|
||
// Close closes the buffer, cleans up background goroutines, and flushes | ||
// remaining, unwritten data. This will not close the underlying WriteSyncer. |
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 warning that this will not close the underlying WriteSyncer
makes me wonder if Close
is a little surprising. Would this be better named something else like Stop
to make it very clear that it doesn't close the underlying writer?
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.
Reasonable. Renaming.
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.
Sounds good. Stop
makes more sense in the context of this specific writer.
Reopened in #961 @prashantv |
This diff addresses comments in #782
API for BufferedWriteSyncer: