mirror of
https://github.com/rclone/rclone.git
synced 2026-01-06 10:33:34 +00:00
Break the fs package up into smaller parts.
The purpose of this is to make it easier to maintain and eventually to allow the rclone backends to be re-used in other projects without having to use the rclone configuration system. The new code layout is documented in CONTRIBUTING.
This commit is contained in:
89
fs/log/log.go
Normal file
89
fs/log/log.go
Normal file
@@ -0,0 +1,89 @@
|
||||
// Package log provides logging for rclone
|
||||
package log
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/ncw/rclone/fs"
|
||||
"github.com/ncw/rclone/fs/config/flags"
|
||||
)
|
||||
|
||||
// Flags
|
||||
var (
|
||||
logFile = flags.StringP("log-file", "", "", "Log everything to this file")
|
||||
useSyslog = flags.BoolP("syslog", "", false, "Use Syslog for logging")
|
||||
syslogFacility = flags.StringP("syslog-facility", "", "DAEMON", "Facility for syslog, eg KERN,USER,...")
|
||||
)
|
||||
|
||||
// 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 fs.Config.LogLevel < fs.LogLevelDebug {
|
||||
return func(format string, a ...interface{}) {}
|
||||
}
|
||||
name := fnName()
|
||||
fs.LogPrintf(fs.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()
|
||||
}
|
||||
}
|
||||
}
|
||||
fs.LogPrintf(fs.LogLevelDebug, o, ">"+name+": "+format, a...)
|
||||
}
|
||||
}
|
||||
|
||||
// InitLogging start the logging as per the command line flags
|
||||
func InitLogging() {
|
||||
// Log file output
|
||||
if *logFile != "" {
|
||||
f, err := os.OpenFile(*logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to open log file: %v", err)
|
||||
}
|
||||
_, err = f.Seek(0, os.SEEK_END)
|
||||
if err != nil {
|
||||
fs.Errorf(nil, "Failed to seek log file to end: %v", err)
|
||||
}
|
||||
log.SetOutput(f)
|
||||
redirectStderr(f)
|
||||
}
|
||||
|
||||
// Syslog output
|
||||
if *useSyslog {
|
||||
if *logFile != "" {
|
||||
log.Fatalf("Can't use --syslog and --log-file together")
|
||||
}
|
||||
startSysLog()
|
||||
}
|
||||
}
|
||||
16
fs/log/redirect_stderr.go
Normal file
16
fs/log/redirect_stderr.go
Normal file
@@ -0,0 +1,16 @@
|
||||
// Log the panic to the log file - for oses which can't do this
|
||||
|
||||
// +build !windows,!darwin,!dragonfly,!freebsd,!linux,!nacl,!netbsd,!openbsd
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/ncw/rclone/fs"
|
||||
)
|
||||
|
||||
// redirectStderr to the file passed in
|
||||
func redirectStderr(f *os.File) {
|
||||
fs.Errorf(nil, "Can't redirect stderr to file")
|
||||
}
|
||||
20
fs/log/redirect_stderr_unix.go
Normal file
20
fs/log/redirect_stderr_unix.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Log the panic under unix to the log file
|
||||
|
||||
// +build !windows,!solaris,!plan9
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// redirectStderr to the file passed in
|
||||
func redirectStderr(f *os.File) {
|
||||
err := unix.Dup2(int(f.Fd()), int(os.Stderr.Fd()))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to redirect stderr to file: %v", err)
|
||||
}
|
||||
}
|
||||
39
fs/log/redirect_stderr_windows.go
Normal file
39
fs/log/redirect_stderr_windows.go
Normal file
@@ -0,0 +1,39 @@
|
||||
// Log the panic under windows to the log file
|
||||
//
|
||||
// Code from minix, via
|
||||
//
|
||||
// https://play.golang.org/p/kLtct7lSUg
|
||||
|
||||
// +build windows
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
kernel32 = syscall.MustLoadDLL("kernel32.dll")
|
||||
procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
|
||||
)
|
||||
|
||||
func setStdHandle(stdhandle int32, handle syscall.Handle) error {
|
||||
r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
|
||||
if r0 == 0 {
|
||||
if e1 != 0 {
|
||||
return error(e1)
|
||||
}
|
||||
return syscall.EINVAL
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// redirectStderr to the file passed in
|
||||
func redirectStderr(f *os.File) {
|
||||
err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to redirect stderr to file: %v", err)
|
||||
}
|
||||
}
|
||||
16
fs/log/syslog.go
Normal file
16
fs/log/syslog.go
Normal file
@@ -0,0 +1,16 @@
|
||||
// Syslog interface for non-Unix variants only
|
||||
|
||||
// +build windows nacl plan9
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"log"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// Starts syslog if configured, returns true if it was started
|
||||
func startSysLog() bool {
|
||||
log.Fatalf("--syslog not supported on %s platform", runtime.GOOS)
|
||||
return false
|
||||
}
|
||||
67
fs/log/syslog_unix.go
Normal file
67
fs/log/syslog_unix.go
Normal file
@@ -0,0 +1,67 @@
|
||||
// Syslog interface for Unix variants only
|
||||
|
||||
// +build !windows,!nacl,!plan9
|
||||
|
||||
package log
|
||||
|
||||
import (
|
||||
"log"
|
||||
"log/syslog"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/ncw/rclone/fs"
|
||||
)
|
||||
|
||||
var (
|
||||
syslogFacilityMap = map[string]syslog.Priority{
|
||||
"KERN": syslog.LOG_KERN,
|
||||
"USER": syslog.LOG_USER,
|
||||
"MAIL": syslog.LOG_MAIL,
|
||||
"DAEMON": syslog.LOG_DAEMON,
|
||||
"AUTH": syslog.LOG_AUTH,
|
||||
"SYSLOG": syslog.LOG_SYSLOG,
|
||||
"LPR": syslog.LOG_LPR,
|
||||
"NEWS": syslog.LOG_NEWS,
|
||||
"UUCP": syslog.LOG_UUCP,
|
||||
"CRON": syslog.LOG_CRON,
|
||||
"AUTHPRIV": syslog.LOG_AUTHPRIV,
|
||||
"FTP": syslog.LOG_FTP,
|
||||
}
|
||||
)
|
||||
|
||||
// Starts syslog
|
||||
func startSysLog() bool {
|
||||
facility, ok := syslogFacilityMap[*syslogFacility]
|
||||
if !ok {
|
||||
log.Fatalf("Unknown syslog facility %q - man syslog for list", *syslogFacility)
|
||||
}
|
||||
Me := path.Base(os.Args[0])
|
||||
w, err := syslog.New(syslog.LOG_NOTICE|facility, Me)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to start syslog: %v", err)
|
||||
}
|
||||
log.SetFlags(0)
|
||||
log.SetOutput(w)
|
||||
fs.LogPrint = func(level fs.LogLevel, text string) {
|
||||
switch level {
|
||||
case fs.LogLevelEmergency:
|
||||
_ = w.Emerg(text)
|
||||
case fs.LogLevelAlert:
|
||||
_ = w.Alert(text)
|
||||
case fs.LogLevelCritical:
|
||||
_ = w.Crit(text)
|
||||
case fs.LogLevelError:
|
||||
_ = w.Err(text)
|
||||
case fs.LogLevelWarning:
|
||||
_ = w.Warning(text)
|
||||
case fs.LogLevelNotice:
|
||||
_ = w.Notice(text)
|
||||
case fs.LogLevelInfo:
|
||||
_ = w.Info(text)
|
||||
case fs.LogLevelDebug:
|
||||
_ = w.Debug(text)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user