Skip to content

Commit

Permalink
feat(testutil): expand capturelogger to capture all logs
Browse files Browse the repository at this point in the history
Currently CaptureLogger only captures error logs. This expands it to capture all logs, allowing testing of all log messages.
This also associates the logger with a specific test (*testing.T), allowing the log entries to be associated with the correct test function.
  • Loading branch information
phemmer committed Apr 27, 2023
1 parent a868add commit 40e1993
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 30 deletions.
4 changes: 2 additions & 2 deletions plugins/inputs/mongodb/mongodb_server_test.go
Expand Up @@ -107,7 +107,7 @@ func TestSkipBehaviorIntegration(t *testing.T) {
}

m := &MongoDB{
Log: &testutil.CaptureLogger{},
Log: &testutil.CaptureLogger{T: t},
Servers: []string{unreachableMongoEndpoint},
}

Expand All @@ -129,7 +129,7 @@ func TestErrorBehaviorIntegration(t *testing.T) {
}

m := &MongoDB{
Log: &testutil.CaptureLogger{},
Log: &testutil.CaptureLogger{T: t},
Servers: []string{unreachableMongoEndpoint},
DisconnectedServersBehavior: "error",
}
Expand Down
2 changes: 1 addition & 1 deletion plugins/inputs/opcua/opcua_test.go
Expand Up @@ -85,7 +85,7 @@ func TestGetDataBadNodeContainerIntegration(t *testing.T) {
}
readConfig.Groups = append(readConfig.Groups, g)

logger := &testutil.CaptureLogger{}
logger := &testutil.CaptureLogger{T: t}
readClient, err := readConfig.CreateReadClient(logger)
require.NoError(t, err)
err = readClient.Connect()
Expand Down
2 changes: 1 addition & 1 deletion plugins/inputs/statsd/statsd_test.go
Expand Up @@ -1814,7 +1814,7 @@ func TestUdp(t *testing.T) {
}

