fs: Implement fs.Trace for tracing entry and exit of functions

This commit is contained in:
Nick Craig-Wood 2017-05-09 11:38:58 +01:00
parent abda616f84
commit 50e79bc087

View file

@ -6,6 +6,9 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"reflect"
"runtime"
"strings"
) )
// LogLevel describes rclone's logs. These are a subset of the syslog log levels. // LogLevel describes rclone's logs. These are a subset of the syslog log levels.
@ -110,6 +113,50 @@ func Debugf(o interface{}, text string, args ...interface{}) {
} }
} }
// fnName returns the name of the calling +2 function
func fnName() string {
pc, _, _, ok := runtime.Caller(2)
name := "*Unknown*"
if ok {
name = runtime.FuncForPC(pc).Name()
dot := strings.LastIndex(name, ".")
if dot >= 0 {
name = name[dot+1:]
}
}
return name
}
// Trace debugs the entry and exit of the calling function
//
// It is designed to be used in a defer statement so it returns a
// function that logs the exit parameters.
//
// Any pointers in the exit function will be dereferenced
func Trace(o interface{}, format string, a ...interface{}) func(string, ...interface{}) {
if Config.LogLevel < LogLevelDebug {
return func(format string, a ...interface{}) {}
}
name := fnName()
logPrintf(LogLevelDebug, o, name+": "+format, a...)
return func(format string, a ...interface{}) {
for i := range a {
// read the values of the pointed to items
typ := reflect.TypeOf(a[i])
if typ.Kind() == reflect.Ptr {
value := reflect.ValueOf(a[i])
if value.IsNil() {
a[i] = nil
} else {
pointedToValue := reflect.Indirect(value)
a[i] = pointedToValue.Interface()
}
}
}
logPrintf(LogLevelDebug, o, ">"+name+": "+format, a...)
}
}
// InitLogging start the logging as per the command line flags // InitLogging start the logging as per the command line flags
func InitLogging() { func InitLogging() {
// Log file output // Log file output