From 30bb530903352039c1b5055a756b7e246e2406b6 Mon Sep 17 00:00:00 2001 From: =Corey Hulen Date: Mon, 11 Jan 2016 09:13:38 -0600 Subject: Upgrading logging package --- Godeps/Godeps.json | 5 +- .../src/code.google.com/p/log4go/.hgtags | 4 - .../src/code.google.com/p/log4go/LICENSE | 13 - .../_workspace/src/code.google.com/p/log4go/README | 12 - .../src/code.google.com/p/log4go/config.go | 288 ----------- .../p/log4go/examples/ConsoleLogWriter_Manual.go | 13 - .../p/log4go/examples/FileLogWriter_Manual.go | 57 --- .../p/log4go/examples/SimpleNetLogServer.go | 42 -- .../p/log4go/examples/SocketLogWriter_Manual.go | 18 - .../p/log4go/examples/XMLConfigurationExample.go | 13 - .../code.google.com/p/log4go/examples/example.xml | 47 -- .../src/code.google.com/p/log4go/filelog.go | 239 --------- .../src/code.google.com/p/log4go/log4go.go | 484 ------------------- .../src/code.google.com/p/log4go/log4go_test.go | 534 --------------------- .../src/code.google.com/p/log4go/pattlog.go | 122 ----- .../src/code.google.com/p/log4go/socklog.go | 57 --- .../src/code.google.com/p/log4go/termlog.go | 45 -- .../src/code.google.com/p/log4go/wrapper.go | 278 ----------- .../src/github.com/alecthomas/log4go/.gitignore | 2 + .../src/github.com/alecthomas/log4go/LICENSE | 13 + .../src/github.com/alecthomas/log4go/README | 12 + .../src/github.com/alecthomas/log4go/config.go | 288 +++++++++++ .../log4go/examples/ConsoleLogWriter_Manual.go | 14 + .../log4go/examples/FileLogWriter_Manual.go | 57 +++ .../log4go/examples/SimpleNetLogServer.go | 42 ++ .../log4go/examples/SocketLogWriter_Manual.go | 18 + .../log4go/examples/XMLConfigurationExample.go | 13 + .../alecthomas/log4go/examples/example.xml | 47 ++ .../src/github.com/alecthomas/log4go/filelog.go | 264 ++++++++++ .../src/github.com/alecthomas/log4go/log4go.go | 484 +++++++++++++++++++ .../src/github.com/alecthomas/log4go/pattlog.go | 126 +++++ .../src/github.com/alecthomas/log4go/socklog.go | 57 +++ .../src/github.com/alecthomas/log4go/termlog.go | 49 ++ .../src/github.com/alecthomas/log4go/wrapper.go | 278 +++++++++++ 34 files changed, 1766 insertions(+), 2269 deletions(-) delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/.hgtags delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/LICENSE delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/README delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/config.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/examples/ConsoleLogWriter_Manual.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/examples/FileLogWriter_Manual.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/examples/SimpleNetLogServer.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/examples/SocketLogWriter_Manual.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/examples/XMLConfigurationExample.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/examples/example.xml delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/filelog.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/log4go.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/log4go_test.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/pattlog.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/socklog.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/termlog.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/log4go/wrapper.go create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/.gitignore create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/LICENSE create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/README create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/config.go create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/examples/ConsoleLogWriter_Manual.go create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/examples/FileLogWriter_Manual.go create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/examples/SimpleNetLogServer.go create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/examples/SocketLogWriter_Manual.go create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/examples/XMLConfigurationExample.go create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/examples/example.xml create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/filelog.go create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/log4go.go create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/pattlog.go create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/socklog.go create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/termlog.go create mode 100644 Godeps/_workspace/src/github.com/alecthomas/log4go/wrapper.go (limited to 'Godeps') diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index bd2392f90..d9c4a61bd 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -3,9 +3,8 @@ "GoVersion": "go1.5.1", "Deps": [ { - "ImportPath": "code.google.com/p/log4go", - "Comment": "go.weekly.2012-02-22-1", - "Rev": "c3294304d93f48a37d3bed1d382882a9c2989f99" + "ImportPath": "github.com/alecthomas/log4go", + "Rev": "8e9057c3b25c409a34c0b9737cdc82cbcafeabce" }, { "ImportPath": "github.com/braintree/manners", diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/.hgtags b/Godeps/_workspace/src/code.google.com/p/log4go/.hgtags deleted file mode 100644 index 72a2eea2c..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/.hgtags +++ /dev/null @@ -1,4 +0,0 @@ -4fbe6aadba231e838a449d340e43bdaab0bf85bd go.weekly.2012-02-07 -56168fd53249d639c25c74ced881fffb20d27be9 go.weekly.2012-02-22 -56168fd53249d639c25c74ced881fffb20d27be9 go.weekly.2012-02-22 -5c22fbd77d91f54d76cdbdee05318699754c44cc go.weekly.2012-02-22 diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/LICENSE b/Godeps/_workspace/src/code.google.com/p/log4go/LICENSE deleted file mode 100644 index 7093402bf..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2010, Kyle Lemons . All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/README b/Godeps/_workspace/src/code.google.com/p/log4go/README deleted file mode 100644 index 16d80ecb7..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/README +++ /dev/null @@ -1,12 +0,0 @@ -Please see http://log4go.googlecode.com/ - -Installation: -- Run `goinstall log4go.googlecode.com/hg` - -Usage: -- Add the following import: -import l4g "log4go.googlecode.com/hg" - -Acknowledgements: -- pomack - For providing awesome patches to bring log4go up to the latest Go spec diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/config.go b/Godeps/_workspace/src/code.google.com/p/log4go/config.go deleted file mode 100644 index f048b69f5..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/config.go +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright (C) 2010, Kyle Lemons . All rights reserved. - -package log4go - -import ( - "encoding/xml" - "fmt" - "io/ioutil" - "os" - "strconv" - "strings" -) - -type xmlProperty struct { - Name string `xml:"name,attr"` - Value string `xml:",chardata"` -} - -type xmlFilter struct { - Enabled string `xml:"enabled,attr"` - Tag string `xml:"tag"` - Level string `xml:"level"` - Type string `xml:"type"` - Property []xmlProperty `xml:"property"` -} - -type xmlLoggerConfig struct { - Filter []xmlFilter `xml:"filter"` -} - -// Load XML configuration; see examples/example.xml for documentation -func (log Logger) LoadConfiguration(filename string) { - log.Close() - - // Open the configuration file - fd, err := os.Open(filename) - if err != nil { - fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Could not open %q for reading: %s\n", filename, err) - os.Exit(1) - } - - contents, err := ioutil.ReadAll(fd) - if err != nil { - fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Could not read %q: %s\n", filename, err) - os.Exit(1) - } - - xc := new(xmlLoggerConfig) - if err := xml.Unmarshal(contents, xc); err != nil { - fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Could not parse XML configuration in %q: %s\n", filename, err) - os.Exit(1) - } - - for _, xmlfilt := range xc.Filter { - var filt LogWriter - var lvl level - bad, good, enabled := false, true, false - - // Check required children - if len(xmlfilt.Enabled) == 0 { - fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required attribute %s for filter missing in %s\n", "enabled", filename) - bad = true - } else { - enabled = xmlfilt.Enabled != "false" - } - if len(xmlfilt.Tag) == 0 { - fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required child <%s> for filter missing in %s\n", "tag", filename) - bad = true - } - if len(xmlfilt.Type) == 0 { - fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required child <%s> for filter missing in %s\n", "type", filename) - bad = true - } - if len(xmlfilt.Level) == 0 { - fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required child <%s> for filter missing in %s\n", "level", filename) - bad = true - } - - switch xmlfilt.Level { - case "FINEST": - lvl = FINEST - case "FINE": - lvl = FINE - case "DEBUG": - lvl = DEBUG - case "TRACE": - lvl = TRACE - case "INFO": - lvl = INFO - case "WARNING": - lvl = WARNING - case "ERROR": - lvl = ERROR - case "CRITICAL": - lvl = CRITICAL - default: - fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required child <%s> for filter has unknown value in %s: %s\n", "level", filename, xmlfilt.Level) - bad = true - } - - // Just so all of the required attributes are errored at the same time if missing - if bad { - os.Exit(1) - } - - switch xmlfilt.Type { - case "console": - filt, good = xmlToConsoleLogWriter(filename, xmlfilt.Property, enabled) - case "file": - filt, good = xmlToFileLogWriter(filename, xmlfilt.Property, enabled) - case "xml": - filt, good = xmlToXMLLogWriter(filename, xmlfilt.Property, enabled) - case "socket": - filt, good = xmlToSocketLogWriter(filename, xmlfilt.Property, enabled) - default: - fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Could not load XML configuration in %s: unknown filter type \"%s\"\n", filename, xmlfilt.Type) - os.Exit(1) - } - - // Just so all of the required params are errored at the same time if wrong - if !good { - os.Exit(1) - } - - // If we're disabled (syntax and correctness checks only), don't add to logger - if !enabled { - continue - } - - log[xmlfilt.Tag] = &Filter{lvl, filt} - } -} - -func xmlToConsoleLogWriter(filename string, props []xmlProperty, enabled bool) (ConsoleLogWriter, bool) { - // Parse properties - for _, prop := range props { - switch prop.Name { - default: - fmt.Fprintf(os.Stderr, "LoadConfiguration: Warning: Unknown property \"%s\" for console filter in %s\n", prop.Name, filename) - } - } - - // If it's disabled, we're just checking syntax - if !enabled { - return nil, true - } - - return NewConsoleLogWriter(), true -} - -// Parse a number with K/M/G suffixes based on thousands (1000) or 2^10 (1024) -func strToNumSuffix(str string, mult int) int { - num := 1 - if len(str) > 1 { - switch str[len(str)-1] { - case 'G', 'g': - num *= mult - fallthrough - case 'M', 'm': - num *= mult - fallthrough - case 'K', 'k': - num *= mult - str = str[0 : len(str)-1] - } - } - parsed, _ := strconv.Atoi(str) - return parsed * num -} -func xmlToFileLogWriter(filename string, props []xmlProperty, enabled bool) (*FileLogWriter, bool) { - file := "" - format := "[%D %T] [%L] (%S) %M" - maxlines := 0 - maxsize := 0 - daily := false - rotate := false - - // Parse properties - for _, prop := range props { - switch prop.Name { - case "filename": - file = strings.Trim(prop.Value, " \r\n") - case "format": - format = strings.Trim(prop.Value, " \r\n") - case "maxlines": - maxlines = strToNumSuffix(strings.Trim(prop.Value, " \r\n"), 1000) - case "maxsize": - maxsize = strToNumSuffix(strings.Trim(prop.Value, " \r\n"), 1024) - case "daily": - daily = strings.Trim(prop.Value, " \r\n") != "false" - case "rotate": - rotate = strings.Trim(prop.Value, " \r\n") != "false" - default: - fmt.Fprintf(os.Stderr, "LoadConfiguration: Warning: Unknown property \"%s\" for file filter in %s\n", prop.Name, filename) - } - } - - // Check properties - if len(file) == 0 { - fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required property \"%s\" for file filter missing in %s\n", "filename", filename) - return nil, false - } - - // If it's disabled, we're just checking syntax - if !enabled { - return nil, true - } - - flw := NewFileLogWriter(file, rotate) - flw.SetFormat(format) - flw.SetRotateLines(maxlines) - flw.SetRotateSize(maxsize) - flw.SetRotateDaily(daily) - return flw, true -} - -func xmlToXMLLogWriter(filename string, props []xmlProperty, enabled bool) (*FileLogWriter, bool) { - file := "" - maxrecords := 0 - maxsize := 0 - daily := false - rotate := false - - // Parse properties - for _, prop := range props { - switch prop.Name { - case "filename": - file = strings.Trim(prop.Value, " \r\n") - case "maxrecords": - maxrecords = strToNumSuffix(strings.Trim(prop.Value, " \r\n"), 1000) - case "maxsize": - maxsize = strToNumSuffix(strings.Trim(prop.Value, " \r\n"), 1024) - case "daily": - daily = strings.Trim(prop.Value, " \r\n") != "false" - case "rotate": - rotate = strings.Trim(prop.Value, " \r\n") != "false" - default: - fmt.Fprintf(os.Stderr, "LoadConfiguration: Warning: Unknown property \"%s\" for xml filter in %s\n", prop.Name, filename) - } - } - - // Check properties - if len(file) == 0 { - fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required property \"%s\" for xml filter missing in %s\n", "filename", filename) - return nil, false - } - - // If it's disabled, we're just checking syntax - if !enabled { - return nil, true - } - - xlw := NewXMLLogWriter(file, rotate) - xlw.SetRotateLines(maxrecords) - xlw.SetRotateSize(maxsize) - xlw.SetRotateDaily(daily) - return xlw, true -} - -func xmlToSocketLogWriter(filename string, props []xmlProperty, enabled bool) (SocketLogWriter, bool) { - endpoint := "" - protocol := "udp" - - // Parse properties - for _, prop := range props { - switch prop.Name { - case "endpoint": - endpoint = strings.Trim(prop.Value, " \r\n") - case "protocol": - protocol = strings.Trim(prop.Value, " \r\n") - default: - fmt.Fprintf(os.Stderr, "LoadConfiguration: Warning: Unknown property \"%s\" for file filter in %s\n", prop.Name, filename) - } - } - - // Check properties - if len(endpoint) == 0 { - fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required property \"%s\" for file filter missing in %s\n", "endpoint", filename) - return nil, false - } - - // If it's disabled, we're just checking syntax - if !enabled { - return nil, true - } - - return NewSocketLogWriter(protocol, endpoint), true -} diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/examples/ConsoleLogWriter_Manual.go b/Godeps/_workspace/src/code.google.com/p/log4go/examples/ConsoleLogWriter_Manual.go deleted file mode 100644 index 394ca8380..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/examples/ConsoleLogWriter_Manual.go +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import ( - "time" -) - -import l4g "code.google.com/p/log4go" - -func main() { - log := l4g.NewLogger() - log.AddFilter("stdout", l4g.DEBUG, l4g.NewConsoleLogWriter()) - log.Info("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02")) -} diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/examples/FileLogWriter_Manual.go b/Godeps/_workspace/src/code.google.com/p/log4go/examples/FileLogWriter_Manual.go deleted file mode 100644 index efd596aa6..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/examples/FileLogWriter_Manual.go +++ /dev/null @@ -1,57 +0,0 @@ -package main - -import ( - "bufio" - "fmt" - "io" - "os" - "time" -) - -import l4g "code.google.com/p/log4go" - -const ( - filename = "flw.log" -) - -func main() { - // Get a new logger instance - log := l4g.NewLogger() - - // Create a default logger that is logging messages of FINE or higher - log.AddFilter("file", l4g.FINE, l4g.NewFileLogWriter(filename, false)) - log.Close() - - /* Can also specify manually via the following: (these are the defaults) */ - flw := l4g.NewFileLogWriter(filename, false) - flw.SetFormat("[%D %T] [%L] (%S) %M") - flw.SetRotate(false) - flw.SetRotateSize(0) - flw.SetRotateLines(0) - flw.SetRotateDaily(false) - log.AddFilter("file", l4g.FINE, flw) - - // Log some experimental messages - log.Finest("Everything is created now (notice that I will not be printing to the file)") - log.Info("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02")) - log.Critical("Time to close out!") - - // Close the log - log.Close() - - // Print what was logged to the file (yes, I know I'm skipping error checking) - fd, _ := os.Open(filename) - in := bufio.NewReader(fd) - fmt.Print("Messages logged to file were: (line numbers not included)\n") - for lineno := 1; ; lineno++ { - line, err := in.ReadString('\n') - if err == io.EOF { - break - } - fmt.Printf("%3d:\t%s", lineno, line) - } - fd.Close() - - // Remove the file so it's not lying around - os.Remove(filename) -} diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/examples/SimpleNetLogServer.go b/Godeps/_workspace/src/code.google.com/p/log4go/examples/SimpleNetLogServer.go deleted file mode 100644 index 83c80ad12..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/examples/SimpleNetLogServer.go +++ /dev/null @@ -1,42 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "net" - "os" -) - -var ( - port = flag.String("p", "12124", "Port number to listen on") -) - -func e(err error) { - if err != nil { - fmt.Printf("Erroring out: %s\n", err) - os.Exit(1) - } -} - -func main() { - flag.Parse() - - // Bind to the port - bind, err := net.ResolveUDPAddr("0.0.0.0:" + *port) - e(err) - - // Create listener - listener, err := net.ListenUDP("udp", bind) - e(err) - - fmt.Printf("Listening to port %s...\n", *port) - for { - // read into a new buffer - buffer := make([]byte, 1024) - _, _, err := listener.ReadFrom(buffer) - e(err) - - // log to standard output - fmt.Println(string(buffer)) - } -} diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/examples/SocketLogWriter_Manual.go b/Godeps/_workspace/src/code.google.com/p/log4go/examples/SocketLogWriter_Manual.go deleted file mode 100644 index 400b698ca..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/examples/SocketLogWriter_Manual.go +++ /dev/null @@ -1,18 +0,0 @@ -package main - -import ( - "time" -) - -import l4g "code.google.com/p/log4go" - -func main() { - log := l4g.NewLogger() - log.AddFilter("network", l4g.FINEST, l4g.NewSocketLogWriter("udp", "192.168.1.255:12124")) - - // Run `nc -u -l -p 12124` or similar before you run this to see the following message - log.Info("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02")) - - // This makes sure the output stream buffer is written - log.Close() -} diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/examples/XMLConfigurationExample.go b/Godeps/_workspace/src/code.google.com/p/log4go/examples/XMLConfigurationExample.go deleted file mode 100644 index 164c2add4..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/examples/XMLConfigurationExample.go +++ /dev/null @@ -1,13 +0,0 @@ -package main - -import l4g "code.google.com/p/log4go" - -func main() { - // Load the configuration (isn't this easy?) - l4g.LoadConfiguration("example.xml") - - // And now we're ready! - l4g.Finest("This will only go to those of you really cool UDP kids! If you change enabled=true.") - l4g.Debug("Oh no! %d + %d = %d!", 2, 2, 2+2) - l4g.Info("About that time, eh chaps?") -} diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/examples/example.xml b/Godeps/_workspace/src/code.google.com/p/log4go/examples/example.xml deleted file mode 100644 index e791278ce..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/examples/example.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - stdout - console - - DEBUG - - - file - file - FINEST - test.log - - [%D %T] [%L] (%S) %M - false - 0M - 0K - true - - - xmllog - xml - TRACE - trace.xml - true - 100M - 6K - false - - - donotopen - socket - FINEST - 192.168.1.255:12124 - udp - - diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/filelog.go b/Godeps/_workspace/src/code.google.com/p/log4go/filelog.go deleted file mode 100644 index 9cbd815d9..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/filelog.go +++ /dev/null @@ -1,239 +0,0 @@ -// Copyright (C) 2010, Kyle Lemons . All rights reserved. - -package log4go - -import ( - "os" - "fmt" - "time" -) - -// This log writer sends output to a file -type FileLogWriter struct { - rec chan *LogRecord - rot chan bool - - // The opened file - filename string - file *os.File - - // The logging format - format string - - // File header/trailer - header, trailer string - - // Rotate at linecount - maxlines int - maxlines_curlines int - - // Rotate at size - maxsize int - maxsize_cursize int - - // Rotate daily - daily bool - daily_opendate int - - // Keep old logfiles (.001, .002, etc) - rotate bool -} - -// This is the FileLogWriter's output method -func (w *FileLogWriter) LogWrite(rec *LogRecord) { - w.rec <- rec -} - -func (w *FileLogWriter) Close() { - close(w.rec) -} - -// NewFileLogWriter creates a new LogWriter which writes to the given file and -// has rotation enabled if rotate is true. -// -// If rotate is true, any time a new log file is opened, the old one is renamed -// with a .### extension to preserve it. The various Set* methods can be used -// to configure log rotation based on lines, size, and daily. -// -// The standard log-line format is: -// [%D %T] [%L] (%S) %M -func NewFileLogWriter(fname string, rotate bool) *FileLogWriter { - w := &FileLogWriter{ - rec: make(chan *LogRecord, LogBufferLength), - rot: make(chan bool), - filename: fname, - format: "[%D %T] [%L] (%S) %M", - rotate: rotate, - } - - // open the file for the first time - if err := w.intRotate(); err != nil { - fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err) - return nil - } - - go func() { - defer func() { - if w.file != nil { - fmt.Fprint(w.file, FormatLogRecord(w.trailer, &LogRecord{Created: time.Now()})) - w.file.Close() - } - }() - - for { - select { - case <-w.rot: - if err := w.intRotate(); err != nil { - fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err) - return - } - case rec, ok := <-w.rec: - if !ok { - return - } - 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) { - if err := w.intRotate(); err != nil { - fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err) - return - } - } - - // Perform the write - n, err := fmt.Fprint(w.file, FormatLogRecord(w.format, rec)) - if err != nil { - fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err) - return - } - - // Update the counts - w.maxlines_curlines++ - w.maxsize_cursize += n - } - } - }() - - return w -} - -// Request that the logs rotate -func (w *FileLogWriter) Rotate() { - w.rot <- true -} - -// If this is called in a threaded context, it MUST be synchronized -func (w *FileLogWriter) intRotate() error { - // Close any log file that may be open - if w.file != nil { - fmt.Fprint(w.file, FormatLogRecord(w.trailer, &LogRecord{Created: time.Now()})) - w.file.Close() - } - - // If we are keeping log files, move it to the next available number - if w.rotate { - _, err := os.Lstat(w.filename) - if err == nil { // file exists - // Find the next available number - num := 1 - fname := "" - for ; err == nil && num <= 999; num++ { - fname = w.filename + fmt.Sprintf(".%03d", num) - _, err = os.Lstat(fname) - } - // return error if the last file checked still existed - if err == nil { - return fmt.Errorf("Rotate: Cannot find free log number to rename %s\n", w.filename) - } - - // Rename the file to its newfound home - err = os.Rename(w.filename, fname) - if err != nil { - return fmt.Errorf("Rotate: %s\n", err) - } - } - } - - // Open the log file - fd, err := os.OpenFile(w.filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660) - if err != nil { - return err - } - w.file = fd - - now := time.Now() - fmt.Fprint(w.file, FormatLogRecord(w.header, &LogRecord{Created: now})) - - // Set the daily open date to the current date - w.daily_opendate = now.Day() - - // initialize rotation values - w.maxlines_curlines = 0 - w.maxsize_cursize = 0 - - return nil -} - -// Set the logging format (chainable). Must be called before the first log -// message is written. -func (w *FileLogWriter) SetFormat(format string) *FileLogWriter { - w.format = format - return w -} - -// Set the logfile header and footer (chainable). Must be called before the first log -// message is written. These are formatted similar to the FormatLogRecord (e.g. -// you can use %D and %T in your header/footer for date and time). -func (w *FileLogWriter) SetHeadFoot(head, foot string) *FileLogWriter { - w.header, w.trailer = head, foot - if w.maxlines_curlines == 0 { - fmt.Fprint(w.file, FormatLogRecord(w.header, &LogRecord{Created: time.Now()})) - } - return w -} - -// Set rotate at linecount (chainable). Must be called before the first log -// message is written. -func (w *FileLogWriter) SetRotateLines(maxlines int) *FileLogWriter { - //fmt.Fprintf(os.Stderr, "FileLogWriter.SetRotateLines: %v\n", maxlines) - w.maxlines = maxlines - return w -} - -// Set rotate at size (chainable). Must be called before the first log message -// is written. -func (w *FileLogWriter) SetRotateSize(maxsize int) *FileLogWriter { - //fmt.Fprintf(os.Stderr, "FileLogWriter.SetRotateSize: %v\n", maxsize) - w.maxsize = maxsize - return w -} - -// Set rotate daily (chainable). Must be called before the first log message is -// written. -func (w *FileLogWriter) SetRotateDaily(daily bool) *FileLogWriter { - //fmt.Fprintf(os.Stderr, "FileLogWriter.SetRotateDaily: %v\n", daily) - w.daily = daily - return w -} - -// SetRotate changes whether or not the old logs are kept. (chainable) Must be -// called before the first log message is written. If rotate is false, the -// files are overwritten; otherwise, they are rotated to another file before the -// new log is opened. -func (w *FileLogWriter) SetRotate(rotate bool) *FileLogWriter { - //fmt.Fprintf(os.Stderr, "FileLogWriter.SetRotate: %v\n", rotate) - w.rotate = rotate - return w -} - -// NewXMLLogWriter is a utility method for creating a FileLogWriter set up to -// output XML record log messages instead of line-based ones. -func NewXMLLogWriter(fname string, rotate bool) *FileLogWriter { - return NewFileLogWriter(fname, rotate).SetFormat( - ` - %D %T - %S - %M - `).SetHeadFoot("", "") -} diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/log4go.go b/Godeps/_workspace/src/code.google.com/p/log4go/log4go.go deleted file mode 100644 index ab4e857f5..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/log4go.go +++ /dev/null @@ -1,484 +0,0 @@ -// Copyright (C) 2010, Kyle Lemons . All rights reserved. - -// Package log4go provides level-based and highly configurable logging. -// -// Enhanced Logging -// -// This is inspired by the logging functionality in Java. Essentially, you create a Logger -// object and create output filters for it. You can send whatever you want to the Logger, -// and it will filter that based on your settings and send it to the outputs. This way, you -// can put as much debug code in your program as you want, and when you're done you can filter -// out the mundane messages so only the important ones show up. -// -// Utility functions are provided to make life easier. Here is some example code to get started: -// -// log := log4go.NewLogger() -// log.AddFilter("stdout", log4go.DEBUG, log4go.NewConsoleLogWriter()) -// log.AddFilter("log", log4go.FINE, log4go.NewFileLogWriter("example.log", true)) -// log.Info("The time is now: %s", time.LocalTime().Format("15:04:05 MST 2006/01/02")) -// -// The first two lines can be combined with the utility NewDefaultLogger: -// -// log := log4go.NewDefaultLogger(log4go.DEBUG) -// log.AddFilter("log", log4go.FINE, log4go.NewFileLogWriter("example.log", true)) -// log.Info("The time is now: %s", time.LocalTime().Format("15:04:05 MST 2006/01/02")) -// -// Usage notes: -// - The ConsoleLogWriter does not display the source of the message to standard -// output, but the FileLogWriter does. -// - The utility functions (Info, Debug, Warn, etc) derive their source from the -// calling function, and this incurs extra overhead. -// -// Changes from 2.0: -// - The external interface has remained mostly stable, but a lot of the -// internals have been changed, so if you depended on any of this or created -// your own LogWriter, then you will probably have to update your code. In -// particular, Logger is now a map and ConsoleLogWriter is now a channel -// behind-the-scenes, and the LogWrite method no longer has return values. -// -// Future work: (please let me know if you think I should work on any of these particularly) -// - Log file rotation -// - Logging configuration files ala log4j -// - Have the ability to remove filters? -// - Have GetInfoChannel, GetDebugChannel, etc return a chan string that allows -// for another method of logging -// - Add an XML filter type -package log4go - -import ( - "errors" - "os" - "fmt" - "time" - "strings" - "runtime" -) - -// Version information -const ( - L4G_VERSION = "log4go-v3.0.1" - L4G_MAJOR = 3 - L4G_MINOR = 0 - L4G_BUILD = 1 -) - -/****** Constants ******/ - -// These are the integer logging levels used by the logger -type level int - -const ( - FINEST level = iota - FINE - DEBUG - TRACE - INFO - WARNING - ERROR - CRITICAL -) - -// Logging level strings -var ( - 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)] -} - -/****** Variables ******/ -var ( - // 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 -} - -/****** 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 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 ******/ - -// A Filter represents the log level below which no log records are written to -// the associated LogWriter. -type Filter struct { - Level level - LogWriter -} - -// A Logger represents a collection of Filters through which log messages are -// written. -type Logger map[string]*Filter - -// Create a new logger. -// -// DEPRECATED: Use make(Logger) instead. -func NewLogger() 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 -// or above lvl to standard output. -// -// DEPRECATED: use NewDefaultLogger instead. -func NewConsoleLogger(lvl level) Logger { - os.Stderr.WriteString("warning: use of deprecated NewConsoleLogger\n") - return Logger{ - "stdout": &Filter{lvl, 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()}, - } -} - -// Closes all log writers in preparation for exiting the program or a -// reconfiguration of logging. Calling this is not really imperative, unless -// 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) - } -} - -// 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 -} - -/******* 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) - } -} - -// 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) - } -} - -// 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) - } -} - -// 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...) -} - -// 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) -} - -// 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...) - } -} - -// 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...) - } -} - -// Debug is a utility method for debug log messages. -// The behavior of Debug depends on the first argument: -// - arg0 is a string -// When given a string as the first argument, this behaves like Logf but with -// the DEBUG log level: the first argument is interpreted as a format for the -// latter arguments. -// - arg0 is a func()string -// When given a closure of type func()string, this logs the string returned by -// the closure iff it will be logged. The closure runs at most one time. -// - arg0 is 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...) - } -} - -// 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...) - } -} - -// 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...) - } -} - -// Warn logs a message at the warning log level and returns the formatted error. -// At the warning level and higher, there is no performance benefit if the -// message is not actually logged, because all formats are processed and all -// 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) -} - -// 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) -} - -// 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) -} diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/log4go_test.go b/Godeps/_workspace/src/code.google.com/p/log4go/log4go_test.go deleted file mode 100644 index 90c629977..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/log4go_test.go +++ /dev/null @@ -1,534 +0,0 @@ -// Copyright (C) 2010, Kyle Lemons . All rights reserved. - -package log4go - -import ( - "crypto/md5" - "encoding/hex" - "fmt" - "io" - "io/ioutil" - "os" - "runtime" - "testing" - "time" -) - -const testLogFile = "_logtest.log" - -var now time.Time = time.Unix(0, 1234567890123456789).In(time.UTC) - -func newLogRecord(lvl level, src string, msg string) *LogRecord { - return &LogRecord{ - Level: lvl, - Source: src, - Created: now, - Message: msg, - } -} - -func TestELog(t *testing.T) { - fmt.Printf("Testing %s\n", L4G_VERSION) - lr := newLogRecord(CRITICAL, "source", "message") - if lr.Level != CRITICAL { - t.Errorf("Incorrect level: %d should be %d", lr.Level, CRITICAL) - } - if lr.Source != "source" { - t.Errorf("Incorrect source: %s should be %s", lr.Source, "source") - } - if lr.Message != "message" { - t.Errorf("Incorrect message: %s should be %s", lr.Source, "message") - } -} - -var formatTests = []struct { - Test string - Record *LogRecord - Formats map[string]string -}{ - { - Test: "Standard formats", - Record: &LogRecord{ - Level: ERROR, - Source: "source", - Message: "message", - Created: now, - }, - Formats: map[string]string{ - // TODO(kevlar): How can I do this so it'll work outside of PST? - FORMAT_DEFAULT: "[2009/02/13 23:31:30 UTC] [EROR] (source) message\n", - FORMAT_SHORT: "[23:31 02/13/09] [EROR] message\n", - FORMAT_ABBREV: "[EROR] message\n", - }, - }, -} - -func TestFormatLogRecord(t *testing.T) { - for _, test := range formatTests { - name := test.Test - for fmt, want := range test.Formats { - if got := FormatLogRecord(fmt, test.Record); got != want { - t.Errorf("%s - %s:", name, fmt) - t.Errorf(" got %q", got) - t.Errorf(" want %q", want) - } - } - } -} - -var logRecordWriteTests = []struct { - Test string - Record *LogRecord - Console string -}{ - { - Test: "Normal message", - Record: &LogRecord{ - Level: CRITICAL, - Source: "source", - Message: "message", - Created: now, - }, - Console: "[02/13/09 23:31:30] [CRIT] message\n", - }, -} - -func TestConsoleLogWriter(t *testing.T) { - console := make(ConsoleLogWriter) - - r, w := io.Pipe() - go console.run(w) - defer console.Close() - - buf := make([]byte, 1024) - - for _, test := range logRecordWriteTests { - name := test.Test - - console.LogWrite(test.Record) - n, _ := r.Read(buf) - - if got, want := string(buf[:n]), test.Console; got != want { - t.Errorf("%s: got %q", name, got) - t.Errorf("%s: want %q", name, want) - } - } -} - -func TestFileLogWriter(t *testing.T) { - defer func(buflen int) { - LogBufferLength = buflen - }(LogBufferLength) - LogBufferLength = 0 - - w := NewFileLogWriter(testLogFile, false) - if w == nil { - t.Fatalf("Invalid return: w should not be nil") - } - defer os.Remove(testLogFile) - - w.LogWrite(newLogRecord(CRITICAL, "source", "message")) - w.Close() - runtime.Gosched() - - if contents, err := ioutil.ReadFile(testLogFile); err != nil { - t.Errorf("read(%q): %s", testLogFile, err) - } else if len(contents) != 50 { - t.Errorf("malformed filelog: %q (%d bytes)", string(contents), len(contents)) - } -} - -func TestXMLLogWriter(t *testing.T) { - defer func(buflen int) { - LogBufferLength = buflen - }(LogBufferLength) - LogBufferLength = 0 - - w := NewXMLLogWriter(testLogFile, false) - if w == nil { - t.Fatalf("Invalid return: w should not be nil") - } - defer os.Remove(testLogFile) - - w.LogWrite(newLogRecord(CRITICAL, "source", "message")) - w.Close() - runtime.Gosched() - - if contents, err := ioutil.ReadFile(testLogFile); err != nil { - t.Errorf("read(%q): %s", testLogFile, err) - } else if len(contents) != 185 { - t.Errorf("malformed xmllog: %q (%d bytes)", string(contents), len(contents)) - } -} - -func TestLogger(t *testing.T) { - sl := NewDefaultLogger(WARNING) - if sl == nil { - t.Fatalf("NewDefaultLogger should never return nil") - } - if lw, exist := sl["stdout"]; lw == nil || exist != true { - t.Fatalf("NewDefaultLogger produced invalid logger (DNE or nil)") - } - if sl["stdout"].Level != WARNING { - t.Fatalf("NewDefaultLogger produced invalid logger (incorrect level)") - } - if len(sl) != 1 { - t.Fatalf("NewDefaultLogger produced invalid logger (incorrect map count)") - } - - //func (l *Logger) AddFilter(name string, level int, writer LogWriter) {} - l := make(Logger) - l.AddFilter("stdout", DEBUG, NewConsoleLogWriter()) - if lw, exist := l["stdout"]; lw == nil || exist != true { - t.Fatalf("AddFilter produced invalid logger (DNE or nil)") - } - if l["stdout"].Level != DEBUG { - t.Fatalf("AddFilter produced invalid logger (incorrect level)") - } - if len(l) != 1 { - t.Fatalf("AddFilter produced invalid logger (incorrect map count)") - } - - //func (l *Logger) Warn(format string, args ...interface{}) error {} - if err := l.Warn("%s %d %#v", "Warning:", 1, []int{}); err.Error() != "Warning: 1 []int{}" { - t.Errorf("Warn returned invalid error: %s", err) - } - - //func (l *Logger) Error(format string, args ...interface{}) error {} - if err := l.Error("%s %d %#v", "Error:", 10, []string{}); err.Error() != "Error: 10 []string{}" { - t.Errorf("Error returned invalid error: %s", err) - } - - //func (l *Logger) Critical(format string, args ...interface{}) error {} - if err := l.Critical("%s %d %#v", "Critical:", 100, []int64{}); err.Error() != "Critical: 100 []int64{}" { - t.Errorf("Critical returned invalid error: %s", err) - } - - // Already tested or basically untestable - //func (l *Logger) Log(level int, source, message string) {} - //func (l *Logger) Logf(level int, format string, args ...interface{}) {} - //func (l *Logger) intLogf(level int, format string, args ...interface{}) string {} - //func (l *Logger) Finest(format string, args ...interface{}) {} - //func (l *Logger) Fine(format string, args ...interface{}) {} - //func (l *Logger) Debug(format string, args ...interface{}) {} - //func (l *Logger) Trace(format string, args ...interface{}) {} - //func (l *Logger) Info(format string, args ...interface{}) {} -} - -func TestLogOutput(t *testing.T) { - const ( - expected = "fdf3e51e444da56b4cb400f30bc47424" - ) - - // Unbuffered output - defer func(buflen int) { - LogBufferLength = buflen - }(LogBufferLength) - LogBufferLength = 0 - - l := make(Logger) - - // Delete and open the output log without a timestamp (for a constant md5sum) - l.AddFilter("file", FINEST, NewFileLogWriter(testLogFile, false).SetFormat("[%L] %M")) - defer os.Remove(testLogFile) - - // Send some log messages - l.Log(CRITICAL, "testsrc1", fmt.Sprintf("This message is level %d", int(CRITICAL))) - l.Logf(ERROR, "This message is level %v", ERROR) - l.Logf(WARNING, "This message is level %s", WARNING) - l.Logc(INFO, func() string { return "This message is level INFO" }) - l.Trace("This message is level %d", int(TRACE)) - l.Debug("This message is level %s", DEBUG) - l.Fine(func() string { return fmt.Sprintf("This message is level %v", FINE) }) - l.Finest("This message is level %v", FINEST) - l.Finest(FINEST, "is also this message's level") - - l.Close() - - contents, err := ioutil.ReadFile(testLogFile) - if err != nil { - t.Fatalf("Could not read output log: %s", err) - } - - sum := md5.New() - sum.Write(contents) - if sumstr := hex.EncodeToString(sum.Sum(nil)); sumstr != expected { - t.Errorf("--- Log Contents:\n%s---", string(contents)) - t.Fatalf("Checksum does not match: %s (expecting %s)", sumstr, expected) - } -} - -func TestCountMallocs(t *testing.T) { - const N = 1 - var m runtime.MemStats - getMallocs := func() uint64 { - runtime.ReadMemStats(&m) - return m.Mallocs - } - - // Console logger - sl := NewDefaultLogger(INFO) - mallocs := 0 - getMallocs() - for i := 0; i < N; i++ { - sl.Log(WARNING, "here", "This is a WARNING message") - } - mallocs += getMallocs() - fmt.Printf("mallocs per sl.Log((WARNING, \"here\", \"This is a log message\"): %d\n", mallocs/N) - - // Console logger formatted - mallocs = 0 - getMallocs() - for i := 0; i < N; i++ { - sl.Logf(WARNING, "%s is a log message with level %d", "This", WARNING) - } - mallocs += getMallocs() - fmt.Printf("mallocs per sl.Logf(WARNING, \"%%s is a log message with level %%d\", \"This\", WARNING): %d\n", mallocs/N) - - // Console logger (not logged) - sl = NewDefaultLogger(INFO) - mallocs = 0 - getMallocs() - for i := 0; i < N; i++ { - sl.Log(DEBUG, "here", "This is a DEBUG log message") - } - mallocs += getMallocs() - fmt.Printf("mallocs per unlogged sl.Log((WARNING, \"here\", \"This is a log message\"): %d\n", mallocs/N) - - // Console logger formatted (not logged) - mallocs = 0 - getMallocs() - for i := 0; i < N; i++ { - sl.Logf(DEBUG, "%s is a log message with level %d", "This", DEBUG) - } - mallocs += getMallocs() - fmt.Printf("mallocs per unlogged sl.Logf(WARNING, \"%%s is a log message with level %%d\", \"This\", WARNING): %d\n", mallocs/N) -} - -func TestXMLConfig(t *testing.T) { - const ( - configfile = "example.xml" - ) - - fd, err := os.Create(configfile) - if err != nil { - t.Fatalf("Could not open %s for writing: %s", configfile, err) - } - - fmt.Fprintln(fd, "") - fmt.Fprintln(fd, " ") - fmt.Fprintln(fd, " stdout") - fmt.Fprintln(fd, " console") - fmt.Fprintln(fd, " ") - fmt.Fprintln(fd, " DEBUG") - fmt.Fprintln(fd, " ") - fmt.Fprintln(fd, " ") - fmt.Fprintln(fd, " file") - fmt.Fprintln(fd, " file") - fmt.Fprintln(fd, " FINEST") - fmt.Fprintln(fd, " test.log") - fmt.Fprintln(fd, " ") - fmt.Fprintln(fd, " [%D %T] [%L] (%S) %M") - fmt.Fprintln(fd, " false ") - fmt.Fprintln(fd, " 0M ") - fmt.Fprintln(fd, " 0K ") - fmt.Fprintln(fd, " true ") - fmt.Fprintln(fd, " ") - fmt.Fprintln(fd, " ") - fmt.Fprintln(fd, " xmllog") - fmt.Fprintln(fd, " xml") - fmt.Fprintln(fd, " TRACE") - fmt.Fprintln(fd, " trace.xml") - fmt.Fprintln(fd, " true ") - fmt.Fprintln(fd, " 100M ") - fmt.Fprintln(fd, " 6K ") - fmt.Fprintln(fd, " false ") - fmt.Fprintln(fd, " ") - fmt.Fprintln(fd, " ") - fmt.Fprintln(fd, " donotopen") - fmt.Fprintln(fd, " socket") - fmt.Fprintln(fd, " FINEST") - fmt.Fprintln(fd, " 192.168.1.255:12124 ") - fmt.Fprintln(fd, " udp ") - fmt.Fprintln(fd, " ") - fmt.Fprintln(fd, "") - fd.Close() - - log := make(Logger) - log.LoadConfiguration(configfile) - defer os.Remove("trace.xml") - defer os.Remove("test.log") - defer log.Close() - - // Make sure we got all loggers - if len(log) != 3 { - t.Fatalf("XMLConfig: Expected 3 filters, found %d", len(log)) - } - - // Make sure they're the right keys - if _, ok := log["stdout"]; !ok { - t.Errorf("XMLConfig: Expected stdout logger") - } - if _, ok := log["file"]; !ok { - t.Fatalf("XMLConfig: Expected file logger") - } - if _, ok := log["xmllog"]; !ok { - t.Fatalf("XMLConfig: Expected xmllog logger") - } - - // Make sure they're the right type - 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 { - t.Fatalf("XMLConfig: Expected file to be *FileLogWriter, found %T", log["file"].LogWriter) - } - if _, ok := log["xmllog"].LogWriter.(*FileLogWriter); !ok { - t.Fatalf("XMLConfig: Expected xmllog to be *FileLogWriter, found %T", log["xmllog"].LogWriter) - } - - // Make sure levels are set - if lvl := log["stdout"].Level; lvl != DEBUG { - t.Errorf("XMLConfig: Expected stdout to be set to level %d, found %d", DEBUG, lvl) - } - if lvl := log["file"].Level; lvl != FINEST { - t.Errorf("XMLConfig: Expected file to be set to level %d, found %d", FINEST, lvl) - } - if lvl := log["xmllog"].Level; lvl != TRACE { - t.Errorf("XMLConfig: Expected xmllog to be set to level %d, found %d", TRACE, lvl) - } - - // Make sure the w is open and points to the right file - if fname := log["file"].LogWriter.(*FileLogWriter).file.Name(); fname != "test.log" { - t.Errorf("XMLConfig: Expected file to have opened %s, found %s", "test.log", fname) - } - - // Make sure the XLW is open and points to the right file - if fname := log["xmllog"].LogWriter.(*FileLogWriter).file.Name(); fname != "trace.xml" { - t.Errorf("XMLConfig: Expected xmllog to have opened %s, found %s", "trace.xml", fname) - } - - // Move XML log file - os.Rename(configfile, "examples/"+configfile) // Keep this so that an example with the documentation is available -} - -func BenchmarkFormatLogRecord(b *testing.B) { - const updateEvery = 1 - rec := &LogRecord{ - Level: CRITICAL, - Created: now, - Source: "source", - Message: "message", - } - for i := 0; i < b.N; i++ { - rec.Created = rec.Created.Add(1 * time.Second / updateEvery) - if i%2 == 0 { - FormatLogRecord(FORMAT_DEFAULT, rec) - } else { - FormatLogRecord(FORMAT_SHORT, rec) - } - } -} - -func BenchmarkConsoleLog(b *testing.B) { - /* This doesn't seem to work on OS X - sink, err := os.Open(os.DevNull) - if err != nil { - panic(err) - } - if err := syscall.Dup2(int(sink.Fd()), syscall.Stdout); err != nil { - panic(err) - } - */ - - stdout = ioutil.Discard - sl := NewDefaultLogger(INFO) - for i := 0; i < b.N; i++ { - sl.Log(WARNING, "here", "This is a log message") - } -} - -func BenchmarkConsoleNotLogged(b *testing.B) { - sl := NewDefaultLogger(INFO) - for i := 0; i < b.N; i++ { - sl.Log(DEBUG, "here", "This is a log message") - } -} - -func BenchmarkConsoleUtilLog(b *testing.B) { - sl := NewDefaultLogger(INFO) - for i := 0; i < b.N; i++ { - sl.Info("%s is a log message", "This") - } -} - -func BenchmarkConsoleUtilNotLog(b *testing.B) { - sl := NewDefaultLogger(INFO) - for i := 0; i < b.N; i++ { - sl.Debug("%s is a log message", "This") - } -} - -func BenchmarkFileLog(b *testing.B) { - sl := make(Logger) - b.StopTimer() - sl.AddFilter("file", INFO, NewFileLogWriter("benchlog.log", false)) - b.StartTimer() - for i := 0; i < b.N; i++ { - sl.Log(WARNING, "here", "This is a log message") - } - b.StopTimer() - os.Remove("benchlog.log") -} - -func BenchmarkFileNotLogged(b *testing.B) { - sl := make(Logger) - b.StopTimer() - sl.AddFilter("file", INFO, NewFileLogWriter("benchlog.log", false)) - b.StartTimer() - for i := 0; i < b.N; i++ { - sl.Log(DEBUG, "here", "This is a log message") - } - b.StopTimer() - os.Remove("benchlog.log") -} - -func BenchmarkFileUtilLog(b *testing.B) { - sl := make(Logger) - b.StopTimer() - sl.AddFilter("file", INFO, NewFileLogWriter("benchlog.log", false)) - b.StartTimer() - for i := 0; i < b.N; i++ { - sl.Info("%s is a log message", "This") - } - b.StopTimer() - os.Remove("benchlog.log") -} - -func BenchmarkFileUtilNotLog(b *testing.B) { - sl := make(Logger) - b.StopTimer() - sl.AddFilter("file", INFO, NewFileLogWriter("benchlog.log", false)) - b.StartTimer() - for i := 0; i < b.N; i++ { - sl.Debug("%s is a log message", "This") - } - b.StopTimer() - os.Remove("benchlog.log") -} - -// Benchmark results (darwin amd64 6g) -//elog.BenchmarkConsoleLog 100000 22819 ns/op -//elog.BenchmarkConsoleNotLogged 2000000 879 ns/op -//elog.BenchmarkConsoleUtilLog 50000 34380 ns/op -//elog.BenchmarkConsoleUtilNotLog 1000000 1339 ns/op -//elog.BenchmarkFileLog 100000 26497 ns/op -//elog.BenchmarkFileNotLogged 2000000 821 ns/op -//elog.BenchmarkFileUtilLog 50000 33945 ns/op -//elog.BenchmarkFileUtilNotLog 1000000 1258 ns/op diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/pattlog.go b/Godeps/_workspace/src/code.google.com/p/log4go/pattlog.go deleted file mode 100644 index 8224302b3..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/pattlog.go +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (C) 2010, Kyle Lemons . All rights reserved. - -package log4go - -import ( - "fmt" - "bytes" - "io" -) - -const ( - FORMAT_DEFAULT = "[%D %T] [%L] (%S) %M" - FORMAT_SHORT = "[%t %d] [%L] %M" - FORMAT_ABBREV = "[%L] %M" -) - -type formatCacheType struct { - LastUpdateSeconds int64 - shortTime, shortDate string - longTime, longDate string -} - -var formatCache = &formatCacheType{} - -// Known format codes: -// %T - Time (15:04:05 MST) -// %t - Time (15:04) -// %D - Date (2006/01/02) -// %d - Date (01/02/06) -// %L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT) -// %S - Source -// %M - Message -// Ignores unknown formats -// Recommended: "[%D %T] [%L] (%S) %M" -func FormatLogRecord(format string, rec *LogRecord) string { - if rec == nil { - return "" - } - if len(format) == 0 { - return "" - } - - out := bytes.NewBuffer(make([]byte, 0, 64)) - secs := rec.Created.UnixNano() / 1e9 - - cache := *formatCache - if cache.LastUpdateSeconds != secs { - month, day, year := rec.Created.Month(), rec.Created.Day(), rec.Created.Year() - hour, minute, second := rec.Created.Hour(), rec.Created.Minute(), rec.Created.Second() - zone, _ := rec.Created.Zone() - updated := &formatCacheType{ - LastUpdateSeconds: secs, - shortTime: fmt.Sprintf("%02d:%02d", hour, minute), - shortDate: fmt.Sprintf("%02d/%02d/%02d", month, day, year%100), - longTime: fmt.Sprintf("%02d:%02d:%02d %s", hour, minute, second, zone), - longDate: fmt.Sprintf("%04d/%02d/%02d", year, month, day), - } - cache = *updated - formatCache = updated - } - - // Split the string into pieces by % signs - pieces := bytes.Split([]byte(format), []byte{'%'}) - - // Iterate over the pieces, replacing known formats - for i, piece := range pieces { - if i > 0 && len(piece) > 0 { - switch piece[0] { - case 'T': - out.WriteString(cache.longTime) - case 't': - out.WriteString(cache.shortTime) - case 'D': - out.WriteString(cache.longDate) - case 'd': - out.WriteString(cache.shortDate) - case 'L': - out.WriteString(levelStrings[rec.Level]) - case 'S': - out.WriteString(rec.Source) - case 'M': - out.WriteString(rec.Message) - } - if len(piece) > 1 { - out.Write(piece[1:]) - } - } else if len(piece) > 0 { - out.Write(piece) - } - } - out.WriteByte('\n') - - return out.String() -} - -// This is the standard writer that prints to standard output. -type FormatLogWriter chan *LogRecord - -// This creates a new FormatLogWriter -func NewFormatLogWriter(out io.Writer, format string) FormatLogWriter { - records := make(FormatLogWriter, LogBufferLength) - go records.run(out, format) - return records -} - -func (w FormatLogWriter) run(out io.Writer, format string) { - for rec := range w { - fmt.Fprint(out, FormatLogRecord(format, rec)) - } -} - -// This is the FormatLogWriter's output method. This will block if the output -// buffer is full. -func (w FormatLogWriter) LogWrite(rec *LogRecord) { - w <- rec -} - -// Close stops the logger from sending messages to standard output. Attempts to -// send log messages to this logger after a Close have undefined behavior. -func (w FormatLogWriter) Close() { - close(w) -} diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/socklog.go b/Godeps/_workspace/src/code.google.com/p/log4go/socklog.go deleted file mode 100644 index 1d224a99d..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/socklog.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2010, Kyle Lemons . All rights reserved. - -package log4go - -import ( - "encoding/json" - "fmt" - "net" - "os" -) - -// This log writer sends output to a socket -type SocketLogWriter chan *LogRecord - -// This is the SocketLogWriter's output method -func (w SocketLogWriter) LogWrite(rec *LogRecord) { - w <- rec -} - -func (w SocketLogWriter) Close() { - close(w) -} - -func NewSocketLogWriter(proto, hostport string) SocketLogWriter { - sock, err := net.Dial(proto, hostport) - if err != nil { - fmt.Fprintf(os.Stderr, "NewSocketLogWriter(%q): %s\n", hostport, err) - return nil - } - - w := SocketLogWriter(make(chan *LogRecord, LogBufferLength)) - - go func() { - defer func() { - if sock != nil && proto == "tcp" { - sock.Close() - } - }() - - for rec := range w { - // Marshall into JSON - js, err := json.Marshal(rec) - if err != nil { - fmt.Fprint(os.Stderr, "SocketLogWriter(%q): %s", hostport, err) - return - } - - _, err = sock.Write(js) - if err != nil { - fmt.Fprint(os.Stderr, "SocketLogWriter(%q): %s", hostport, err) - return - } - } - }() - - return w -} diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/termlog.go b/Godeps/_workspace/src/code.google.com/p/log4go/termlog.go deleted file mode 100644 index 1ed2e4e0d..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/termlog.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (C) 2010, Kyle Lemons . All rights reserved. - -package log4go - -import ( - "io" - "os" - "fmt" -) - -var stdout io.Writer = os.Stdout - -// This is the standard writer that prints to standard output. -type ConsoleLogWriter chan *LogRecord - -// This creates a new ConsoleLogWriter -func NewConsoleLogWriter() ConsoleLogWriter { - records := make(ConsoleLogWriter, LogBufferLength) - go records.run(stdout) - return records -} - -func (w ConsoleLogWriter) run(out io.Writer) { - var timestr string - var timestrAt int64 - - for rec := range w { - if at := rec.Created.UnixNano() / 1e9; at != timestrAt { - timestr, timestrAt = rec.Created.Format("01/02/06 15:04:05"), at - } - fmt.Fprint(out, "[", timestr, "] [", levelStrings[rec.Level], "] ", rec.Message, "\n") - } -} - -// This is the ConsoleLogWriter's output method. This will block if the output -// buffer is full. -func (w ConsoleLogWriter) LogWrite(rec *LogRecord) { - w <- rec -} - -// Close stops the logger from sending messages to standard output. Attempts to -// send log messages to this logger after a Close have undefined behavior. -func (w ConsoleLogWriter) Close() { - close(w) -} diff --git a/Godeps/_workspace/src/code.google.com/p/log4go/wrapper.go b/Godeps/_workspace/src/code.google.com/p/log4go/wrapper.go deleted file mode 100644 index 10ecd88e6..000000000 --- a/Godeps/_workspace/src/code.google.com/p/log4go/wrapper.go +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright (C) 2010, Kyle Lemons . All rights reserved. - -package log4go - -import ( - "errors" - "os" - "fmt" - "strings" -) - -var ( - Global Logger -) - -func init() { - Global = NewDefaultLogger(DEBUG) -} - -// Wrapper for (*Logger).LoadConfiguration -func LoadConfiguration(filename string) { - Global.LoadConfiguration(filename) -} - -// Wrapper for (*Logger).AddFilter -func AddFilter(name string, lvl level, writer LogWriter) { - Global.AddFilter(name, lvl, writer) -} - -// Wrapper for (*Logger).Close (closes and removes all logwriters) -func Close() { - Global.Close() -} - -func Crash(args ...interface{}) { - if len(args) > 0 { - Global.intLogf(CRITICAL, strings.Repeat(" %v", len(args))[1:], args...) - } - panic(args) -} - -// Logs the given message and crashes the program -func Crashf(format string, args ...interface{}) { - Global.intLogf(CRITICAL, format, args...) - Global.Close() // so that hopefully the messages get logged - panic(fmt.Sprintf(format, args...)) -} - -// Compatibility with `log` -func Exit(args ...interface{}) { - if len(args) > 0 { - Global.intLogf(ERROR, strings.Repeat(" %v", len(args))[1:], args...) - } - Global.Close() // so that hopefully the messages get logged - os.Exit(0) -} - -// Compatibility with `log` -func Exitf(format string, args ...interface{}) { - Global.intLogf(ERROR, format, args...) - Global.Close() // so that hopefully the messages get logged - os.Exit(0) -} - -// Compatibility with `log` -func Stderr(args ...interface{}) { - if len(args) > 0 { - Global.intLogf(ERROR, strings.Repeat(" %v", len(args))[1:], args...) - } -} - -// Compatibility with `log` -func Stderrf(format string, args ...interface{}) { - Global.intLogf(ERROR, format, args...) -} - -// Compatibility with `log` -func Stdout(args ...interface{}) { - if len(args) > 0 { - Global.intLogf(INFO, strings.Repeat(" %v", len(args))[1:], args...) - } -} - -// Compatibility with `log` -func Stdoutf(format string, args ...interface{}) { - Global.intLogf(INFO, format, args...) -} - -// Send a log message manually -// Wrapper for (*Logger).Log -func Log(lvl level, source, message string) { - Global.Log(lvl, source, message) -} - -// Send a formatted log message easily -// Wrapper for (*Logger).Logf -func Logf(lvl level, format string, args ...interface{}) { - Global.intLogf(lvl, format, args...) -} - -// Send a closure log message -// Wrapper for (*Logger).Logc -func Logc(lvl level, closure func() string) { - Global.intLogc(lvl, closure) -} - -// Utility for finest log messages (see Debug() for parameter explanation) -// Wrapper for (*Logger).Finest -func Finest(arg0 interface{}, args ...interface{}) { - const ( - lvl = FINEST - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - Global.intLogf(lvl, first, args...) - case func() string: - // Log the closure (no other arguments used) - Global.intLogc(lvl, first) - default: - // Build a format string so that it will be similar to Sprint - Global.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) - } -} - -// Utility for fine log messages (see Debug() for parameter explanation) -// Wrapper for (*Logger).Fine -func Fine(arg0 interface{}, args ...interface{}) { - const ( - lvl = FINE - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - Global.intLogf(lvl, first, args...) - case func() string: - // Log the closure (no other arguments used) - Global.intLogc(lvl, first) - default: - // Build a format string so that it will be similar to Sprint - Global.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) - } -} - -// Utility for debug log messages -// When given a string as the first argument, this behaves like Logf but with the DEBUG log level (e.g. the first argument is interpreted as a format for the latter arguments) -// When given a closure of type func()string, this logs the string returned by the closure iff it will be logged. The closure runs at most one time. -// When given anything else, the log message will be each of the arguments formatted with %v and separated by spaces (ala Sprint). -// Wrapper for (*Logger).Debug -func Debug(arg0 interface{}, args ...interface{}) { - const ( - lvl = DEBUG - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - Global.intLogf(lvl, first, args...) - case func() string: - // Log the closure (no other arguments used) - Global.intLogc(lvl, first) - default: - // Build a format string so that it will be similar to Sprint - Global.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) - } -} - -// Utility for trace log messages (see Debug() for parameter explanation) -// Wrapper for (*Logger).Trace -func Trace(arg0 interface{}, args ...interface{}) { - const ( - lvl = TRACE - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - Global.intLogf(lvl, first, args...) - case func() string: - // Log the closure (no other arguments used) - Global.intLogc(lvl, first) - default: - // Build a format string so that it will be similar to Sprint - Global.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) - } -} - -// Utility for info log messages (see Debug() for parameter explanation) -// Wrapper for (*Logger).Info -func Info(arg0 interface{}, args ...interface{}) { - const ( - lvl = INFO - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - Global.intLogf(lvl, first, args...) - case func() string: - // Log the closure (no other arguments used) - Global.intLogc(lvl, first) - default: - // Build a format string so that it will be similar to Sprint - Global.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) - } -} - -// Utility for warn log messages (returns an error for easy function returns) (see Debug() for parameter explanation) -// These functions will execute a closure exactly once, to build the error message for the return -// Wrapper for (*Logger).Warn -func Warn(arg0 interface{}, args ...interface{}) error { - const ( - lvl = WARNING - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - Global.intLogf(lvl, first, args...) - return errors.New(fmt.Sprintf(first, args...)) - case func() string: - // Log the closure (no other arguments used) - str := first() - Global.intLogf(lvl, "%s", str) - return errors.New(str) - default: - // Build a format string so that it will be similar to Sprint - Global.intLogf(lvl, fmt.Sprint(first)+strings.Repeat(" %v", len(args)), args...) - return errors.New(fmt.Sprint(first) + fmt.Sprintf(strings.Repeat(" %v", len(args)), args...)) - } - return nil -} - -// Utility for error log messages (returns an error for easy function returns) (see Debug() for parameter explanation) -// These functions will execute a closure exactly once, to build the error message for the return -// Wrapper for (*Logger).Error -func Error(arg0 interface{}, args ...interface{}) error { - const ( - lvl = ERROR - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - Global.intLogf(lvl, first, args...) - return errors.New(fmt.Sprintf(first, args...)) - case func() string: - // Log the closure (no other arguments used) - str := first() - Global.intLogf(lvl, "%s", str) - return errors.New(str) - default: - // Build a format string so that it will be similar to Sprint - Global.intLogf(lvl, fmt.Sprint(first)+strings.Repeat(" %v", len(args)), args...) - return errors.New(fmt.Sprint(first) + fmt.Sprintf(strings.Repeat(" %v", len(args)), args...)) - } - return nil -} - -// Utility for critical log messages (returns an error for easy function returns) (see Debug() for parameter explanation) -// These functions will execute a closure exactly once, to build the error message for the return -// Wrapper for (*Logger).Critical -func Critical(arg0 interface{}, args ...interface{}) error { - const ( - lvl = CRITICAL - ) - switch first := arg0.(type) { - case string: - // Use the string as a format string - Global.intLogf(lvl, first, args...) - return errors.New(fmt.Sprintf(first, args...)) - case func() string: - // Log the closure (no other arguments used) - str := first() - Global.intLogf(lvl, "%s", str) - return errors.New(str) - default: - // Build a format string so that it will be similar to Sprint - Global.intLogf(lvl, fmt.Sprint(first)+strings.Repeat(" %v", len(args)), args...) - return errors.New(fmt.Sprint(first) + fmt.Sprintf(strings.Repeat(" %v", len(args)), args...)) - } - return nil -} diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/.gitignore b/Godeps/_workspace/src/github.com/alecthomas/log4go/.gitignore new file mode 100644 index 000000000..f6207cd8a --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/.gitignore @@ -0,0 +1,2 @@ +*.sw[op] +.DS_Store diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/LICENSE b/Godeps/_workspace/src/github.com/alecthomas/log4go/LICENSE new file mode 100644 index 000000000..7093402bf --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/LICENSE @@ -0,0 +1,13 @@ +Copyright (c) 2010, Kyle Lemons . All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/README b/Godeps/_workspace/src/github.com/alecthomas/log4go/README new file mode 100644 index 000000000..16d80ecb7 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/README @@ -0,0 +1,12 @@ +Please see http://log4go.googlecode.com/ + +Installation: +- Run `goinstall log4go.googlecode.com/hg` + +Usage: +- Add the following import: +import l4g "log4go.googlecode.com/hg" + +Acknowledgements: +- pomack + For providing awesome patches to bring log4go up to the latest Go spec diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/config.go b/Godeps/_workspace/src/github.com/alecthomas/log4go/config.go new file mode 100644 index 000000000..577c3eb2f --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/config.go @@ -0,0 +1,288 @@ +// Copyright (C) 2010, Kyle Lemons . All rights reserved. + +package log4go + +import ( + "encoding/xml" + "fmt" + "io/ioutil" + "os" + "strconv" + "strings" +) + +type xmlProperty struct { + Name string `xml:"name,attr"` + Value string `xml:",chardata"` +} + +type xmlFilter struct { + Enabled string `xml:"enabled,attr"` + Tag string `xml:"tag"` + Level string `xml:"level"` + Type string `xml:"type"` + Property []xmlProperty `xml:"property"` +} + +type xmlLoggerConfig struct { + Filter []xmlFilter `xml:"filter"` +} + +// Load XML configuration; see examples/example.xml for documentation +func (log Logger) LoadConfiguration(filename string) { + log.Close() + + // Open the configuration file + fd, err := os.Open(filename) + if err != nil { + fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Could not open %q for reading: %s\n", filename, err) + os.Exit(1) + } + + contents, err := ioutil.ReadAll(fd) + if err != nil { + fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Could not read %q: %s\n", filename, err) + os.Exit(1) + } + + xc := new(xmlLoggerConfig) + if err := xml.Unmarshal(contents, xc); err != nil { + fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Could not parse XML configuration in %q: %s\n", filename, err) + os.Exit(1) + } + + for _, xmlfilt := range xc.Filter { + var filt LogWriter + var lvl Level + bad, good, enabled := false, true, false + + // Check required children + if len(xmlfilt.Enabled) == 0 { + fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required attribute %s for filter missing in %s\n", "enabled", filename) + bad = true + } else { + enabled = xmlfilt.Enabled != "false" + } + if len(xmlfilt.Tag) == 0 { + fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required child <%s> for filter missing in %s\n", "tag", filename) + bad = true + } + if len(xmlfilt.Type) == 0 { + fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required child <%s> for filter missing in %s\n", "type", filename) + bad = true + } + if len(xmlfilt.Level) == 0 { + fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required child <%s> for filter missing in %s\n", "level", filename) + bad = true + } + + switch xmlfilt.Level { + case "FINEST": + lvl = FINEST + case "FINE": + lvl = FINE + case "DEBUG": + lvl = DEBUG + case "TRACE": + lvl = TRACE + case "INFO": + lvl = INFO + case "WARNING": + lvl = WARNING + case "ERROR": + lvl = ERROR + case "CRITICAL": + lvl = CRITICAL + default: + fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required child <%s> for filter has unknown value in %s: %s\n", "level", filename, xmlfilt.Level) + bad = true + } + + // Just so all of the required attributes are errored at the same time if missing + if bad { + os.Exit(1) + } + + switch xmlfilt.Type { + case "console": + filt, good = xmlToConsoleLogWriter(filename, xmlfilt.Property, enabled) + case "file": + filt, good = xmlToFileLogWriter(filename, xmlfilt.Property, enabled) + case "xml": + filt, good = xmlToXMLLogWriter(filename, xmlfilt.Property, enabled) + case "socket": + filt, good = xmlToSocketLogWriter(filename, xmlfilt.Property, enabled) + default: + fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Could not load XML configuration in %s: unknown filter type \"%s\"\n", filename, xmlfilt.Type) + os.Exit(1) + } + + // Just so all of the required params are errored at the same time if wrong + if !good { + os.Exit(1) + } + + // If we're disabled (syntax and correctness checks only), don't add to logger + if !enabled { + continue + } + + log[xmlfilt.Tag] = &Filter{lvl, filt} + } +} + +func xmlToConsoleLogWriter(filename string, props []xmlProperty, enabled bool) (*ConsoleLogWriter, bool) { + // Parse properties + for _, prop := range props { + switch prop.Name { + default: + fmt.Fprintf(os.Stderr, "LoadConfiguration: Warning: Unknown property \"%s\" for console filter in %s\n", prop.Name, filename) + } + } + + // If it's disabled, we're just checking syntax + if !enabled { + return nil, true + } + + return NewConsoleLogWriter(), true +} + +// Parse a number with K/M/G suffixes based on thousands (1000) or 2^10 (1024) +func strToNumSuffix(str string, mult int) int { + num := 1 + if len(str) > 1 { + switch str[len(str)-1] { + case 'G', 'g': + num *= mult + fallthrough + case 'M', 'm': + num *= mult + fallthrough + case 'K', 'k': + num *= mult + str = str[0 : len(str)-1] + } + } + parsed, _ := strconv.Atoi(str) + return parsed * num +} +func xmlToFileLogWriter(filename string, props []xmlProperty, enabled bool) (*FileLogWriter, bool) { + file := "" + format := "[%D %T] [%L] (%S) %M" + maxlines := 0 + maxsize := 0 + daily := false + rotate := false + + // Parse properties + for _, prop := range props { + switch prop.Name { + case "filename": + file = strings.Trim(prop.Value, " \r\n") + case "format": + format = strings.Trim(prop.Value, " \r\n") + case "maxlines": + maxlines = strToNumSuffix(strings.Trim(prop.Value, " \r\n"), 1000) + case "maxsize": + maxsize = strToNumSuffix(strings.Trim(prop.Value, " \r\n"), 1024) + case "daily": + daily = strings.Trim(prop.Value, " \r\n") != "false" + case "rotate": + rotate = strings.Trim(prop.Value, " \r\n") != "false" + default: + fmt.Fprintf(os.Stderr, "LoadConfiguration: Warning: Unknown property \"%s\" for file filter in %s\n", prop.Name, filename) + } + } + + // Check properties + if len(file) == 0 { + fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required property \"%s\" for file filter missing in %s\n", "filename", filename) + return nil, false + } + + // If it's disabled, we're just checking syntax + if !enabled { + return nil, true + } + + flw := NewFileLogWriter(file, rotate) + flw.SetFormat(format) + flw.SetRotateLines(maxlines) + flw.SetRotateSize(maxsize) + flw.SetRotateDaily(daily) + return flw, true +} + +func xmlToXMLLogWriter(filename string, props []xmlProperty, enabled bool) (*FileLogWriter, bool) { + file := "" + maxrecords := 0 + maxsize := 0 + daily := false + rotate := false + + // Parse properties + for _, prop := range props { + switch prop.Name { + case "filename": + file = strings.Trim(prop.Value, " \r\n") + case "maxrecords": + maxrecords = strToNumSuffix(strings.Trim(prop.Value, " \r\n"), 1000) + case "maxsize": + maxsize = strToNumSuffix(strings.Trim(prop.Value, " \r\n"), 1024) + case "daily": + daily = strings.Trim(prop.Value, " \r\n") != "false" + case "rotate": + rotate = strings.Trim(prop.Value, " \r\n") != "false" + default: + fmt.Fprintf(os.Stderr, "LoadConfiguration: Warning: Unknown property \"%s\" for xml filter in %s\n", prop.Name, filename) + } + } + + // Check properties + if len(file) == 0 { + fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required property \"%s\" for xml filter missing in %s\n", "filename", filename) + return nil, false + } + + // If it's disabled, we're just checking syntax + if !enabled { + return nil, true + } + + xlw := NewXMLLogWriter(file, rotate) + xlw.SetRotateLines(maxrecords) + xlw.SetRotateSize(maxsize) + xlw.SetRotateDaily(daily) + return xlw, true +} + +func xmlToSocketLogWriter(filename string, props []xmlProperty, enabled bool) (SocketLogWriter, bool) { + endpoint := "" + protocol := "udp" + + // Parse properties + for _, prop := range props { + switch prop.Name { + case "endpoint": + endpoint = strings.Trim(prop.Value, " \r\n") + case "protocol": + protocol = strings.Trim(prop.Value, " \r\n") + default: + fmt.Fprintf(os.Stderr, "LoadConfiguration: Warning: Unknown property \"%s\" for file filter in %s\n", prop.Name, filename) + } + } + + // Check properties + if len(endpoint) == 0 { + fmt.Fprintf(os.Stderr, "LoadConfiguration: Error: Required property \"%s\" for file filter missing in %s\n", "endpoint", filename) + return nil, false + } + + // If it's disabled, we're just checking syntax + if !enabled { + return nil, true + } + + return NewSocketLogWriter(protocol, endpoint), true +} diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/ConsoleLogWriter_Manual.go b/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/ConsoleLogWriter_Manual.go new file mode 100644 index 000000000..698dd332d --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/ConsoleLogWriter_Manual.go @@ -0,0 +1,14 @@ +package main + +import ( + "time" +) + +import l4g "code.google.com/p/log4go" + +func main() { + log := l4g.NewLogger() + defer log.Close() + log.AddFilter("stdout", l4g.DEBUG, l4g.NewConsoleLogWriter()) + log.Info("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02")) +} diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/FileLogWriter_Manual.go b/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/FileLogWriter_Manual.go new file mode 100644 index 000000000..efd596aa6 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/FileLogWriter_Manual.go @@ -0,0 +1,57 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "os" + "time" +) + +import l4g "code.google.com/p/log4go" + +const ( + filename = "flw.log" +) + +func main() { + // Get a new logger instance + log := l4g.NewLogger() + + // Create a default logger that is logging messages of FINE or higher + log.AddFilter("file", l4g.FINE, l4g.NewFileLogWriter(filename, false)) + log.Close() + + /* Can also specify manually via the following: (these are the defaults) */ + flw := l4g.NewFileLogWriter(filename, false) + flw.SetFormat("[%D %T] [%L] (%S) %M") + flw.SetRotate(false) + flw.SetRotateSize(0) + flw.SetRotateLines(0) + flw.SetRotateDaily(false) + log.AddFilter("file", l4g.FINE, flw) + + // Log some experimental messages + log.Finest("Everything is created now (notice that I will not be printing to the file)") + log.Info("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02")) + log.Critical("Time to close out!") + + // Close the log + log.Close() + + // Print what was logged to the file (yes, I know I'm skipping error checking) + fd, _ := os.Open(filename) + in := bufio.NewReader(fd) + fmt.Print("Messages logged to file were: (line numbers not included)\n") + for lineno := 1; ; lineno++ { + line, err := in.ReadString('\n') + if err == io.EOF { + break + } + fmt.Printf("%3d:\t%s", lineno, line) + } + fd.Close() + + // Remove the file so it's not lying around + os.Remove(filename) +} diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/SimpleNetLogServer.go b/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/SimpleNetLogServer.go new file mode 100644 index 000000000..83c80ad12 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/SimpleNetLogServer.go @@ -0,0 +1,42 @@ +package main + +import ( + "flag" + "fmt" + "net" + "os" +) + +var ( + port = flag.String("p", "12124", "Port number to listen on") +) + +func e(err error) { + if err != nil { + fmt.Printf("Erroring out: %s\n", err) + os.Exit(1) + } +} + +func main() { + flag.Parse() + + // Bind to the port + bind, err := net.ResolveUDPAddr("0.0.0.0:" + *port) + e(err) + + // Create listener + listener, err := net.ListenUDP("udp", bind) + e(err) + + fmt.Printf("Listening to port %s...\n", *port) + for { + // read into a new buffer + buffer := make([]byte, 1024) + _, _, err := listener.ReadFrom(buffer) + e(err) + + // log to standard output + fmt.Println(string(buffer)) + } +} diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/SocketLogWriter_Manual.go b/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/SocketLogWriter_Manual.go new file mode 100644 index 000000000..400b698ca --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/SocketLogWriter_Manual.go @@ -0,0 +1,18 @@ +package main + +import ( + "time" +) + +import l4g "code.google.com/p/log4go" + +func main() { + log := l4g.NewLogger() + log.AddFilter("network", l4g.FINEST, l4g.NewSocketLogWriter("udp", "192.168.1.255:12124")) + + // Run `nc -u -l -p 12124` or similar before you run this to see the following message + log.Info("The time is now: %s", time.Now().Format("15:04:05 MST 2006/01/02")) + + // This makes sure the output stream buffer is written + log.Close() +} diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/XMLConfigurationExample.go b/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/XMLConfigurationExample.go new file mode 100644 index 000000000..164c2add4 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/XMLConfigurationExample.go @@ -0,0 +1,13 @@ +package main + +import l4g "code.google.com/p/log4go" + +func main() { + // Load the configuration (isn't this easy?) + l4g.LoadConfiguration("example.xml") + + // And now we're ready! + l4g.Finest("This will only go to those of you really cool UDP kids! If you change enabled=true.") + l4g.Debug("Oh no! %d + %d = %d!", 2, 2, 2+2) + l4g.Info("About that time, eh chaps?") +} diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/example.xml b/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/example.xml new file mode 100644 index 000000000..e791278ce --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/examples/example.xml @@ -0,0 +1,47 @@ + + + stdout + console + + DEBUG + + + file + file + FINEST + test.log + + [%D %T] [%L] (%S) %M + false + 0M + 0K + true + + + xmllog + xml + TRACE + trace.xml + true + 100M + 6K + false + + + donotopen + socket + FINEST + 192.168.1.255:12124 + udp + + diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/filelog.go b/Godeps/_workspace/src/github.com/alecthomas/log4go/filelog.go new file mode 100644 index 000000000..ee0ab0c04 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/filelog.go @@ -0,0 +1,264 @@ +// Copyright (C) 2010, Kyle Lemons . All rights reserved. + +package log4go + +import ( + "fmt" + "os" + "time" +) + +// This log writer sends output to a file +type FileLogWriter struct { + rec chan *LogRecord + rot chan bool + + // The opened file + filename string + file *os.File + + // The logging format + format string + + // File header/trailer + header, trailer string + + // Rotate at linecount + maxlines int + maxlines_curlines int + + // Rotate at size + maxsize int + maxsize_cursize int + + // Rotate daily + daily bool + daily_opendate int + + // Keep old logfiles (.001, .002, etc) + rotate bool + maxbackup int +} + +// This is the FileLogWriter's output method +func (w *FileLogWriter) LogWrite(rec *LogRecord) { + w.rec <- rec +} + +func (w *FileLogWriter) Close() { + close(w.rec) + w.file.Sync() +} + +// NewFileLogWriter creates a new LogWriter which writes to the given file and +// has rotation enabled if rotate is true. +// +// If rotate is true, any time a new log file is opened, the old one is renamed +// with a .### extension to preserve it. The various Set* methods can be used +// to configure log rotation based on lines, size, and daily. +// +// The standard log-line format is: +// [%D %T] [%L] (%S) %M +func NewFileLogWriter(fname string, rotate bool) *FileLogWriter { + w := &FileLogWriter{ + rec: make(chan *LogRecord, LogBufferLength), + rot: make(chan bool), + filename: fname, + format: "[%D %T] [%L] (%S) %M", + rotate: rotate, + maxbackup: 999, + } + + // open the file for the first time + if err := w.intRotate(); err != nil { + fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err) + return nil + } + + go func() { + defer func() { + if w.file != nil { + fmt.Fprint(w.file, FormatLogRecord(w.trailer, &LogRecord{Created: time.Now()})) + w.file.Close() + } + }() + + for { + select { + case <-w.rot: + if err := w.intRotate(); err != nil { + fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err) + return + } + case rec, ok := <-w.rec: + if !ok { + return + } + 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) { + if err := w.intRotate(); err != nil { + fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err) + return + } + } + + // Perform the write + n, err := fmt.Fprint(w.file, FormatLogRecord(w.format, rec)) + if err != nil { + fmt.Fprintf(os.Stderr, "FileLogWriter(%q): %s\n", w.filename, err) + return + } + + // Update the counts + w.maxlines_curlines++ + w.maxsize_cursize += n + } + } + }() + + return w +} + +// Request that the logs rotate +func (w *FileLogWriter) Rotate() { + w.rot <- true +} + +// If this is called in a threaded context, it MUST be synchronized +func (w *FileLogWriter) intRotate() error { + // Close any log file that may be open + if w.file != nil { + fmt.Fprint(w.file, FormatLogRecord(w.trailer, &LogRecord{Created: time.Now()})) + w.file.Close() + } + + // If we are keeping log files, move it to the next available number + if w.rotate { + _, err := os.Lstat(w.filename) + if err == nil { // file exists + // Find the next available number + num := 1 + fname := "" + if w.daily && time.Now().Day() != w.daily_opendate { + yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02") + + for ; err == nil && num <= 999; num++ { + fname = w.filename + fmt.Sprintf(".%s.%03d", yesterday, num) + _, err = os.Lstat(fname) + } + // return error if the last file checked still existed + if err == nil { + return fmt.Errorf("Rotate: Cannot find free log number to rename %s\n", w.filename) + } + } else { + num = w.maxbackup - 1 + for ; num >= 1; num-- { + fname = w.filename + fmt.Sprintf(".%d", num) + nfname := w.filename + fmt.Sprintf(".%d", num+1) + _, err = os.Lstat(fname) + if err == nil { + os.Rename(fname, nfname) + } + } + } + + w.file.Close() + // Rename the file to its newfound home + err = os.Rename(w.filename, fname) + if err != nil { + return fmt.Errorf("Rotate: %s\n", err) + } + } + } + + // Open the log file + fd, err := os.OpenFile(w.filename, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0660) + if err != nil { + return err + } + w.file = fd + + now := time.Now() + fmt.Fprint(w.file, FormatLogRecord(w.header, &LogRecord{Created: now})) + + // Set the daily open date to the current date + w.daily_opendate = now.Day() + + // initialize rotation values + w.maxlines_curlines = 0 + w.maxsize_cursize = 0 + + return nil +} + +// Set the logging format (chainable). Must be called before the first log +// message is written. +func (w *FileLogWriter) SetFormat(format string) *FileLogWriter { + w.format = format + return w +} + +// Set the logfile header and footer (chainable). Must be called before the first log +// message is written. These are formatted similar to the FormatLogRecord (e.g. +// you can use %D and %T in your header/footer for date and time). +func (w *FileLogWriter) SetHeadFoot(head, foot string) *FileLogWriter { + w.header, w.trailer = head, foot + if w.maxlines_curlines == 0 { + fmt.Fprint(w.file, FormatLogRecord(w.header, &LogRecord{Created: time.Now()})) + } + return w +} + +// Set rotate at linecount (chainable). Must be called before the first log +// message is written. +func (w *FileLogWriter) SetRotateLines(maxlines int) *FileLogWriter { + //fmt.Fprintf(os.Stderr, "FileLogWriter.SetRotateLines: %v\n", maxlines) + w.maxlines = maxlines + return w +} + +// Set rotate at size (chainable). Must be called before the first log message +// is written. +func (w *FileLogWriter) SetRotateSize(maxsize int) *FileLogWriter { + //fmt.Fprintf(os.Stderr, "FileLogWriter.SetRotateSize: %v\n", maxsize) + w.maxsize = maxsize + return w +} + +// Set rotate daily (chainable). Must be called before the first log message is +// written. +func (w *FileLogWriter) SetRotateDaily(daily bool) *FileLogWriter { + //fmt.Fprintf(os.Stderr, "FileLogWriter.SetRotateDaily: %v\n", daily) + w.daily = daily + return w +} + +// Set max backup files. Must be called before the first log message +// is written. +func (w *FileLogWriter) SetRotateMaxBackup(maxbackup int) *FileLogWriter { + w.maxbackup = maxbackup + return w +} + +// SetRotate changes whether or not the old logs are kept. (chainable) Must be +// called before the first log message is written. If rotate is false, the +// files are overwritten; otherwise, they are rotated to another file before the +// new log is opened. +func (w *FileLogWriter) SetRotate(rotate bool) *FileLogWriter { + //fmt.Fprintf(os.Stderr, "FileLogWriter.SetRotate: %v\n", rotate) + w.rotate = rotate + return w +} + +// NewXMLLogWriter is a utility method for creating a FileLogWriter set up to +// output XML record log messages instead of line-based ones. +func NewXMLLogWriter(fname string, rotate bool) *FileLogWriter { + return NewFileLogWriter(fname, rotate).SetFormat( + ` + %D %T + %S + %M + `).SetHeadFoot("", "") +} diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/log4go.go b/Godeps/_workspace/src/github.com/alecthomas/log4go/log4go.go new file mode 100644 index 000000000..822e890cc --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/log4go.go @@ -0,0 +1,484 @@ +// Copyright (C) 2010, Kyle Lemons . All rights reserved. + +// Package log4go provides level-based and highly configurable logging. +// +// Enhanced Logging +// +// This is inspired by the logging functionality in Java. Essentially, you create a Logger +// object and create output filters for it. You can send whatever you want to the Logger, +// and it will filter that based on your settings and send it to the outputs. This way, you +// can put as much debug code in your program as you want, and when you're done you can filter +// out the mundane messages so only the important ones show up. +// +// Utility functions are provided to make life easier. Here is some example code to get started: +// +// log := log4go.NewLogger() +// log.AddFilter("stdout", log4go.DEBUG, log4go.NewConsoleLogWriter()) +// log.AddFilter("log", log4go.FINE, log4go.NewFileLogWriter("example.log", true)) +// log.Info("The time is now: %s", time.LocalTime().Format("15:04:05 MST 2006/01/02")) +// +// The first two lines can be combined with the utility NewDefaultLogger: +// +// log := log4go.NewDefaultLogger(log4go.DEBUG) +// log.AddFilter("log", log4go.FINE, log4go.NewFileLogWriter("example.log", true)) +// log.Info("The time is now: %s", time.LocalTime().Format("15:04:05 MST 2006/01/02")) +// +// Usage notes: +// - The ConsoleLogWriter does not display the source of the message to standard +// output, but the FileLogWriter does. +// - The utility functions (Info, Debug, Warn, etc) derive their source from the +// calling function, and this incurs extra overhead. +// +// Changes from 2.0: +// - The external interface has remained mostly stable, but a lot of the +// internals have been changed, so if you depended on any of this or created +// your own LogWriter, then you will probably have to update your code. In +// particular, Logger is now a map and ConsoleLogWriter is now a channel +// behind-the-scenes, and the LogWrite method no longer has return values. +// +// Future work: (please let me know if you think I should work on any of these particularly) +// - Log file rotation +// - Logging configuration files ala log4j +// - Have the ability to remove filters? +// - Have GetInfoChannel, GetDebugChannel, etc return a chan string that allows +// for another method of logging +// - Add an XML filter type +package log4go + +import ( + "errors" + "fmt" + "os" + "runtime" + "strings" + "time" +) + +// Version information +const ( + L4G_VERSION = "log4go-v3.0.1" + L4G_MAJOR = 3 + L4G_MINOR = 0 + L4G_BUILD = 1 +) + +/****** Constants ******/ + +// These are the integer logging levels used by the logger +type Level int + +const ( + FINEST Level = iota + FINE + DEBUG + TRACE + INFO + WARNING + ERROR + CRITICAL +) + +// Logging level strings +var ( + 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)] +} + +/****** Variables ******/ +var ( + // 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 +} + +/****** 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 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 ******/ + +// A Filter represents the log level below which no log records are written to +// the associated LogWriter. +type Filter struct { + Level Level + LogWriter +} + +// A Logger represents a collection of Filters through which log messages are +// written. +type Logger map[string]*Filter + +// Create a new logger. +// +// DEPRECATED: Use make(Logger) instead. +func NewLogger() 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 +// or above lvl to standard output. +// +// DEPRECATED: use NewDefaultLogger instead. +func NewConsoleLogger(lvl Level) Logger { + os.Stderr.WriteString("warning: use of deprecated NewConsoleLogger\n") + return Logger{ + "stdout": &Filter{lvl, 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()}, + } +} + +// Closes all log writers in preparation for exiting the program or a +// reconfiguration of logging. Calling this is not really imperative, unless +// 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) + } +} + +// 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 +} + +/******* 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) + } +} + +// 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) + } +} + +// 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) + } +} + +// 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...) +} + +// 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) +} + +// 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...) + } +} + +// 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...) + } +} + +// Debug is a utility method for debug log messages. +// The behavior of Debug depends on the first argument: +// - arg0 is a string +// When given a string as the first argument, this behaves like Logf but with +// the DEBUG log level: the first argument is interpreted as a format for the +// latter arguments. +// - arg0 is a func()string +// When given a closure of type func()string, this logs the string returned by +// the closure iff it will be logged. The closure runs at most one time. +// - arg0 is 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...) + } +} + +// 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...) + } +} + +// 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...) + } +} + +// Warn logs a message at the warning log level and returns the formatted error. +// At the warning level and higher, there is no performance benefit if the +// message is not actually logged, because all formats are processed and all +// 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) +} + +// 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) +} + +// 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) +} diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/pattlog.go b/Godeps/_workspace/src/github.com/alecthomas/log4go/pattlog.go new file mode 100644 index 000000000..82b4e36b1 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/pattlog.go @@ -0,0 +1,126 @@ +// Copyright (C) 2010, Kyle Lemons . All rights reserved. + +package log4go + +import ( + "bytes" + "fmt" + "io" + "strings" +) + +const ( + FORMAT_DEFAULT = "[%D %T] [%L] (%S) %M" + FORMAT_SHORT = "[%t %d] [%L] %M" + FORMAT_ABBREV = "[%L] %M" +) + +type formatCacheType struct { + LastUpdateSeconds int64 + shortTime, shortDate string + longTime, longDate string +} + +var formatCache = &formatCacheType{} + +// Known format codes: +// %T - Time (15:04:05 MST) +// %t - Time (15:04) +// %D - Date (2006/01/02) +// %d - Date (01/02/06) +// %L - Level (FNST, FINE, DEBG, TRAC, WARN, EROR, CRIT) +// %S - Source +// %M - Message +// Ignores unknown formats +// Recommended: "[%D %T] [%L] (%S) %M" +func FormatLogRecord(format string, rec *LogRecord) string { + if rec == nil { + return "" + } + if len(format) == 0 { + return "" + } + + out := bytes.NewBuffer(make([]byte, 0, 64)) + secs := rec.Created.UnixNano() / 1e9 + + cache := *formatCache + if cache.LastUpdateSeconds != secs { + month, day, year := rec.Created.Month(), rec.Created.Day(), rec.Created.Year() + hour, minute, second := rec.Created.Hour(), rec.Created.Minute(), rec.Created.Second() + zone, _ := rec.Created.Zone() + updated := &formatCacheType{ + LastUpdateSeconds: secs, + shortTime: fmt.Sprintf("%02d:%02d", hour, minute), + shortDate: fmt.Sprintf("%02d/%02d/%02d", day, month, year%100), + longTime: fmt.Sprintf("%02d:%02d:%02d %s", hour, minute, second, zone), + longDate: fmt.Sprintf("%04d/%02d/%02d", year, month, day), + } + cache = *updated + formatCache = updated + } + + // Split the string into pieces by % signs + pieces := bytes.Split([]byte(format), []byte{'%'}) + + // Iterate over the pieces, replacing known formats + for i, piece := range pieces { + if i > 0 && len(piece) > 0 { + switch piece[0] { + case 'T': + out.WriteString(cache.longTime) + case 't': + out.WriteString(cache.shortTime) + case 'D': + out.WriteString(cache.longDate) + case 'd': + out.WriteString(cache.shortDate) + case 'L': + out.WriteString(levelStrings[rec.Level]) + case 'S': + out.WriteString(rec.Source) + case 's': + slice := strings.Split(rec.Source, "/") + out.WriteString(slice[len(slice)-1]) + case 'M': + out.WriteString(rec.Message) + } + if len(piece) > 1 { + out.Write(piece[1:]) + } + } else if len(piece) > 0 { + out.Write(piece) + } + } + out.WriteByte('\n') + + return out.String() +} + +// This is the standard writer that prints to standard output. +type FormatLogWriter chan *LogRecord + +// This creates a new FormatLogWriter +func NewFormatLogWriter(out io.Writer, format string) FormatLogWriter { + records := make(FormatLogWriter, LogBufferLength) + go records.run(out, format) + return records +} + +func (w FormatLogWriter) run(out io.Writer, format string) { + for rec := range w { + fmt.Fprint(out, FormatLogRecord(format, rec)) + } +} + +// This is the FormatLogWriter's output method. This will block if the output +// buffer is full. +func (w FormatLogWriter) LogWrite(rec *LogRecord) { + w <- rec +} + +// Close stops the logger from sending messages to standard output. Attempts to +// send log messages to this logger after a Close have undefined behavior. +func (w FormatLogWriter) Close() { + close(w) +} diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/socklog.go b/Godeps/_workspace/src/github.com/alecthomas/log4go/socklog.go new file mode 100644 index 000000000..1d224a99d --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/socklog.go @@ -0,0 +1,57 @@ +// Copyright (C) 2010, Kyle Lemons . All rights reserved. + +package log4go + +import ( + "encoding/json" + "fmt" + "net" + "os" +) + +// This log writer sends output to a socket +type SocketLogWriter chan *LogRecord + +// This is the SocketLogWriter's output method +func (w SocketLogWriter) LogWrite(rec *LogRecord) { + w <- rec +} + +func (w SocketLogWriter) Close() { + close(w) +} + +func NewSocketLogWriter(proto, hostport string) SocketLogWriter { + sock, err := net.Dial(proto, hostport) + if err != nil { + fmt.Fprintf(os.Stderr, "NewSocketLogWriter(%q): %s\n", hostport, err) + return nil + } + + w := SocketLogWriter(make(chan *LogRecord, LogBufferLength)) + + go func() { + defer func() { + if sock != nil && proto == "tcp" { + sock.Close() + } + }() + + for rec := range w { + // Marshall into JSON + js, err := json.Marshal(rec) + if err != nil { + fmt.Fprint(os.Stderr, "SocketLogWriter(%q): %s", hostport, err) + return + } + + _, err = sock.Write(js) + if err != nil { + fmt.Fprint(os.Stderr, "SocketLogWriter(%q): %s", hostport, err) + return + } + } + }() + + return w +} diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/termlog.go b/Godeps/_workspace/src/github.com/alecthomas/log4go/termlog.go new file mode 100644 index 000000000..8a941e269 --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/termlog.go @@ -0,0 +1,49 @@ +// Copyright (C) 2010, Kyle Lemons . All rights reserved. + +package log4go + +import ( + "fmt" + "io" + "os" + "time" +) + +var stdout io.Writer = os.Stdout + +// This is the standard writer that prints to standard output. +type ConsoleLogWriter struct { + format string + w chan *LogRecord +} + +// This creates a new ConsoleLogWriter +func NewConsoleLogWriter() *ConsoleLogWriter { + consoleWriter := &ConsoleLogWriter{ + format: "[%T %D] [%L] (%S) %M", + w: make(chan *LogRecord, LogBufferLength), + } + go consoleWriter.run(stdout) + return consoleWriter +} +func (c *ConsoleLogWriter) SetFormat(format string) { + c.format = format +} +func (c *ConsoleLogWriter) run(out io.Writer) { + for rec := range c.w { + fmt.Fprint(out, FormatLogRecord(c.format, rec)) + } +} + +// This is the ConsoleLogWriter's output method. This will block if the output +// buffer is full. +func (c *ConsoleLogWriter) LogWrite(rec *LogRecord) { + c.w <- rec +} + +// Close stops the logger from sending messages to standard output. Attempts to +// send log messages to this logger after a Close have undefined behavior. +func (c *ConsoleLogWriter) Close() { + close(c.w) + time.Sleep(50 * time.Millisecond) // Try to give console I/O time to complete +} diff --git a/Godeps/_workspace/src/github.com/alecthomas/log4go/wrapper.go b/Godeps/_workspace/src/github.com/alecthomas/log4go/wrapper.go new file mode 100644 index 000000000..2ae222b0c --- /dev/null +++ b/Godeps/_workspace/src/github.com/alecthomas/log4go/wrapper.go @@ -0,0 +1,278 @@ +// Copyright (C) 2010, Kyle Lemons . All rights reserved. + +package log4go + +import ( + "errors" + "fmt" + "os" + "strings" +) + +var ( + Global Logger +) + +func init() { + Global = NewDefaultLogger(DEBUG) +} + +// Wrapper for (*Logger).LoadConfiguration +func LoadConfiguration(filename string) { + Global.LoadConfiguration(filename) +} + +// Wrapper for (*Logger).AddFilter +func AddFilter(name string, lvl Level, writer LogWriter) { + Global.AddFilter(name, lvl, writer) +} + +// Wrapper for (*Logger).Close (closes and removes all logwriters) +func Close() { + Global.Close() +} + +func Crash(args ...interface{}) { + if len(args) > 0 { + Global.intLogf(CRITICAL, strings.Repeat(" %v", len(args))[1:], args...) + } + panic(args) +} + +// Logs the given message and crashes the program +func Crashf(format string, args ...interface{}) { + Global.intLogf(CRITICAL, format, args...) + Global.Close() // so that hopefully the messages get logged + panic(fmt.Sprintf(format, args...)) +} + +// Compatibility with `log` +func Exit(args ...interface{}) { + if len(args) > 0 { + Global.intLogf(ERROR, strings.Repeat(" %v", len(args))[1:], args...) + } + Global.Close() // so that hopefully the messages get logged + os.Exit(0) +} + +// Compatibility with `log` +func Exitf(format string, args ...interface{}) { + Global.intLogf(ERROR, format, args...) + Global.Close() // so that hopefully the messages get logged + os.Exit(0) +} + +// Compatibility with `log` +func Stderr(args ...interface{}) { + if len(args) > 0 { + Global.intLogf(ERROR, strings.Repeat(" %v", len(args))[1:], args...) + } +} + +// Compatibility with `log` +func Stderrf(format string, args ...interface{}) { + Global.intLogf(ERROR, format, args...) +} + +// Compatibility with `log` +func Stdout(args ...interface{}) { + if len(args) > 0 { + Global.intLogf(INFO, strings.Repeat(" %v", len(args))[1:], args...) + } +} + +// Compatibility with `log` +func Stdoutf(format string, args ...interface{}) { + Global.intLogf(INFO, format, args...) +} + +// Send a log message manually +// Wrapper for (*Logger).Log +func Log(lvl Level, source, message string) { + Global.Log(lvl, source, message) +} + +// Send a formatted log message easily +// Wrapper for (*Logger).Logf +func Logf(lvl Level, format string, args ...interface{}) { + Global.intLogf(lvl, format, args...) +} + +// Send a closure log message +// Wrapper for (*Logger).Logc +func Logc(lvl Level, closure func() string) { + Global.intLogc(lvl, closure) +} + +// Utility for finest log messages (see Debug() for parameter explanation) +// Wrapper for (*Logger).Finest +func Finest(arg0 interface{}, args ...interface{}) { + const ( + lvl = FINEST + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + Global.intLogf(lvl, first, args...) + case func() string: + // Log the closure (no other arguments used) + Global.intLogc(lvl, first) + default: + // Build a format string so that it will be similar to Sprint + Global.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) + } +} + +// Utility for fine log messages (see Debug() for parameter explanation) +// Wrapper for (*Logger).Fine +func Fine(arg0 interface{}, args ...interface{}) { + const ( + lvl = FINE + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + Global.intLogf(lvl, first, args...) + case func() string: + // Log the closure (no other arguments used) + Global.intLogc(lvl, first) + default: + // Build a format string so that it will be similar to Sprint + Global.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) + } +} + +// Utility for debug log messages +// When given a string as the first argument, this behaves like Logf but with the DEBUG log level (e.g. the first argument is interpreted as a format for the latter arguments) +// When given a closure of type func()string, this logs the string returned by the closure iff it will be logged. The closure runs at most one time. +// When given anything else, the log message will be each of the arguments formatted with %v and separated by spaces (ala Sprint). +// Wrapper for (*Logger).Debug +func Debug(arg0 interface{}, args ...interface{}) { + const ( + lvl = DEBUG + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + Global.intLogf(lvl, first, args...) + case func() string: + // Log the closure (no other arguments used) + Global.intLogc(lvl, first) + default: + // Build a format string so that it will be similar to Sprint + Global.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) + } +} + +// Utility for trace log messages (see Debug() for parameter explanation) +// Wrapper for (*Logger).Trace +func Trace(arg0 interface{}, args ...interface{}) { + const ( + lvl = TRACE + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + Global.intLogf(lvl, first, args...) + case func() string: + // Log the closure (no other arguments used) + Global.intLogc(lvl, first) + default: + // Build a format string so that it will be similar to Sprint + Global.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) + } +} + +// Utility for info log messages (see Debug() for parameter explanation) +// Wrapper for (*Logger).Info +func Info(arg0 interface{}, args ...interface{}) { + const ( + lvl = INFO + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + Global.intLogf(lvl, first, args...) + case func() string: + // Log the closure (no other arguments used) + Global.intLogc(lvl, first) + default: + // Build a format string so that it will be similar to Sprint + Global.intLogf(lvl, fmt.Sprint(arg0)+strings.Repeat(" %v", len(args)), args...) + } +} + +// Utility for warn log messages (returns an error for easy function returns) (see Debug() for parameter explanation) +// These functions will execute a closure exactly once, to build the error message for the return +// Wrapper for (*Logger).Warn +func Warn(arg0 interface{}, args ...interface{}) error { + const ( + lvl = WARNING + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + Global.intLogf(lvl, first, args...) + return errors.New(fmt.Sprintf(first, args...)) + case func() string: + // Log the closure (no other arguments used) + str := first() + Global.intLogf(lvl, "%s", str) + return errors.New(str) + default: + // Build a format string so that it will be similar to Sprint + Global.intLogf(lvl, fmt.Sprint(first)+strings.Repeat(" %v", len(args)), args...) + return errors.New(fmt.Sprint(first) + fmt.Sprintf(strings.Repeat(" %v", len(args)), args...)) + } + return nil +} + +// Utility for error log messages (returns an error for easy function returns) (see Debug() for parameter explanation) +// These functions will execute a closure exactly once, to build the error message for the return +// Wrapper for (*Logger).Error +func Error(arg0 interface{}, args ...interface{}) error { + const ( + lvl = ERROR + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + Global.intLogf(lvl, first, args...) + return errors.New(fmt.Sprintf(first, args...)) + case func() string: + // Log the closure (no other arguments used) + str := first() + Global.intLogf(lvl, "%s", str) + return errors.New(str) + default: + // Build a format string so that it will be similar to Sprint + Global.intLogf(lvl, fmt.Sprint(first)+strings.Repeat(" %v", len(args)), args...) + return errors.New(fmt.Sprint(first) + fmt.Sprintf(strings.Repeat(" %v", len(args)), args...)) + } + return nil +} + +// Utility for critical log messages (returns an error for easy function returns) (see Debug() for parameter explanation) +// These functions will execute a closure exactly once, to build the error message for the return +// Wrapper for (*Logger).Critical +func Critical(arg0 interface{}, args ...interface{}) error { + const ( + lvl = CRITICAL + ) + switch first := arg0.(type) { + case string: + // Use the string as a format string + Global.intLogf(lvl, first, args...) + return errors.New(fmt.Sprintf(first, args...)) + case func() string: + // Log the closure (no other arguments used) + str := first() + Global.intLogf(lvl, "%s", str) + return errors.New(str) + default: + // Build a format string so that it will be similar to Sprint + Global.intLogf(lvl, fmt.Sprint(first)+strings.Repeat(" %v", len(args)), args...) + return errors.New(fmt.Sprint(first) + fmt.Sprintf(strings.Repeat(" %v", len(args)), args...)) + } + return nil +} -- cgit v1.2.3-1-g7c22