From 8b8c933eb22aceec164ad98ea536fa6d419feb95 Mon Sep 17 00:00:00 2001 From: "infi.he" Date: Sun, 20 May 2018 18:18:14 +0800 Subject: [PATCH] Support log file can be rotated hourly. --- .gitignore | 1 + config.go | 6 +- filelog.go | 47 +++- log4go.go | 571 +++++++++++++++++++++++++------------------------ log4go_test.go | 15 +- wrapper.go | 2 +- 6 files changed, 352 insertions(+), 290 deletions(-) diff --git a/.gitignore b/.gitignore index f6207cd..1d3d262 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.sw[op] .DS_Store +.idea/ \ No newline at end of file diff --git a/config.go b/config.go index 4e90f8f..5eec44f 100644 --- a/config.go +++ b/config.go @@ -127,7 +127,7 @@ func (log Logger) LoadConfiguration(filename string) { continue } - log[xmlfilt.Tag] = &Filter{lvl, filt} + log[xmlfilt.Tag] = &Filter{lvl, filt, xmlfilt.Tag} } } @@ -180,6 +180,7 @@ func xmlToFileLogWriter(filename string, props []xmlProperty, enabled bool) (*Fi format := "[%D %T] [%L] (%S) %M" maxlines := 0 maxsize := 0 + hourly := false daily := false rotate := false @@ -194,6 +195,8 @@ func xmlToFileLogWriter(filename string, props []xmlProperty, enabled bool) (*Fi maxlines = strToNumSuffix(strings.Trim(prop.Value, " \r\n"), 1000) case "maxsize": maxsize = strToNumSuffix(strings.Trim(prop.Value, " \r\n"), 1024) + case "hourly": + hourly = strings.Trim(prop.Value, " \r\n") != "false" case "daily": daily = strings.Trim(prop.Value, " \r\n") != "false" case "rotate": @@ -218,6 +221,7 @@ func xmlToFileLogWriter(filename string, props []xmlProperty, enabled bool) (*Fi flw.SetFormat(format) flw.SetRotateLines(maxlines) flw.SetRotateSize(maxsize) + flw.SetRotateHourly(hourly) flw.SetRotateDaily(daily) return flw, true } diff --git a/filelog.go b/filelog.go index adbc1f7..cceae04 100644 --- a/filelog.go +++ b/filelog.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "time" + "strings" ) // This log writer sends output to a file @@ -35,6 +36,10 @@ type FileLogWriter struct { daily bool daily_opendate int + // Rotate hourly + hourly bool + hourly_opendate int + // Keep old logfiles (.001, .002, etc) rotate bool maxbackup int @@ -97,7 +102,8 @@ func NewFileLogWriter(fname string, rotate bool) *FileLogWriter { now := time.Now() if (w.maxlines > 0 && w.maxlines_curlines >= w.maxlines) || (w.maxsize > 0 && w.maxsize_cursize >= w.maxsize) || - (w.daily && now.Day() != w.daily_opendate) { + (w.hourly && now.Hour() != w.hourly_opendate) || + (w.daily && now.Day() != w.daily_opendate) { if err := w.intRotate(); err != nil { fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err) return @@ -135,17 +141,19 @@ func (w *FileLogWriter) intRotate() error { } // If we are keeping log files, move it to the next available number + fileName := getActualPathReplacePattern(w.filename) if w.rotate { - _, err := os.Lstat(w.filename) + _, err := os.Lstat(fileName) if err == nil { // file exists // Find the next available number num := 1 fname := "" + //cutting by daily if w.daily && time.Now().Day() != w.daily_opendate { yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02") for ; err == nil && num <= w.maxbackup; num++ { - fname = w.filename + fmt.Sprintf(".%s.%03d", yesterday, num) + fname = fileName + fmt.Sprintf(".%s.%03d", yesterday, num) _, err = os.Lstat(fname) } // return error if the last file checked still existed @@ -155,8 +163,8 @@ func (w *FileLogWriter) intRotate() error { } else { num = w.maxbackup - 1 for ; num >= 1; num-- { - fname = w.filename + fmt.Sprintf(".%d", num) - nfname := w.filename + fmt.Sprintf(".%d", num+1) + fname = fileName + fmt.Sprintf(".%d", num) + nfname := fileName + fmt.Sprintf(".%d", num+1) _, err = os.Lstat(fname) if err == nil { os.Rename(fname, nfname) @@ -166,7 +174,7 @@ func (w *FileLogWriter) intRotate() error { w.file.Close() // Rename the file to its newfound home - err = os.Rename(w.filename, fname) + err = os.Rename(fileName, fname) if err != nil { return fmt.Errorf("Rotate: %s\n", err) } @@ -174,7 +182,7 @@ func (w *FileLogWriter) intRotate() error { } // Open the log file - fd, err := os.OpenFile(w.filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660) + fd, err := os.OpenFile(fileName, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660) if err != nil { return err } @@ -185,6 +193,7 @@ func (w *FileLogWriter) intRotate() error { // Set the daily open date to the current date w.daily_opendate = now.Day() + w.hourly_opendate = now.Hour() // initialize rotation values w.maxlines_curlines = 0 @@ -227,6 +236,13 @@ func (w *FileLogWriter) SetRotateSize(maxsize int) *FileLogWriter { return w } +// Set rotate hourly (chainable). Must be called before the first log message is +// written. +func (w *FileLogWriter) SetRotateHourly(hourly bool) *FileLogWriter { + w.hourly = hourly + return w +} + // Set rotate daily (chainable). Must be called before the first log message is // written. func (w *FileLogWriter) SetRotateDaily(daily bool) *FileLogWriter { @@ -262,3 +278,20 @@ func NewXMLLogWriter(fname string, rotate bool) *FileLogWriter { %M `).SetHeadFoot("", "") } + + +func getActualPathReplacePattern(pattern string) string { + now := time.Now() + Y := fmt.Sprintf("%d",now.Year()) + M := fmt.Sprintf("%02d",now.Month()) + D := fmt.Sprintf("%02d",now.Day()) + H := fmt.Sprintf("%02d",now.Hour()) + m := fmt.Sprintf("%02d",now.Minute()) + + pattern = strings.Replace(pattern, "%Y", Y, -1) + pattern = strings.Replace(pattern, "%M", M, -1) + pattern = strings.Replace(pattern, "%D", D, -1) + pattern = strings.Replace(pattern, "%H", H, -1) + pattern = strings.Replace(pattern, "%m", m, -1) + return pattern +} \ No newline at end of file diff --git a/log4go.go b/log4go.go index 822e890..d7d04d1 100644 --- a/log4go.go +++ b/log4go.go @@ -46,20 +46,20 @@ package log4go import ( - "errors" - "fmt" - "os" - "runtime" - "strings" - "time" + "errors" + "fmt" + "os" + "runtime" + "strings" + "time" ) // Version information const ( - L4G_VERSION = "log4go-v3.0.1" - L4G_MAJOR = 3 - L4G_MINOR = 0 - L4G_BUILD = 1 + L4G_VERSION = "log4go-v3.0.1" + L4G_MAJOR = 3 + L4G_MINOR = 0 + L4G_BUILD = 1 ) /****** Constants ******/ @@ -68,55 +68,55 @@ const ( type Level int const ( - FINEST Level = iota - FINE - DEBUG - TRACE - INFO - WARNING - ERROR - CRITICAL + FINEST Level = iota + FINE + DEBUG + TRACE + INFO + WARNING + ERROR + CRITICAL ) // Logging level strings var ( - levelStrings = [...]string{"FNST", "FINE", "DEBG", "TRAC", "INFO", "WARN", "EROR", "CRIT"} + levelStrings = [...]string{"FNST", "FINE", "DEBG", "TRAC", "INFO", "WARN", "EROR", "CRIT"} ) func (l Level) String() string { - if l < 0 || int(l) > len(levelStrings) { - return "UNKNOWN" - } - return levelStrings[int(l)] + if l < 0 || int(l) > len(levelStrings) { + return "UNKNOWN" + } + return levelStrings[int(l)] } /****** Variables ******/ var ( - // LogBufferLength specifies how many log messages a particular log4go - // logger can buffer at a time before writing them. - LogBufferLength = 32 + // LogBufferLength specifies how many log messages a particular log4go + // logger can buffer at a time before writing them. + LogBufferLength = 32 ) /****** LogRecord ******/ // A LogRecord contains all of the pertinent information for each message type LogRecord struct { - Level Level // The log level - Created time.Time // The time at which the log message was created (nanoseconds) - Source string // The message source - Message string // The log message + Level Level // The log level + Created time.Time // The time at which the log message was created (nanoseconds) + Source string // The message source + Message string // The log message } /****** LogWriter ******/ // This is an interface for anything that should be able to write logs type LogWriter interface { - // This will be called to log a LogRecord message. - LogWrite(rec *LogRecord) + // This will be called to log a LogRecord message. + LogWrite(rec *LogRecord) - // This should clean up anything lingering about the LogWriter, as it is called before - // the LogWriter is removed. LogWrite should not be called after Close. - Close() + // This should clean up anything lingering about the LogWriter, as it is called before + // the LogWriter is removed. LogWrite should not be called after Close. + Close() } /****** Logger ******/ @@ -124,8 +124,9 @@ type LogWriter interface { // A Filter represents the log level below which no log records are written to // the associated LogWriter. type Filter struct { - Level Level - LogWriter + Level Level + LogWriter LogWriter + Tag string } // A Logger represents a collection of Filters through which log messages are @@ -136,8 +137,8 @@ type Logger map[string]*Filter // // DEPRECATED: Use make(Logger) instead. func NewLogger() Logger { - os.Stderr.WriteString("warning: use of deprecated NewLogger\n") - return make(Logger) + os.Stderr.WriteString("warning: use of deprecated NewLogger\n") + return make(Logger) } // Create a new logger with a "stdout" filter configured to send log messages at @@ -145,18 +146,18 @@ func NewLogger() Logger { // // DEPRECATED: use NewDefaultLogger instead. func NewConsoleLogger(lvl Level) Logger { - os.Stderr.WriteString("warning: use of deprecated NewConsoleLogger\n") - return Logger{ - "stdout": &Filter{lvl, NewConsoleLogWriter()}, - } + os.Stderr.WriteString("warning: use of deprecated NewConsoleLogger\n") + return Logger{ + "stdout": &Filter{Level: lvl, LogWriter: NewConsoleLogWriter()}, + } } // Create a new logger with a "stdout" filter configured to send log messages at // or above lvl to standard output. func NewDefaultLogger(lvl Level) Logger { - return Logger{ - "stdout": &Filter{lvl, NewConsoleLogWriter()}, - } + return Logger{ + "stdout": &Filter{Level: lvl, LogWriter: NewConsoleLogWriter()}, + } } // Closes all log writers in preparation for exiting the program or a @@ -164,185 +165,197 @@ func NewDefaultLogger(lvl Level) Logger { // you want to guarantee that all log messages are written. Close removes // all filters (and thus all LogWriters) from the logger. func (log Logger) Close() { - // Close all open loggers - for name, filt := range log { - filt.Close() - delete(log, name) - } + // Close all open loggers + for name, filt := range log { + filt.LogWriter.Close() + delete(log, name) + } } // Add a new LogWriter to the Logger which will only log messages at lvl or // higher. This function should not be called from multiple goroutines. // Returns the logger for chaining. func (log Logger) AddFilter(name string, lvl Level, writer LogWriter) Logger { - log[name] = &Filter{lvl, writer} - return log + log[name] = &Filter{Level: lvl, LogWriter: NewConsoleLogWriter()} + return log } /******* Logging *******/ // Send a formatted log message internally func (log Logger) intLogf(lvl Level, format string, args ...interface{}) { - skip := true - - // Determine if any logging will be done - for _, filt := range log { - if lvl >= filt.Level { - skip = false - break - } - } - if skip { - return - } - - // Determine caller func - pc, _, lineno, ok := runtime.Caller(2) - src := "" - if ok { - src = fmt.Sprintf("%s:%d", runtime.FuncForPC(pc).Name(), lineno) - } - - msg := format - if len(args) > 0 { - msg = fmt.Sprintf(format, args...) - } - - // Make the log record - rec := &LogRecord{ - Level: lvl, - Created: time.Now(), - Source: src, - Message: msg, - } - - // Dispatch the logs - for _, filt := range log { - if lvl < filt.Level { - continue - } - filt.LogWrite(rec) - } + skip := true + + // Determine if any logging will be done + for _, filt := range log { + if lvl >= filt.Level { + skip = false + break + } + } + if skip { + return + } + + // Determine caller func + pc, _, lineno, ok := runtime.Caller(2) + src := "" + if ok { + src = fmt.Sprintf("%s:%d", runtime.FuncForPC(pc).Name(), lineno) + } + + msg := format + if len(args) > 0 { + msg = fmt.Sprintf(format, args...) + } + + // Make the log record + rec := &LogRecord{ + Level: lvl, + Created: time.Now(), + Source: src, + Message: msg, + } + pac := strings.Split(src, ":")[0] + + // Dispatch the logs + for _, filt := range log { + if lvl < filt.Level { + continue + } + skip1 := false + tags := strings.Split(filt.Tag, ",") + for _, tag := range tags { + if strings.Contains(pac, tag) { + skip1 = true + break + } + } + if skip1 { + filt.LogWriter.LogWrite(rec) + } + + } } // Send a closure log message internally func (log Logger) intLogc(lvl Level, closure func() string) { - skip := true - - // Determine if any logging will be done - for _, filt := range log { - if lvl >= filt.Level { - skip = false - break - } - } - if skip { - return - } - - // Determine caller func - pc, _, lineno, ok := runtime.Caller(2) - src := "" - if ok { - src = fmt.Sprintf("%s:%d", runtime.FuncForPC(pc).Name(), lineno) - } - - // Make the log record - rec := &LogRecord{ - Level: lvl, - Created: time.Now(), - Source: src, - Message: closure(), - } - - // Dispatch the logs - for _, filt := range log { - if lvl < filt.Level { - continue - } - filt.LogWrite(rec) - } + skip := true + + // Determine if any logging will be done + for _, filt := range log { + if lvl >= filt.Level { + skip = false + break + } + } + if skip { + return + } + + // Determine caller func + pc, _, lineno, ok := runtime.Caller(2) + src := "" + if ok { + src = fmt.Sprintf("%s:%d", runtime.FuncForPC(pc).Name(), lineno) + } + + // Make the log record + rec := &LogRecord{ + Level: lvl, + Created: time.Now(), + Source: src, + Message: closure(), + } + + // Dispatch the logs + for _, filt := range log { + if lvl < filt.Level { + continue + } + filt.LogWriter.LogWrite(rec) + } } // Send a log message with manual level, source, and message. func (log Logger) Log(lvl Level, source, message string) { - skip := true - - // Determine if any logging will be done - for _, filt := range log { - if lvl >= filt.Level { - skip = false - break - } - } - if skip { - return - } - - // Make the log record - rec := &LogRecord{ - Level: lvl, - Created: time.Now(), - Source: source, - Message: message, - } - - // Dispatch the logs - for _, filt := range log { - if lvl < filt.Level { - continue - } - filt.LogWrite(rec) - } + skip := true + + // Determine if any logging will be done + for _, filt := range log { + if lvl >= filt.Level { + skip = false + break + } + } + if skip { + return + } + + // Make the log record + rec := &LogRecord{ + Level: lvl, + Created: time.Now(), + Source: source, + Message: message, + } + + // Dispatch the logs + for _, filt := range log { + if lvl < filt.Level { + continue + } + filt.LogWriter.LogWrite(rec) + } } // Logf logs a formatted log message at the given log level, using the caller as // its source. func (log Logger) Logf(lvl Level, format string, args ...interface{}) { - log.intLogf(lvl, format, args...) + log.intLogf(lvl, format, args...) } // Logc logs a string returned by the closure at the given log level, using the caller as // its source. If no log message would be written, the closure is never called. func (log Logger) Logc(lvl Level, closure func() string) { - log.intLogc(lvl, closure) + log.intLogc(lvl, closure) } // Finest logs a message at the finest log level. // See Debug for an explanation of the arguments. func (log Logger) Finest(arg0 interface{}, args ...interface{}) { - const ( - lvl = FINEST - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - log.intLogf(lvl, first, args...) - case func() string: - // Log the closure (no other arguments used) - log.intLogc(lvl, first) - default: - // Build a format string so that it will be similar to Sprint - log.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) - } + const ( + lvl = FINEST + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + log.intLogf(lvl, first, args...) + case func() string: + // Log the closure (no other arguments used) + log.intLogc(lvl, first) + default: + // Build a format string so that it will be similar to Sprint + log.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) + } } // Fine logs a message at the fine log level. // See Debug for an explanation of the arguments. func (log Logger) Fine(arg0 interface{}, args ...interface{}) { - const ( - lvl = FINE - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - log.intLogf(lvl, first, args...) - case func() string: - // Log the closure (no other arguments used) - log.intLogc(lvl, first) - default: - // Build a format string so that it will be similar to Sprint - log.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) - } + const ( + lvl = FINE + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + log.intLogf(lvl, first, args...) + case func() string: + // Log the closure (no other arguments used) + log.intLogc(lvl, first) + default: + // Build a format string so that it will be similar to Sprint + log.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) + } } // Debug is a utility method for debug log messages. @@ -358,58 +371,58 @@ func (log Logger) Fine(arg0 interface{}, args ...interface{}) { // When given anything else, the log message will be each of the arguments // formatted with %v and separated by spaces (ala Sprint). func (log Logger) Debug(arg0 interface{}, args ...interface{}) { - const ( - lvl = DEBUG - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - log.intLogf(lvl, first, args...) - case func() string: - // Log the closure (no other arguments used) - log.intLogc(lvl, first) - default: - // Build a format string so that it will be similar to Sprint - log.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) - } + const ( + lvl = DEBUG + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + log.intLogf(lvl, first, args...) + case func() string: + // Log the closure (no other arguments used) + log.intLogc(lvl, first) + default: + // Build a format string so that it will be similar to Sprint + log.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) + } } // Trace logs a message at the trace log level. // See Debug for an explanation of the arguments. func (log Logger) Trace(arg0 interface{}, args ...interface{}) { - const ( - lvl = TRACE - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - log.intLogf(lvl, first, args...) - case func() string: - // Log the closure (no other arguments used) - log.intLogc(lvl, first) - default: - // Build a format string so that it will be similar to Sprint - log.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) - } + const ( + lvl = TRACE + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + log.intLogf(lvl, first, args...) + case func() string: + // Log the closure (no other arguments used) + log.intLogc(lvl, first) + default: + // Build a format string so that it will be similar to Sprint + log.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) + } } // Info logs a message at the info log level. // See Debug for an explanation of the arguments. func (log Logger) Info(arg0 interface{}, args ...interface{}) { - const ( - lvl = INFO - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - log.intLogf(lvl, first, args...) - case func() string: - // Log the closure (no other arguments used) - log.intLogc(lvl, first) - default: - // Build a format string so that it will be similar to Sprint - log.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) - } + const ( + lvl = INFO + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + log.intLogf(lvl, first, args...) + case func() string: + // Log the closure (no other arguments used) + log.intLogc(lvl, first) + default: + // Build a format string so that it will be similar to Sprint + log.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) + } } // Warn logs a message at the warning log level and returns the formatted error. @@ -418,67 +431,67 @@ func (log Logger) Info(arg0 interface{}, args ...interface{}) { // closures are executed to format the error message. // See Debug for further explanation of the arguments. func (log Logger) Warn(arg0 interface{}, args ...interface{}) error { - const ( - lvl = WARNING - ) - var msg string - switch first := arg0.(type) { - case string: - // Use the string as a format string - msg = fmt.Sprintf(first, args...) - case func() string: - // Log the closure (no other arguments used) - msg = first() - default: - // Build a format string so that it will be similar to Sprint - msg = fmt.Sprintf(fmt.Sprint(first)+strings.Repeat(" %v", len(args)), args...) - } - log.intLogf(lvl, msg) - return errors.New(msg) + const ( + lvl = WARNING + ) + var msg string + switch first := arg0.(type) { + case string: + // Use the string as a format string + msg = fmt.Sprintf(first, args...) + case func() string: + // Log the closure (no other arguments used) + msg = first() + default: + // Build a format string so that it will be similar to Sprint + msg = fmt.Sprintf(fmt.Sprint(first)+strings.Repeat(" %v", len(args)), args...) + } + log.intLogf(lvl, msg) + return errors.New(msg) } // Error logs a message at the error log level and returns the formatted error, // See Warn for an explanation of the performance and Debug for an explanation // of the parameters. func (log Logger) Error(arg0 interface{}, args ...interface{}) error { - const ( - lvl = ERROR - ) - var msg string - switch first := arg0.(type) { - case string: - // Use the string as a format string - msg = fmt.Sprintf(first, args...) - case func() string: - // Log the closure (no other arguments used) - msg = first() - default: - // Build a format string so that it will be similar to Sprint - msg = fmt.Sprintf(fmt.Sprint(first)+strings.Repeat(" %v", len(args)), args...) - } - log.intLogf(lvl, msg) - return errors.New(msg) + const ( + lvl = ERROR + ) + var msg string + switch first := arg0.(type) { + case string: + // Use the string as a format string + msg = fmt.Sprintf(first, args...) + case func() string: + // Log the closure (no other arguments used) + msg = first() + default: + // Build a format string so that it will be similar to Sprint + msg = fmt.Sprintf(fmt.Sprint(first)+strings.Repeat(" %v", len(args)), args...) + } + log.intLogf(lvl, msg) + return errors.New(msg) } // Critical logs a message at the critical log level and returns the formatted error, // See Warn for an explanation of the performance and Debug for an explanation // of the parameters. func (log Logger) Critical(arg0 interface{}, args ...interface{}) error { - const ( - lvl = CRITICAL - ) - var msg string - switch first := arg0.(type) { - case string: - // Use the string as a format string - msg = fmt.Sprintf(first, args...) - case func() string: - // Log the closure (no other arguments used) - msg = first() - default: - // Build a format string so that it will be similar to Sprint - msg = fmt.Sprintf(fmt.Sprint(first)+strings.Repeat(" %v", len(args)), args...) - } - log.intLogf(lvl, msg) - return errors.New(msg) + const ( + lvl = CRITICAL + ) + var msg string + switch first := arg0.(type) { + case string: + // Use the string as a format string + msg = fmt.Sprintf(first, args...) + case func() string: + // Log the closure (no other arguments used) + msg = first() + default: + // Build a format string so that it will be similar to Sprint + msg = fmt.Sprintf(fmt.Sprint(first)+strings.Repeat(" %v", len(args)), args...) + } + log.intLogf(lvl, msg) + return errors.New(msg) } diff --git a/log4go_test.go b/log4go_test.go index c4b92f6..9a9f346 100644 --- a/log4go_test.go +++ b/log4go_test.go @@ -94,7 +94,7 @@ var logRecordWriteTests = []struct { } func TestConsoleLogWriter(t *testing.T) { - console := make(ConsoleLogWriter) + console := &ConsoleLogWriter{} r, w := io.Pipe() go console.run(w) @@ -301,6 +301,17 @@ func TestCountMallocs(t *testing.T) { fmt.Printf("mallocs per unlogged sl.Logf(WARNING, \"%%s is a log message with level %%d\", \"This\", WARNING): %d\n", mallocs/N) } +func TestGetActualPathReplacePattern(t *testing.T) { + fileName := "bid.%Y%M%D%H.log" + pattern := getActualPathReplacePattern(fileName) + fmt.Println(pattern) + + + fileName = "p.%Y-%M-%D.log" + pattern = getActualPathReplacePattern(fileName) + fmt.Println(pattern) +} + func TestXMLConfig(t *testing.T) { const ( configfile = "example.xml" @@ -383,7 +394,7 @@ func TestXMLConfig(t *testing.T) { } // Make sure they're the right type - if _, ok := log["stdout"].LogWriter.(ConsoleLogWriter); !ok { + if _, ok := log["stdout"].LogWriter.(*ConsoleLogWriter); !ok { t.Fatalf("XMLConfig: Expected stdout to be ConsoleLogWriter, found %T", log["stdout"].LogWriter) } if _, ok := log["file"].LogWriter.(*FileLogWriter); !ok { diff --git a/wrapper.go b/wrapper.go index 2ae222b..4407f82 100644 --- a/wrapper.go +++ b/wrapper.go @@ -27,7 +27,7 @@ func AddFilter(name string, lvl Level, writer LogWriter) { Global.AddFilter(name, lvl, writer) } -// Wrapper for (*Logger).Close (closes and removes all logwriters) +// Wrapper for (*Logger).Close (closes and removes all logwriters ) func Close() { Global.Close() }