Merge "lib/vlog: update to latest version of llog adding 'Depth' methods."
diff --git a/vlog/.api b/vlog/.api
index 667703c..c4668cd 100644
--- a/vlog/.api
+++ b/vlog/.api
@@ -2,17 +2,22 @@
pkg vlog, func ConfigureLibraryLoggerFromFlags() error
pkg vlog, func ConfigureLoggerFromFlags(Logger) error
pkg vlog, func Error(...interface{})
+pkg vlog, func ErrorDepth(int, ...interface{})
pkg vlog, func Errorf(string, ...interface{})
pkg vlog, func Fatal(...interface{})
+pkg vlog, func FatalDepth(int, ...interface{})
pkg vlog, func Fatalf(string, ...interface{})
pkg vlog, func FlushLog()
pkg vlog, func Info(...interface{})
+pkg vlog, func InfoDepth(int, ...interface{})
pkg vlog, func InfoStack(bool)
pkg vlog, func Infof(string, ...interface{})
+pkg vlog, func InfofDepth(int, string, ...interface{})
pkg vlog, func LogCall(...interface{}) func(...interface{})
pkg vlog, func LogCallf(string, ...interface{}) func(string, ...interface{})
pkg vlog, func NewLogger(string) Logger
pkg vlog, func Panic(...interface{})
+pkg vlog, func PanicDepth(int, ...interface{})
pkg vlog, func Panicf(string, ...interface{})
pkg vlog, func Stats() LevelStats
pkg vlog, func V(Level) bool
@@ -25,6 +30,7 @@
pkg vlog, method (*StderrThreshold) String() string
pkg vlog, method (AlsoLogToStderr) LoggingOpt()
pkg vlog, method (AutoFlush) LoggingOpt()
+pkg vlog, method (FilepathSpec) LoggingOpt()
pkg vlog, method (Level) LoggingOpt()
pkg vlog, method (LogDir) LoggingOpt()
pkg vlog, method (LogToStderr) LoggingOpt()
@@ -35,26 +41,35 @@
pkg vlog, method (TraceLocation) LoggingOpt()
pkg vlog, type AlsoLogToStderr bool
pkg vlog, type AutoFlush bool
-pkg vlog, type InfoLog interface { Info, InfoStack, Infof }
+pkg vlog, type FilepathSpec struct
+pkg vlog, type FilepathSpec struct, embedded llog.FilepathSpec
+pkg vlog, type InfoLog interface { Info, InfoDepth, InfoStack, Infof, InfofDepth }
pkg vlog, type InfoLog interface, Info(...interface{})
+pkg vlog, type InfoLog interface, InfoDepth(int, ...interface{})
pkg vlog, type InfoLog interface, InfoStack(bool)
pkg vlog, type InfoLog interface, Infof(string, ...interface{})
+pkg vlog, type InfoLog interface, InfofDepth(int, string, ...interface{})
pkg vlog, type Level llog.Level
pkg vlog, type LevelStats llog.Stats
pkg vlog, type LogDir string
pkg vlog, type LogToStderr bool
-pkg vlog, type Logger interface { Configure, Error, Errorf, Fatal, Fatalf, FlushLog, Info, InfoStack, Infof, LogDir, Panic, Panicf, Stats, V, VI }
+pkg vlog, type Logger interface { Configure, Error, ErrorDepth, Errorf, Fatal, FatalDepth, Fatalf, FlushLog, Info, InfoDepth, InfoStack, Infof, InfofDepth, LogDir, Panic, PanicDepth, Panicf, Stats, V, VI }
pkg vlog, type Logger interface, Configure(...LoggingOpts) error
pkg vlog, type Logger interface, Error(...interface{})
+pkg vlog, type Logger interface, ErrorDepth(int, ...interface{})
pkg vlog, type Logger interface, Errorf(string, ...interface{})
pkg vlog, type Logger interface, Fatal(...interface{})
+pkg vlog, type Logger interface, FatalDepth(int, ...interface{})
pkg vlog, type Logger interface, Fatalf(string, ...interface{})
pkg vlog, type Logger interface, FlushLog()
pkg vlog, type Logger interface, Info(...interface{})
+pkg vlog, type Logger interface, InfoDepth(int, ...interface{})
pkg vlog, type Logger interface, InfoStack(bool)
pkg vlog, type Logger interface, Infof(string, ...interface{})
+pkg vlog, type Logger interface, InfofDepth(int, string, ...interface{})
pkg vlog, type Logger interface, LogDir() string
pkg vlog, type Logger interface, Panic(...interface{})
+pkg vlog, type Logger interface, PanicDepth(int, ...interface{})
pkg vlog, type Logger interface, Panicf(string, ...interface{})
pkg vlog, type Logger interface, Stats() LevelStats
pkg vlog, type Logger interface, V(Level) bool
@@ -74,5 +89,5 @@
pkg vlog, type Verbosity interface { V, VI }
pkg vlog, type Verbosity interface, V(Level) bool
pkg vlog, type Verbosity interface, VI(Level) InfoLog
-pkg vlog, var Configured error
+pkg vlog, var ErrConfigured error
pkg vlog, var Log *logger
diff --git a/vlog/GO.PACKAGE b/vlog/GO.PACKAGE
index e33cb69..a46fa75 100644
--- a/vlog/GO.PACKAGE
+++ b/vlog/GO.PACKAGE
@@ -1,5 +1,5 @@
{
"imports": [
- {"allow": "github.com/cosmosnicolaou/llog"}
+ {"allow": "github.com/cosnicolaou/llog"}
]
}
diff --git a/vlog/flags.go b/vlog/flags.go
index 16931fe..21a21d2 100644
--- a/vlog/flags.go
+++ b/vlog/flags.go
@@ -8,7 +8,7 @@
"flag"
"fmt"
- "github.com/cosmosnicolaou/llog"
+ "github.com/cosnicolaou/llog"
)
var (
diff --git a/vlog/funcs.go b/vlog/funcs.go
index fd8c478..c7c7e23 100644
--- a/vlog/funcs.go
+++ b/vlog/funcs.go
@@ -5,7 +5,7 @@
package vlog
import (
- "github.com/cosmosnicolaou/llog"
+ "github.com/cosnicolaou/llog"
)
// Info logs to the INFO log.
@@ -22,6 +22,20 @@
Log.maybeFlush()
}
+// InfoDepth acts as Info but uses depth to determine which call frame to log.
+// A depth of 0 is equivalent to calling Info.
+func InfoDepth(depth int, args ...interface{}) {
+ Log.log.PrintDepth(llog.InfoLog, depth, args...)
+ Log.maybeFlush()
+}
+
+// InfofDepth acts as Infof but uses depth to determine which call frame to log.
+// A depth of 0 is equivalent to calling Infof.
+func InfofDepth(depth int, format string, args ...interface{}) {
+ Log.log.PrintfDepth(llog.InfoLog, depth, format, args...)
+ Log.maybeFlush()
+}
+
// InfoStack logs the current goroutine's stack if the all parameter
// is false, or the stacks of all goroutines if it's true.
func InfoStack(all bool) {
@@ -56,6 +70,13 @@
Log.maybeFlush()
}
+// ErrorDepth acts as Error but uses depth to determine which call frame to log.
+// A depth of 0 is equivalent to calling Error.
+func ErrorDepth(depth int, args ...interface{}) {
+ Log.log.PrintDepth(llog.ErrorLog, depth, args...)
+ Log.maybeFlush()
+}
+
// Errorf logs to the ERROR and INFO logs.
// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
func Errorf(format string, args ...interface{}) {
@@ -70,6 +91,12 @@
Log.log.Print(llog.FatalLog, args...)
}
+// FatalDepth acts as Fatal but uses depth to determine which call frame to log.
+// A depth of 0 is equivalent to calling Fatal.
+func FatalDepth(depth int, args ...interface{}) {
+ Log.log.PrintDepth(llog.FatalLog, depth, args...)
+}
+
// Fatalf logs to the FATAL, ERROR and INFO logs,
// including a stack trace of all running goroutines, then calls os.Exit(255).
// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
@@ -97,6 +124,12 @@
Log.Panic(args...)
}
+// PanicDepth acts as Panic but uses depth to determine which call frame to log.
+// A depth of 0 is equivalent to calling Panic.
+func PanicDepth(depth int, args ...interface{}) {
+ Log.PanicDepth(depth, args...)
+}
+
// Panicf is equivalent to Errorf() followed by a call to panic().
func Panicf(format string, args ...interface{}) {
Log.Panicf(format, args...)
diff --git a/vlog/log.go b/vlog/log.go
index b1e7e13..d5a7a33 100644
--- a/vlog/log.go
+++ b/vlog/log.go
@@ -11,7 +11,7 @@
"runtime"
"sync"
- "github.com/cosmosnicolaou/llog"
+ "github.com/cosnicolaou/llog"
)
const (
@@ -34,8 +34,8 @@
}
var (
- Log *logger
- Configured = errors.New("logger has already been configured")
+ Log *logger
+ ErrConfigured = errors.New("logger has already been configured")
)
const stackSkip = 1
@@ -66,7 +66,7 @@
}
}
if l.configured && !override {
- return Configured
+ return ErrConfigured
}
for _, o := range opts {
switch v := o.(type) {
@@ -87,6 +87,8 @@
}
case ModuleSpec:
l.log.SetVModule(v.ModuleSpec)
+ case FilepathSpec:
+ l.log.SetVFilepath(v.FilepathSpec)
case TraceLocation:
l.log.SetTraceLocation(v.TraceLocation)
case StderrThreshold:
@@ -127,6 +129,20 @@
l.maybeFlush()
}
+// InfoDepth acts as Info but uses depth to determine which call frame to log.
+// A depth of 0 is equivalent to calling Info.
+func (l *logger) InfoDepth(depth int, args ...interface{}) {
+ l.log.PrintDepth(llog.InfoLog, depth, args...)
+ l.maybeFlush()
+}
+
+// InfofDepth acts as Infof but uses depth to determine which call frame to log.
+// A depth of 0 is equivalent to calling Infof.
+func (l *logger) InfofDepth(depth int, format string, args ...interface{}) {
+ l.log.PrintfDepth(llog.InfoLog, depth, format, args...)
+ l.maybeFlush()
+}
+
func infoStack(l *logger, all bool) {
n := initialMaxStackBufSize
var trace []byte
@@ -155,9 +171,11 @@
type discardInfo struct{}
-func (_ *discardInfo) Info(args ...interface{}) {}
-func (_ *discardInfo) Infof(format string, args ...interface{}) {}
-func (_ *discardInfo) InfoStack(all bool) {}
+func (_ *discardInfo) Info(...interface{}) {}
+func (_ *discardInfo) Infof(_ string, _ ...interface{}) {}
+func (_ *discardInfo) InfoDepth(_ int, _ ...interface{}) {}
+func (_ *discardInfo) InfofDepth(_ int, _ string, _ ...interface{}) {}
+func (_ *discardInfo) InfoStack(_ bool) {}
func (l *logger) VI(v Level) InfoLog {
if l.log.V(llog.Level(v)) {
@@ -178,6 +196,13 @@
l.maybeFlush()
}
+// ErrorDepth acts as Error but uses depth to determine which call frame to log.
+// A depth of 0 is equivalent to calling Error.
+func (l *logger) ErrorDepth(depth int, args ...interface{}) {
+ l.log.PrintDepth(llog.ErrorLog, depth, args...)
+ l.maybeFlush()
+}
+
// Errorf logs to the ERROR and INFO logs.
// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
func (l *logger) Errorf(format string, args ...interface{}) {
@@ -192,6 +217,12 @@
l.log.Print(llog.FatalLog, args...)
}
+// FatalDepth acts as Fatal but uses depth to determine which call frame to log.
+// A depth of 0 is equivalent to calling Fatal.
+func (l *logger) FatalDepth(depth int, args ...interface{}) {
+ l.log.PrintDepth(llog.FatalLog, depth, args...)
+}
+
// Fatalf logs to the FATAL, ERROR and INFO logs,
// including a stack trace of all running goroutines, then calls os.Exit(255).
// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
@@ -205,6 +236,13 @@
panic(fmt.Sprint(args...))
}
+// PanicDepth acts as Panic but uses depth to determine which call frame to log.
+// A depth of 0 is equivalent to calling Panic.
+func (l *logger) PanicDepth(depth int, args ...interface{}) {
+ l.ErrorDepth(depth, args...)
+ panic(fmt.Sprint(args...))
+}
+
// Panicf is equivalent to Errorf() followed by a call to panic().
func (l *logger) Panicf(format string, args ...interface{}) {
l.Errorf(format, args...)
diff --git a/vlog/log_test.go b/vlog/log_test.go
index 9243554..1e09263 100644
--- a/vlog/log_test.go
+++ b/vlog/log_test.go
@@ -72,7 +72,7 @@
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
- fileRE := regexp.MustCompile(`\S+ \S+ \S+ (.*):.*`)
+ fileRE := regexp.MustCompile(`\S+ \S+\s+\S+ (.*):.*`)
for _, line := range contents {
name := fileRE.FindStringSubmatch(line)
if len(name) < 2 {
@@ -89,6 +89,43 @@
}
}
+func TestDepth(t *testing.T) {
+ dir, err := ioutil.TempDir("", "logtest")
+ defer os.RemoveAll(dir)
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ logger := vlog.NewLogger("testHeader")
+ logger.Configure(vlog.LogDir(dir), vlog.Level(2))
+
+ logger.InfoDepth(0, "here\n")
+ tmp := func() {
+ logger.InfoDepth(1, "still here\n")
+ logger.InfoDepth(2, "not here\n")
+ }
+ tmp()
+ logger.FlushLog()
+ contents, err := readLogFiles(dir)
+ if err != nil {
+ t.Fatalf("unexpected error: %s", err)
+ }
+ fileRE := regexp.MustCompile(`\S+ \S+\s+\S+ (.*):.*`)
+ files := []string{}
+ for _, line := range contents {
+ name := fileRE.FindStringSubmatch(line)
+ if len(name) < 2 {
+ t.Errorf("failed to find file in %s", line)
+ continue
+ }
+ files = append(files, name[1])
+ }
+ for i, want := range []string{"log_test.go", "log_test.go", "testing.go"} {
+ if got := files[i]; got != want {
+ t.Errorf("%d: got %v, want %v", i, got, want)
+ }
+ }
+}
+
func myLoggedFunc() {
f := vlog.LogCall("entry")
f("exit")
@@ -112,7 +149,7 @@
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
- logCallLineRE := regexp.MustCompile(`\S+ \S+ \S+ ([^:]*):.*(call|return)\[(\S*)`)
+ logCallLineRE := regexp.MustCompile(`\S+ \S+\s+\S+ ([^:]*):.*(call|return)\[(\S*)`)
for _, line := range contents {
match := logCallLineRE.FindStringSubmatch(line)
if len(match) != 4 {
@@ -176,6 +213,54 @@
if vlog.VI(3) == vlog.Log {
t.Errorf("vlog.V(3) should not be vlog.Log")
}
+ spec = vlog.ModuleSpec{}
+ spec.Set("notlikelytobeinuse=2")
+ vlog.Log.Configure(vlog.OverridePriorConfiguration(true), spec)
+}
+
+func TestVFilepath(t *testing.T) {
+ dir, err := ioutil.TempDir("", "logtest")
+ defer os.RemoveAll(dir)
+ if err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ logger := vlog.NewLogger("testVmodule")
+ logger.Configure(vlog.LogDir(dir))
+ if logger.V(2) || logger.V(3) {
+ t.Errorf("Logging should not be enabled at levels 2 & 3")
+ }
+ spec := vlog.FilepathSpec{}
+ if err := spec.Set(".*log_test=2"); err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if err := logger.Configure(vlog.OverridePriorConfiguration(true), spec); err != nil {
+ t.Fatalf("unexpected error: %v", err)
+ }
+ if !logger.V(2) {
+ t.Errorf("logger.V(2) should be true")
+ }
+ if logger.V(3) {
+ t.Errorf("logger.V(3) should be false")
+ }
+ if vlog.V(2) || vlog.V(3) {
+ t.Errorf("Logging should not be enabled at levels 2 & 3")
+ }
+ vlog.Log.Configure(vlog.OverridePriorConfiguration(true), spec)
+ if !vlog.V(2) {
+ t.Errorf("vlog.V(2) should be true")
+ }
+ if vlog.V(3) {
+ t.Errorf("vlog.V(3) should be false")
+ }
+ if vlog.VI(2) != vlog.Log {
+ t.Errorf("vlog.V(2) should be vlog.Log")
+ }
+ if vlog.VI(3) == vlog.Log {
+ t.Errorf("vlog.V(3) should not be vlog.Log")
+ }
+ spec = vlog.FilepathSpec{}
+ spec.Set("notlikelytobeinuse=2")
+ vlog.Log.Configure(vlog.OverridePriorConfiguration(true), spec)
}
func TestConfigure(t *testing.T) {
@@ -188,7 +273,7 @@
if got, want := logger.Configure(vlog.LogDir(dir), vlog.AlsoLogToStderr(false)), error(nil); got != want {
t.Fatalf("got %v, want %v", got, want)
}
- if got, want := logger.Configure(vlog.AlsoLogToStderr(true)), vlog.Configured; got != want {
+ if got, want := logger.Configure(vlog.AlsoLogToStderr(true)), vlog.ErrConfigured; got != want {
t.Fatalf("got %v, want %v", got, want)
}
if got, want := logger.Configure(vlog.OverridePriorConfiguration(true), vlog.AlsoLogToStderr(false)), error(nil); got != want {
diff --git a/vlog/logcall.go b/vlog/logcall.go
index b63e94c..f163a39 100644
--- a/vlog/logcall.go
+++ b/vlog/logcall.go
@@ -11,7 +11,7 @@
"runtime"
"sync/atomic"
- "github.com/cosmosnicolaou/llog"
+ "github.com/cosnicolaou/llog"
)
// logCallLogLevel is the log level beyond which calls are logged.
diff --git a/vlog/model.go b/vlog/model.go
index 852f52c..ed00124 100644
--- a/vlog/model.go
+++ b/vlog/model.go
@@ -7,7 +7,7 @@
import (
// TODO(cnicolaou): remove this dependency in the future. For now this
// saves us some code.
- "github.com/cosmosnicolaou/llog"
+ "github.com/cosnicolaou/llog"
)
type InfoLog interface {
@@ -19,6 +19,14 @@
// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
Infof(format string, args ...interface{})
+ // InfoDepth acts as Info but uses depth to determine which call frame to log.
+ // A depth of 0 is equivalent to calling Info.
+ InfoDepth(depth int, args ...interface{})
+
+ // InfofDepth acts as Infof but uses depth to determine which call frame to log.
+ // A depth of 0 is equivalent to calling Infof.
+ InfofDepth(depth int, format string, args ...interface{})
+
// InfoStack logs the current goroutine's stack if the all parameter
// is false, or the stacks of all goroutines if it's true.
InfoStack(all bool)
@@ -83,6 +91,14 @@
llog.ModuleSpec
}
+// FilepathSpec allows for the setting of specific log levels for specific
+// files matched by a regular expression. The syntax is <re>=3,<re1>=2.
+// It can be set via the FilepathSpec optional parameter to Configure.
+// It implements the flag.Value interface to support command line option parsing.
+type FilepathSpec struct {
+ llog.FilepathSpec
+}
+
// TraceLocation specifies the location, file:N, which when encountered will
// cause logging to emit a stack trace.
// It can be set via the TraceLocation optional parameter to Configure.
@@ -106,6 +122,10 @@
// Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
Error(args ...interface{})
+ // ErrorDepth acts as Error but uses depth to determine which call frame to log.
+ // A depth of 0 is equivalent to calling Error.
+ ErrorDepth(depth int, args ...interface{})
+
// Errorf logs to the ERROR and INFO logs.
// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
Errorf(format string, args ...interface{})
@@ -115,6 +135,10 @@
// Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
Fatal(args ...interface{})
+ // FatalDepth acts as Fatal but uses depth to determine which call frame to log.
+ // A depth of 0 is equivalent to calling Fatal.
+ FatalDepth(depth int, args ...interface{})
+
// Fatalf logs to the FATAL, ERROR and INFO logs,
// including a stack trace of all running goroutines, then calls os.Exit(255).
// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
@@ -123,6 +147,10 @@
// Panic is equivalent to Error() followed by a call to panic().
Panic(args ...interface{})
+ // PanicDepth acts as Panic but uses depth to determine which call frame to log.
+ // A depth of 0 is equivalent to calling Panic.
+ PanicDepth(depth int, args ...interface{})
+
// Panicf is equivalent to Errorf() followed by a call to panic().
Panicf(format string, args ...interface{})
diff --git a/vlog/opts.go b/vlog/opts.go
index 9e6000d..4d7328b 100644
--- a/vlog/opts.go
+++ b/vlog/opts.go
@@ -37,11 +37,16 @@
// The syntax of the argument is a comma-separated list of pattern=N,
// where pattern is a literal file name (minus the ".go" suffix) or
-// "glob" pattern and N is a V level. For instance,
-// -gopher*=3
+// "glob" pattern and N is a V level. For instance, gopher*=3
// sets the V level to 3 in all Go files whose names begin "gopher".
func (_ ModuleSpec) LoggingOpt() {}
+// The syntax of the argument is a comma-separated list of regexp=N,
+// where pattern is a regular expression matched against the full path name
+// of files and N is a V level. For instance, myco.com/web/.*=3
+// sets the V level to 3 in all Go files whose path names match myco.com/web/.*".
+func (_ FilepathSpec) LoggingOpt() {}
+
// Log events at or above this severity are logged to standard
// error as well as to files.
func (_ StderrThreshold) LoggingOpt() {}