Permalink
Browse files

Added JSON support for configuration files, and included an example J…

…SON configuration file.

Added a LoadJSONConfiguration and LoadXMLConfiguration function so that you can specifically load a certain type of config file, otherwise use LoadConfiguration attempts to figure out the type by the given filenames extension.
  • Loading branch information...
larzconwell committed Sep 22, 2012
1 parent 042afd2 commit 8b8edf1307321a6d6cdfe26d9cdacd17590963c2
Showing with 397 additions and 156 deletions.
  1. +25 −0 config.go
  2. +123 −0 config_json.go
  3. +125 −0 config_xml.go
  4. +39 −16 timber.go
  5. +67 −0 timber.json
  6. +18 −18 timber.xml
  7. +0 −122 xml_config.go
View
@@ -0,0 +1,25 @@
+package timber
+
+import (
+ "log"
+ "path"
+)
+
+func (t *Timber) LoadConfig(filename string) {
+ if len(filename) <= 0 {
+ return
+ }
+ ext := path.Ext(filename)
+ ext = ext[1:]
+
+ switch ext {
+ case "xml":
+ t.LoadXMLConfig(filename)
+ break
+ case "json":
+ t.LoadJSONConfig(filename)
+ break
+ default:
+ log.Printf("TIMBER! Unknown config file type %v, only XML and JSON are supported types\n", ext)
+ }
+}
View
@@ -0,0 +1,123 @@
+package timber
+
+import (
+ "encoding/json"
+ "fmt"
+ "log"
+ "os"
+ "reflect"
+)
+
+type JSONProperty struct {
+ Name string
+ Value string
+}
+
+type JSONFilter struct {
+ Enabled bool
+ Tag string
+ Type string
+ Level string
+ Format JSONProperty
+ Properties []JSONProperty
+}
+
+type JSONConfig struct {
+ Filters []JSONFilter
+}
+
+// Loads the configuration from an JSON file (as you were probably expecting)
+func (t *Timber) LoadJSONConfig(filename string) {
+ if len(filename) <= 0 {
+ return
+ }
+
+ file, err := os.Open(filename)
+ if err != nil {
+ panic(fmt.Sprintf("TIMBER! Can't load json config file: %s %v", filename, err))
+ }
+ defer file.Close()
+
+ config := JSONConfig{}
+ err = json.NewDecoder(file).Decode(&config)
+ if err != nil {
+ panic(fmt.Sprintf("TIMBER! Can't parse json config file: %s %v", filename, err))
+ }
+
+ for _, filter := range config.Filters {
+ if !filter.Enabled {
+ continue
+ }
+ level := getLevel(filter.Level)
+ formatter := getJSONFormatter(filter)
+ configLogger := ConfigLogger{Level: level, Formatter: formatter}
+
+ switch filter.Type {
+ case "console":
+ configLogger.LogWriter = new(ConsoleWriter)
+ case "socket":
+ configLogger.LogWriter = getJSONSocketWriter(filter)
+ case "file":
+ configLogger.LogWriter = getJSONFileWriter(filter)
+ default:
+ log.Printf("TIMBER! Warning unrecognized filter in config file: %v\n", filter.Tag)
+ continue
+ }
+
+ t.AddLogger(configLogger)
+ }
+}
+
+func getJSONFormatter(filter JSONFilter) LogFormatter {
+ format := ""
+ property := JSONProperty{}
+
+ // If format field is set then use it's value, otherwise
+ // attempt to get the format field from the filters properties
+ if !reflect.DeepEqual(filter.Format, property) {
+ format = filter.Format.Value
+ } else {
+ for _, prop := range filter.Properties {
+ if prop.Name == "format" {
+ format = prop.Value
+ }
+ }
+ }
+
+ // If empty format set the default as just the message
+ if format == "" {
+ format = "%M"
+ }
+ return NewPatFormatter(format)
+}
+
+func getJSONSocketWriter(filter JSONFilter) LogWriter {
+ var protocol, endpoint string
+
+ for _, property := range filter.Properties {
+ if property.Name == "protocol" {
+ protocol = property.Value
+ } else if property.Name == "endpoint" {
+ endpoint = property.Value
+ }
+ }
+
+ if protocol == "" || endpoint == "" {
+ panic("TIMBER! Missing protocol or endpoint for socket log writer")
+ }
+ return NewSocketWriter(protocol, endpoint)
+}
+
+func getJSONFileWriter(filter JSONFilter) LogWriter {
+ filename := ""
+
+ for _, property := range filter.Properties {
+ if property.Name == "filename" {
+ filename = property.Value
+ }
+ }
+ if filename == "" {
+ panic("TIMBER! Missing filename for file log writer")
+ }
+ return NewFileWriter(filename)
+}
View
@@ -0,0 +1,125 @@
+package timber
+
+import (
+ "encoding/xml"
+ "fmt"
+ "log"
+ "os"
+ "reflect"
+)
+
+// match the log4go structure so i don't have to change my configs
+type XMLProperty struct {
+ Name string `xml:"name,attr"`
+ Value string `xml:",chardata"`
+}
+type XMLFilter struct {
+ XMLName xml.Name `xml:"filter"`
+ Enabled bool `xml:"enabled,attr"`
+ Tag string `xml:"tag"`
+ Type string `xml:"type"`
+ Level string `xml:"level"`
+ Format XMLProperty `xml:"format"`
+ Properties []XMLProperty `xml:"property"`
+}
+
+type XMLConfig struct {
+ XMLName xml.Name `xml:"logging"`
+ Filters []XMLFilter `xml:"filter"`
+}
+
+// Loads the configuration from an XML file (as you were probably expecting)
+func (t *Timber) LoadXMLConfig(filename string) {
+ if len(filename) <= 0 {
+ return
+ }
+
+ file, err := os.Open(filename)
+ if err != nil {
+ panic(fmt.Sprintf("TIMBER! Can't load xml config file: %s %v", filename, err))
+ }
+ defer file.Close()
+
+ config := XMLConfig{}
+ err = xml.NewDecoder(file).Decode(&config)
+ if err != nil {
+ panic(fmt.Sprintf("TIMBER! Can't parse xml config file: %s %v", filename, err))
+ }
+
+ for _, filter := range config.Filters {
+ if !filter.Enabled {
+ continue
+ }
+ level := getLevel(filter.Level)
+ formatter := getXMLFormatter(filter)
+ configLogger := ConfigLogger{Level: level, Formatter: formatter}
+
+ switch filter.Type {
+ case "console":
+ configLogger.LogWriter = new(ConsoleWriter)
+ case "socket":
+ configLogger.LogWriter = getXMLSocketWriter(filter)
+ case "file":
+ configLogger.LogWriter = getXMLFileWriter(filter)
+ default:
+ log.Printf("TIMBER! Warning unrecognized filter in config file: %v\n", filter.Tag)
+ continue
+ }
+
+ t.AddLogger(configLogger)
+ }
+}
+
+func getXMLFormatter(filter XMLFilter) LogFormatter {
+ format := ""
+ property := XMLProperty{}
+
+ // If format field is set then use it's value, otherwise
+ // attempt to get the format field from the filters properties
+ if !reflect.DeepEqual(filter.Format, property) {
+ format = filter.Format.Value
+ } else {
+ for _, prop := range filter.Properties {
+ if prop.Name == "format" {
+ format = prop.Value
+ }
+ }
+ }
+
+ // If empty format set the default as just the message
+ if format == "" {
+ format = "%M"
+ }
+ return NewPatFormatter(format)
+}
+
+func getXMLSocketWriter(filter XMLFilter) LogWriter {
+ var protocol, endpoint string
+
+ for _, property := range filter.Properties {
+ if property.Name == "protocol" {
+ protocol = property.Value
+ } else if property.Name == "endpoint" {
+ endpoint = property.Value
+ }
+ }
+
+ if protocol == "" || endpoint == "" {
+ panic("TIMBER! Missing protocol or endpoint for socket log writer")
+ }
+ return NewSocketWriter(protocol, endpoint)
+}
+
+func getXMLFileWriter(filter XMLFilter) LogWriter {
+ filename := ""
+
+ for _, property := range filter.Properties {
+ if property.Name == "filename" {
+ filename = property.Value
+ }
+ }
+ if filename == "" {
+ panic("TIMBER! Missing filename for file log writer")
+ }
+ return NewFileWriter(filename)
+}
Oops, something went wrong.

0 comments on commit 8b8edf1

Please sign in to comment.