Merge: dns query log: robust file flushing mechanism #708
* commit 'd5f6dd1a46446ebb440811691a6ee8ce2443320d': - dns query log: robust file flushing mechanism * improve logging
This commit is contained in:
commit
7bb40bca0f
1
app.go
1
app.go
|
@ -372,6 +372,7 @@ func cleanupAlways() {
|
||||||
if len(pidFileName) != 0 {
|
if len(pidFileName) != 0 {
|
||||||
os.Remove(pidFileName)
|
os.Remove(pidFileName)
|
||||||
}
|
}
|
||||||
|
log.Info("Stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
// command-line arguments
|
// command-line arguments
|
||||||
|
|
|
@ -236,7 +236,7 @@ func (s *Server) stopInternal() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// flush remainder to file
|
// flush remainder to file
|
||||||
return s.queryLog.flushLogBuffer()
|
return s.queryLog.flushLogBuffer(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsRunning returns true if the DNS server is running
|
// IsRunning returns true if the DNS server is running
|
||||||
|
|
|
@ -30,6 +30,8 @@ type queryLog struct {
|
||||||
|
|
||||||
logBufferLock sync.RWMutex
|
logBufferLock sync.RWMutex
|
||||||
logBuffer []*logEntry
|
logBuffer []*logEntry
|
||||||
|
fileFlushLock sync.Mutex // synchronize a file-flushing goroutine and main thread
|
||||||
|
flushPending bool // don't start another goroutine while the previous one is still running
|
||||||
|
|
||||||
queryLogCache []*logEntry
|
queryLogCache []*logEntry
|
||||||
queryLogLock sync.RWMutex
|
queryLogLock sync.RWMutex
|
||||||
|
@ -91,13 +93,15 @@ func (l *queryLog) logRequest(question *dns.Msg, answer *dns.Msg, result *dnsfil
|
||||||
IP: ip,
|
IP: ip,
|
||||||
Upstream: upstream,
|
Upstream: upstream,
|
||||||
}
|
}
|
||||||
var flushBuffer []*logEntry
|
|
||||||
|
|
||||||
l.logBufferLock.Lock()
|
l.logBufferLock.Lock()
|
||||||
l.logBuffer = append(l.logBuffer, &entry)
|
l.logBuffer = append(l.logBuffer, &entry)
|
||||||
if len(l.logBuffer) >= logBufferCap {
|
needFlush := false
|
||||||
flushBuffer = l.logBuffer
|
if !l.flushPending {
|
||||||
l.logBuffer = nil
|
needFlush = len(l.logBuffer) >= logBufferCap
|
||||||
|
if needFlush {
|
||||||
|
l.flushPending = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
l.logBufferLock.Unlock()
|
l.logBufferLock.Unlock()
|
||||||
l.queryLogLock.Lock()
|
l.queryLogLock.Lock()
|
||||||
|
@ -116,15 +120,10 @@ func (l *queryLog) logRequest(question *dns.Msg, answer *dns.Msg, result *dnsfil
|
||||||
}
|
}
|
||||||
|
|
||||||
// if buffer needs to be flushed to disk, do it now
|
// if buffer needs to be flushed to disk, do it now
|
||||||
if len(flushBuffer) > 0 {
|
if needFlush {
|
||||||
// write to file
|
// write to file
|
||||||
// do it in separate goroutine -- we are stalling DNS response this whole time
|
// do it in separate goroutine -- we are stalling DNS response this whole time
|
||||||
go func() {
|
go l.flushLogBuffer(false)
|
||||||
err := l.flushToFile(flushBuffer)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Failed to flush the query log: %s", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return &entry
|
return &entry
|
||||||
|
|
|
@ -20,11 +20,20 @@ var (
|
||||||
const enableGzip = false
|
const enableGzip = false
|
||||||
|
|
||||||
// flushLogBuffer flushes the current buffer to file and resets the current buffer
|
// flushLogBuffer flushes the current buffer to file and resets the current buffer
|
||||||
func (l *queryLog) flushLogBuffer() error {
|
func (l *queryLog) flushLogBuffer(fullFlush bool) error {
|
||||||
|
l.fileFlushLock.Lock()
|
||||||
|
defer l.fileFlushLock.Unlock()
|
||||||
|
|
||||||
// flush remainder to file
|
// flush remainder to file
|
||||||
l.logBufferLock.Lock()
|
l.logBufferLock.Lock()
|
||||||
|
needFlush := len(l.logBuffer) >= logBufferCap
|
||||||
|
if !needFlush && !fullFlush {
|
||||||
|
l.logBufferLock.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
flushBuffer := l.logBuffer
|
flushBuffer := l.logBuffer
|
||||||
l.logBuffer = nil
|
l.logBuffer = nil
|
||||||
|
l.flushPending = false
|
||||||
l.logBufferLock.Unlock()
|
l.logBufferLock.Unlock()
|
||||||
err := l.flushToFile(flushBuffer)
|
err := l.flushToFile(flushBuffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -37,6 +46,7 @@ func (l *queryLog) flushLogBuffer() error {
|
||||||
// flushToFile saves the specified log entries to the query log file
|
// flushToFile saves the specified log entries to the query log file
|
||||||
func (l *queryLog) flushToFile(buffer []*logEntry) error {
|
func (l *queryLog) flushToFile(buffer []*logEntry) error {
|
||||||
if len(buffer) == 0 {
|
if len(buffer) == 0 {
|
||||||
|
log.Debug("querylog: there's nothing to write to a file")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
Loading…
Reference in New Issue