TUN-3194: Don't render log output when level is not enabled
This commit is contained in:
parent
cf1c9a3083
commit
4791ba3b87
|
@ -8,17 +8,17 @@ import (
|
||||||
"github.com/acmacalister/skittles"
|
"github.com/acmacalister/skittles"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Level of logging
|
// Level of logging, lower number means more verbose logging, higher more terse
|
||||||
type Level int
|
type Level int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// InfoLevel is for standard log messages
|
|
||||||
InfoLevel Level = iota
|
|
||||||
|
|
||||||
// DebugLevel is for messages that are intended for purposes debugging only
|
// DebugLevel is for messages that are intended for purposes debugging only
|
||||||
DebugLevel
|
DebugLevel Level = iota
|
||||||
|
|
||||||
// ErrorLevel is for error message to indicte something has gone wrong
|
// InfoLevel is for standard log messages
|
||||||
|
InfoLevel
|
||||||
|
|
||||||
|
// ErrorLevel is for error message to indicate something has gone wrong
|
||||||
ErrorLevel
|
ErrorLevel
|
||||||
|
|
||||||
// FatalLevel is for error message that log and kill the program with an os.exit(1)
|
// FatalLevel is for error message that log and kill the program with an os.exit(1)
|
||||||
|
|
|
@ -7,8 +7,8 @@ import "sync"
|
||||||
var SharedWriteManager = NewWriteManager()
|
var SharedWriteManager = NewWriteManager()
|
||||||
|
|
||||||
type writeData struct {
|
type writeData struct {
|
||||||
writeFunc func([]byte)
|
target LogOutput
|
||||||
data []byte
|
data []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteManager is a logging service that handles managing multiple writing streams
|
// WriteManager is a logging service that handles managing multiple writing streams
|
||||||
|
@ -31,9 +31,9 @@ func NewWriteManager() OutputManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append adds a message to the writer runloop
|
// Append adds a message to the writer runloop
|
||||||
func (m *WriteManager) Append(data []byte, callback func([]byte)) {
|
func (m *WriteManager) Append(data []byte, target LogOutput) {
|
||||||
m.wg.Add(1)
|
m.wg.Add(1)
|
||||||
m.writeChan <- writeData{data: data, writeFunc: callback}
|
m.writeChan <- writeData{data: data, target: target}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown stops the sync manager service
|
// Shutdown stops the sync manager service
|
||||||
|
@ -49,7 +49,7 @@ func (m *WriteManager) run() {
|
||||||
select {
|
select {
|
||||||
case event, ok := <-m.writeChan:
|
case event, ok := <-m.writeChan:
|
||||||
if ok {
|
if ok {
|
||||||
event.writeFunc(event.data)
|
event.target.WriteLogLine(event.data)
|
||||||
m.wg.Done()
|
m.wg.Done()
|
||||||
}
|
}
|
||||||
case <-m.shutdown:
|
case <-m.shutdown:
|
||||||
|
|
|
@ -6,13 +6,19 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type outputFunc func(b []byte)
|
||||||
|
|
||||||
|
func (f outputFunc) WriteLogLine(data []byte) {
|
||||||
|
f(data)
|
||||||
|
}
|
||||||
|
|
||||||
func TestWriteManger(t *testing.T) {
|
func TestWriteManger(t *testing.T) {
|
||||||
testData := []byte(string("hello Austin, how are you doing?"))
|
testData := []byte(string("hello Austin, how are you doing?"))
|
||||||
waitChan := make(chan []byte)
|
waitChan := make(chan []byte)
|
||||||
m := NewWriteManager()
|
m := NewWriteManager()
|
||||||
m.Append(testData, func(b []byte) {
|
m.Append(testData, outputFunc(func(b []byte) {
|
||||||
waitChan <- b
|
waitChan <- b
|
||||||
})
|
}))
|
||||||
resp := <-waitChan
|
resp := <-waitChan
|
||||||
assert.Equal(t, testData, resp)
|
assert.Equal(t, testData, resp)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ func NewMockWriteManager() OutputManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append is a mock stub
|
// Append is a mock stub
|
||||||
func (m *MockWriteManager) Append(data []byte, callback func([]byte)) {
|
func (m *MockWriteManager) Append(data []byte, target LogOutput) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown is a mock stub
|
// Shutdown is a mock stub
|
||||||
|
|
|
@ -10,9 +10,13 @@ import (
|
||||||
// provided for testing
|
// provided for testing
|
||||||
var osExit = os.Exit
|
var osExit = os.Exit
|
||||||
|
|
||||||
|
type LogOutput interface {
|
||||||
|
WriteLogLine([]byte)
|
||||||
|
}
|
||||||
|
|
||||||
// OutputManager is used to sync data of Output
|
// OutputManager is used to sync data of Output
|
||||||
type OutputManager interface {
|
type OutputManager interface {
|
||||||
Append([]byte, func([]byte))
|
Append([]byte, LogOutput)
|
||||||
Shutdown()
|
Shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,38 +39,66 @@ type sourceGroup struct {
|
||||||
levelsSupported []Level
|
levelsSupported []Level
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *sourceGroup) WriteLogLine(data []byte) {
|
||||||
|
_, _ = s.writer.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sourceGroup) supportsLevel(l Level) bool {
|
||||||
|
for _, level := range s.levelsSupported {
|
||||||
|
if l == level {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// OutputWriter is the standard logging implementation
|
// OutputWriter is the standard logging implementation
|
||||||
type OutputWriter struct {
|
type OutputWriter struct {
|
||||||
groups []sourceGroup
|
groups []*sourceGroup
|
||||||
syncWriter OutputManager
|
syncWriter OutputManager
|
||||||
|
minLevel Level
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOutputWriter create a new logger
|
// NewOutputWriter create a new logger
|
||||||
func NewOutputWriter(syncWriter OutputManager) *OutputWriter {
|
func NewOutputWriter(syncWriter OutputManager) *OutputWriter {
|
||||||
return &OutputWriter{
|
return &OutputWriter{
|
||||||
syncWriter: syncWriter,
|
syncWriter: syncWriter,
|
||||||
groups: make([]sourceGroup, 0),
|
groups: nil,
|
||||||
|
minLevel: FatalLevel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a writer and formatter to output to
|
// Add a writer and formatter to output to
|
||||||
func (s *OutputWriter) Add(writer io.Writer, formatter Formatter, levels ...Level) {
|
func (s *OutputWriter) Add(writer io.Writer, formatter Formatter, levels ...Level) {
|
||||||
s.groups = append(s.groups, sourceGroup{writer: writer, formatter: formatter, levelsSupported: levels})
|
s.groups = append(s.groups, &sourceGroup{writer: writer, formatter: formatter, levelsSupported: levels})
|
||||||
|
|
||||||
|
// track most verbose (lowest) level we need to output
|
||||||
|
for _, level := range levels {
|
||||||
|
if level < s.minLevel {
|
||||||
|
s.minLevel = level
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error writes an error to the logging sources
|
// Error writes an error to the logging sources
|
||||||
func (s *OutputWriter) Error(message string) {
|
func (s *OutputWriter) Error(message string) {
|
||||||
s.output(ErrorLevel, message)
|
if s.minLevel <= ErrorLevel {
|
||||||
|
s.output(ErrorLevel, message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info writes an info string to the logging sources
|
// Info writes an info string to the logging sources
|
||||||
func (s *OutputWriter) Info(message string) {
|
func (s *OutputWriter) Info(message string) {
|
||||||
s.output(InfoLevel, message)
|
if s.minLevel <= InfoLevel {
|
||||||
|
s.output(InfoLevel, message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug writes a debug string to the logging sources
|
// Debug writes a debug string to the logging sources
|
||||||
func (s *OutputWriter) Debug(message string) {
|
func (s *OutputWriter) Debug(message string) {
|
||||||
s.output(DebugLevel, message)
|
if s.minLevel <= DebugLevel {
|
||||||
|
s.output(DebugLevel, message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fatal writes a error string to the logging sources and runs does an os.exit()
|
// Fatal writes a error string to the logging sources and runs does an os.exit()
|
||||||
|
@ -78,17 +110,23 @@ func (s *OutputWriter) Fatal(message string) {
|
||||||
|
|
||||||
// Errorf writes a formatted error to the logging sources
|
// Errorf writes a formatted error to the logging sources
|
||||||
func (s *OutputWriter) Errorf(format string, args ...interface{}) {
|
func (s *OutputWriter) Errorf(format string, args ...interface{}) {
|
||||||
s.output(ErrorLevel, fmt.Sprintf(format, args...))
|
if s.minLevel <= ErrorLevel {
|
||||||
|
s.output(ErrorLevel, fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Infof writes a formatted info statement to the logging sources
|
// Infof writes a formatted info statement to the logging sources
|
||||||
func (s *OutputWriter) Infof(format string, args ...interface{}) {
|
func (s *OutputWriter) Infof(format string, args ...interface{}) {
|
||||||
s.output(InfoLevel, fmt.Sprintf(format, args...))
|
if s.minLevel <= InfoLevel {
|
||||||
|
s.output(InfoLevel, fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugf writes a formatted debug statement to the logging sources
|
// Debugf writes a formatted debug statement to the logging sources
|
||||||
func (s *OutputWriter) Debugf(format string, args ...interface{}) {
|
func (s *OutputWriter) Debugf(format string, args ...interface{}) {
|
||||||
s.output(DebugLevel, fmt.Sprintf(format, args...))
|
if s.minLevel <= DebugLevel {
|
||||||
|
s.output(DebugLevel, fmt.Sprintf(format, args...))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fatalf writes a writes a formatted error statement and runs does an os.exit()
|
// Fatalf writes a writes a formatted error statement and runs does an os.exit()
|
||||||
|
@ -100,31 +138,16 @@ func (s *OutputWriter) Fatalf(format string, args ...interface{}) {
|
||||||
|
|
||||||
// output does the actual write to the sync manager
|
// output does the actual write to the sync manager
|
||||||
func (s *OutputWriter) output(l Level, content string) {
|
func (s *OutputWriter) output(l Level, content string) {
|
||||||
|
now := time.Now()
|
||||||
for _, group := range s.groups {
|
for _, group := range s.groups {
|
||||||
if isSupported(group, l) {
|
if group.supportsLevel(l) {
|
||||||
logLine := fmt.Sprintf("%s%s\n", group.formatter.Timestamp(l, time.Now()),
|
logLine := fmt.Sprintf("%s%s\n", group.formatter.Timestamp(l, now),
|
||||||
group.formatter.Content(l, content))
|
group.formatter.Content(l, content))
|
||||||
s.append(group, []byte(logLine))
|
s.syncWriter.Append([]byte(logLine), group)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *OutputWriter) append(group sourceGroup, logLine []byte) {
|
|
||||||
s.syncWriter.Append(logLine, func(b []byte) {
|
|
||||||
group.writer.Write(b)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// isSupported checks if the log level is supported
|
|
||||||
func isSupported(group sourceGroup, l Level) bool {
|
|
||||||
for _, level := range group.levelsSupported {
|
|
||||||
if l == level {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write implements io.Writer to support SetOutput of the log package
|
// Write implements io.Writer to support SetOutput of the log package
|
||||||
func (s *OutputWriter) Write(p []byte) (n int, err error) {
|
func (s *OutputWriter) Write(p []byte) (n int, err error) {
|
||||||
s.Info(string(p))
|
s.Info(string(p))
|
||||||
|
|
|
@ -55,6 +55,8 @@ func TestOutputWrite(t *testing.T) {
|
||||||
logger := NewOutputWriter(m)
|
logger := NewOutputWriter(m)
|
||||||
logger.Add(&testBuffer, f, InfoLevel)
|
logger.Add(&testBuffer, f, InfoLevel)
|
||||||
|
|
||||||
|
logger.Debugf("debug message not logged here")
|
||||||
|
|
||||||
testData := "hello Bob Bork, how are you doing?"
|
testData := "hello Bob Bork, how are you doing?"
|
||||||
logger.Info(testData)
|
logger.Info(testData)
|
||||||
testTime := f.Timestamp(InfoLevel, time.Now())
|
testTime := f.Timestamp(InfoLevel, time.Now())
|
||||||
|
|
Loading…
Reference in New Issue