func TestUdpFillQueue(t *testing.T) {
logger := testutil.CaptureLogger{}
logger := testutil.CaptureLogger{T: t}
plugin := &Statsd{
Log: &logger,
Protocol: "udp",
Expand Down
2 changes: 1 addition & 1 deletion plugins/inputs/tcp_listener/tcp_listener_test.go
Expand Up @@ -270,7 +270,7 @@ func TestRunParser(t *testing.T) {
func TestRunParserInvalidMsg(t *testing.T) {
var testmsg = []byte("cpu_load_short")

logger := &testutil.CaptureLogger{}
logger := &testutil.CaptureLogger{T: t}

listener, in := newTestTCPListener()
listener.Log = logger
Expand Down
4 changes: 2 additions & 2 deletions plugins/outputs/graylog/graylog_test_linux.go
Expand Up @@ -397,7 +397,7 @@ func TestWriteTCPServerDownRetry(t *testing.T) {
dummy, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)

logger := &testutil.CaptureLogger{}
logger := &testutil.CaptureLogger{T: t}
plugin := Graylog{
NameFieldNoPrefix: true,
Servers: []string{"tcp://" + dummy.Addr().String()},
Expand Down Expand Up @@ -434,7 +434,7 @@ func TestWriteTCPRetryStopping(t *testing.T) {
dummy, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)

logger := &testutil.CaptureLogger{}
logger := &testutil.CaptureLogger{T: t}
plugin := Graylog{
NameFieldNoPrefix: true,
Servers: []string{"tcp://" + dummy.Addr().String()},
Expand Down
2 changes: 1 addition & 1 deletion plugins/outputs/influxdb/http_test.go
Expand Up @@ -1201,7 +1201,7 @@ func TestDBNotFoundShouldDropMetricWhenSkipDatabaseCreateIsTrue(t *testing.T) {
),
}

logger := &testutil.CaptureLogger{}
logger := &testutil.CaptureLogger{T: t}
output := influxdb.InfluxDB{
URL: u.String(),
Database: "telegraf",
Expand Down
94 changes: 72 additions & 22 deletions testutil/capturelog.go
Expand Up @@ -4,79 +4,129 @@ import (
"fmt"
"log"
"sync"
"testing"

"github.com/influxdata/telegraf"
)

var _ telegraf.Logger = &CaptureLogger{}

const (
logLevelDebug = 'D'
logLevelWarn = 'W'
logLevelInfo = 'I'
logLevelError = 'E'
)

type logMessage struct {
level byte
message string
}

// CaptureLogger defines a logging structure for plugins.
type CaptureLogger struct {
Name string // Name is the plugin name, will be printed in the `[]`.
errors []string
T *testing.T
Name string // Name is the plugin name, will be printed in the `[]`.
messages []logMessage
sync.Mutex
}

// Errorf logs an error message, patterned after log.Printf.
func (l *CaptureLogger) Errorf(format string, args ...interface{}) {
s := fmt.Sprintf("E! ["+l.Name+"] "+format, args...)
func (l *CaptureLogger) msgString(msg logMessage) string {
return fmt.Sprintf("%c! [%s] %s", msg.level, l.Name, msg.message)
}
func (l *CaptureLogger) logMsg(msg logMessage) {
l.Lock()
l.errors = append(l.errors, s)
l.messages = append(l.messages, msg)
l.T.Log(l.msgString(msg))
l.Unlock()
log.Print(s)
}

func (l *CaptureLogger) logf(level byte, format string, args ...any) {
l.logMsg(logMessage{level, fmt.Sprintf(format, args...)})
}

func (l *CaptureLogger) loga(level byte, args ...any) {
l.logMsg(logMessage{level, fmt.Sprint(args...)})
}

// Errorf logs an error message, patterned after log.Printf.
func (l *CaptureLogger) Errorf(format string, args ...interface{}) {
l.logf(logLevelError, format, args...)
}

// Error logs an error message, patterned after log.Print.
func (l *CaptureLogger) Error(args ...interface{}) {
s := fmt.Sprint(append([]interface{}{"E! [" + l.Name + "] "}, args...)...)
l.Lock()
l.errors = append(l.errors, s)
l.Unlock()
log.Print(s)
l.loga(logLevelError, args...)
}

// Debugf logs a debug message, patterned after log.Printf.
func (l *CaptureLogger) Debugf(format string, args ...interface{}) {
log.Printf("D! ["+l.Name+"] "+format, args...)
l.logf(logLevelDebug, format, args...)
}

// Debug logs a debug message, patterned after log.Print.
func (l *CaptureLogger) Debug(args ...interface{}) {
log.Print(append([]interface{}{"D! [" + l.Name + "] "}, args...)...)
l.loga(logLevelDebug, args...)
}

// Warnf logs a warning message, patterned after log.Printf.
func (l *CaptureLogger) Warnf(format string, args ...interface{}) {
log.Printf("W! ["+l.Name+"] "+format, args...)
l.logf(logLevelWarn, format, args...)
}

// Warn logs a warning message, patterned after log.Print.
func (l *CaptureLogger) Warn(args ...interface{}) {
log.Print(append([]interface{}{"W! [" + l.Name + "] "}, args...)...)
l.loga(logLevelWarn, args...)
}

// Infof logs an information message, patterned after log.Printf.
func (l *CaptureLogger) Infof(format string, args ...interface{}) {
log.Printf("I! ["+l.Name+"] "+format, args...)
l.logf(logLevelInfo, format, args...)
}

// Info logs an information message, patterned after log.Print.
func (l *CaptureLogger) Info(args ...interface{}) {
log.Print(append([]interface{}{"I! [" + l.Name + "] "}, args...)...)
l.loga(logLevelInfo, args...)
}

func (l *CaptureLogger) Errors() []string {
func (l *CaptureLogger) Messages() []string {
l.Lock()
msgs := make([]string, len(l.messages))
for i, m := range l.messages {
msgs[i] = l.msgString(m)
}
l.Unlock()
return msgs
}

func (l *CaptureLogger) filter(level byte) []string {
l.Lock()
defer l.Unlock()
e := append([]string{}, l.errors...)
return e
var msgs []string
for _, m := range l.messages {
if m.level == level {
msgs = append(msgs, m.message)
}
}
return msgs
}

func (l *CaptureLogger) Errors() []string {
return l.filter(logLevelError)
}

func (l *CaptureLogger) Warns() []string {
return l.filter(logLevelWarn)
}

func (l *CaptureLogger) LastError() string {
l.Lock()
defer l.Unlock()
if len(l.errors) > 0 {
return l.errors[len(l.errors)-1]
for i := len(l.messages) - 1; i >= 0; i-- {
if l.messages[i].level == logLevelError {
return l.messages[i].message
}
}
return ""
}

0 comments on commit 40e1993

Please sign in to comment.