common: implement a common log package

This change adds two log packages.  One for the external go-ceph
consumers under common/log, and one for the internal use within the
go-ceph code under internal/log.  The external package exports two
functions for consumers, SetWarnf() and SetDebugf(), that set a
logger for warnings and debug messages respectively. They take a
log.Printf compatible function as argument.

The internal package exports these functions as Warnf() and Debugf(),
which can be used by the go-ceph code to log warnings and debug
messages.

Signed-off-by: Sven Anderson <sven@redhat.com>
This commit is contained in:
Sven Anderson 2022-02-01 16:03:26 +01:00 committed by mergify[bot]
parent f6eeb68e33
commit 72493ed2f7
3 changed files with 115 additions and 0 deletions

22
common/log/log.go Normal file
View File

@ -0,0 +1,22 @@
//go:build ceph_preview
// +build ceph_preview
// Package log allows to enable go-ceph logging and integrate it with the
// logging of the go-ceph consuming code.
package log
import (
intLog "github.com/ceph/go-ceph/internal/log"
)
// SetWarnf sets the log.Printf compatible receiver for warning logs.
// PREVIEW
func SetWarnf(f func(format string, v ...interface{})) {
intLog.Warnf = f
}
// SetDebugf sets the log.Printf compatible receiver for debug logs.
// PREVIEW
func SetDebugf(f func(format string, v ...interface{})) {
intLog.Debugf = f
}

14
internal/log/log.go Normal file
View File

@ -0,0 +1,14 @@
// Package log is the internal package for go-ceph logging. This package is only
// used from go-ceph code, not from consumers of go-ceph. go-ceph code uses the
// functions in this package to log information that can't be returned as
// errors. The functions default to no-ops and can be set with the external log
// package common/log by the go-ceph consumers.
package log
func noop(string, ...interface{}) {}
// These variables are set by the common log package.
var (
Warnf = noop
Debugf = noop
)

79
internal/log/log_test.go Normal file
View File

@ -0,0 +1,79 @@
package log_test
import (
"io"
stdlog "log"
"os"
"strings"
"testing"
"github.com/ceph/go-ceph/common/log"
intLog "github.com/ceph/go-ceph/internal/log"
"github.com/stretchr/testify/assert"
)
func testLog() {
intLog.Debugf("-%s-", "debug")
intLog.Warnf("-%s-", "warn")
}
var testOut = []string{
"<go-ceph>[DBG]log_test.go:16: -debug-",
"<go-ceph>[WRN]log_test.go:17: -warn-",
"",
}
func checkLines(t *testing.T, lines []string) {
for i := range lines {
assert.Equal(t, testOut[len(testOut)-len(lines)+i], lines[i])
}
}
func captureAllOutput(f func()) string {
oldout := os.Stdout
olderr := os.Stderr
oldlog := stdlog.Writer()
defer func() {
os.Stdout = oldout
os.Stderr = olderr
stdlog.SetOutput(oldlog)
}()
r, w, _ := os.Pipe()
os.Stdout = w
os.Stderr = w
stdlog.SetOutput(w)
go func() {
f()
_ = w.Close()
}()
buf, _ := io.ReadAll(r)
return string(buf)
}
func TestLogOffByDefault(t *testing.T) {
out := captureAllOutput(func() { testLog() })
assert.Empty(t, out)
}
func TestLogLevels(t *testing.T) {
stdlog.Default()
var out strings.Builder
warn := stdlog.New(&out, "<go-ceph>[WRN]", stdlog.Lshortfile)
log.SetWarnf(warn.Printf)
t.Run("Warnf", func(t *testing.T) {
out.Reset()
testLog()
lines := strings.Split(out.String(), "\n")
assert.Len(t, lines, 2)
checkLines(t, lines)
})
debug := stdlog.New(&out, "<go-ceph>[DBG]", stdlog.Lshortfile)
log.SetDebugf(debug.Printf)
t.Run("Debugf", func(t *testing.T) {
out.Reset()
testLog()
lines := strings.Split(out.String(), "\n")
assert.Len(t, lines, 3)
checkLines(t, lines)
})
}