-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
marc.chua
committed
Apr 5, 2016
0 parents
commit c0978b4
Showing
16 changed files
with
2,262 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Copyright (c) 2010, Kyle Lemons <[email protected]>. 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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,288 @@ | ||
// Copyright (C) 2010, Kyle Lemons <[email protected]>. 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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
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")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} |
Oops, something went wrong.