Skip to content

Commit 764a7f1

Browse files
committed
Ensure all DB errors when inserting logs are always logged to logsink
This improves visibility in cases such as LP1930899 where underprovisioned mongodb instance prevented log entries from being persisted with no additional error output. As the DB error was returned back to the caller (log sender worker), the worker would keep restarting thus preventing models from logging anything. While this commit does not fix the underlying problem (underprovisioned mongo) it should at least make the cause of the problem more obvious to users that are trying to diagnose similar issues by inspecting the logsink.log file contents.
1 parent 203855b commit 764a7f1

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

apiserver/logsink.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,19 @@ func (s *agentLoggingStrategy) WriteLog(m params.LogRecord) error {
176176
Message: m.Message,
177177
}}), "logging to DB failed")
178178

179+
// If the log entries cannot be inserted to the DB log out an error
180+
// to let users know. See LP1930899.
181+
if dbErr != nil {
182+
// If this fails then the next logToFile will fail as well; no
183+
// need to check for errors here.
184+
_ = logToFile(s.fileLogger, s.filePrefix, params.LogRecord{
185+
Time: time.Now(),
186+
Module: "juju.apiserver",
187+
Level: loggo.ERROR.String(),
188+
Message: errors.Annotate(dbErr, "unable to persist log entry to the database").Error(),
189+
})
190+
}
191+
179192
m.Entity = s.entity
180193
fileErr := errors.Annotate(
181194
logToFile(s.fileLogger, s.filePrefix, m),

apiserver/logsink_internal_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2021 Canonical Ltd.
2+
// Licensed under the AGPLv3, see LICENCE file for details.
3+
4+
package apiserver
5+
6+
import (
7+
"bytes"
8+
"time"
9+
10+
"github.com/juju/errors"
11+
"github.com/juju/loggo"
12+
gc "gopkg.in/check.v1"
13+
14+
"github.com/juju/juju/apiserver/params"
15+
"github.com/juju/juju/state"
16+
)
17+
18+
type loggingStrategySuite struct {
19+
logs loggo.TestWriter
20+
}
21+
22+
var _ = gc.Suite(&loggingStrategySuite{})
23+
24+
func (s *loggingStrategySuite) TestLoggingOfDBInsertFailures(c *gc.C) {
25+
var logBuf bytes.Buffer
26+
strategy := &agentLoggingStrategy{
27+
dblogger: failingRecordLogger{},
28+
fileLogger: &logBuf,
29+
}
30+
31+
err := strategy.WriteLog(params.LogRecord{
32+
Time: time.Now(),
33+
Level: "WARN",
34+
Message: "running low on resources",
35+
})
36+
37+
// The captured DB error should be surfaced from WriteLog
38+
c.Assert(err, gc.ErrorMatches, ".*spawn more overlords")
39+
40+
// Ensure that the DB error was also written to the sink
41+
c.Assert(logBuf.String(), gc.Matches, "(?m).*spawn more overlords.*")
42+
}
43+
44+
type failingRecordLogger struct{}
45+
46+
func (failingRecordLogger) Log([]state.LogRecord) error {
47+
return errors.New("spawn more overlords")
48+
}

0 commit comments

Comments
 (0)