Sfoglia il codice sorgente

feat(logging): updated syslog writer to work with log15 log interface, closes #4590

Torkel Ödegaard 9 anni fa
parent
commit
87e98f01cd
3 ha cambiato i file con 102 aggiunte e 104 eliminazioni
  1. 4 0
      CHANGELOG.md
  2. 13 12
      pkg/log/log.go
  3. 85 92
      pkg/log/syslog.go

+ 4 - 0
CHANGELOG.md

@@ -8,6 +8,10 @@
 * **Theme**: Add default theme to config file [#5011](https://github.com/grafana/grafana/pull/5011)
 * **Page Footer**: Added page footer with links to docs, shows Grafana version and info if new version is available, closes [#4889](https://github.com/grafana/grafana/pull/4889)
 * **InfluxDB**: Add spread function, closes [#5211](https://github.com/grafana/grafana/issues/5211)
+* **Logging**: Moved to structured logging lib, and moved to component specific level filters via config file, closes [#4590](https://github.com/grafana/grafana/issues/4590)
+
+## Breaking changes
+* **Logging** : Changed default logging output format (now structured into message, and key value pairs, with logger key acting as component). You can also no change in config to json log ouput.
 
 # 3.0.4 Patch release (2016-05-25)
 * **Panel**: Fixed blank dashboard issue when switching to other dashboard while in fullscreen edit mode, fixes [#5163](https://github.com/grafana/grafana/pull/5163)

+ 13 - 12
pkg/log/log.go

@@ -157,15 +157,20 @@ func ReadLoggingConfig(modes []string, logsPath string, cfg *ini.File) {
 
 			loggersToClose = append(loggersToClose, fileHandler)
 			handler = fileHandler
+		case "syslog":
+			sysLogHandler := NewSyslog()
+			sysLogHandler.Network = sec.Key("network").MustString("")
+			sysLogHandler.Address = sec.Key("address").MustString("")
+			sysLogHandler.Facility = sec.Key("facility").MustString("local7")
+			sysLogHandler.Tag = sec.Key("tag").MustString("")
+
+			if err := sysLogHandler.Init(); err != nil {
+				Root.Error("Failed to init syslog log handler", "error", err)
+				os.Exit(1)
+			}
 
-			// case "syslog":
-			// 	LogConfigs[i] = util.DynMap{
-			// 		"level":    level,
-			// 		"network":  sec.Key("network").MustString(""),
-			// 		"address":  sec.Key("address").MustString(""),
-			// 		"facility": sec.Key("facility").MustString("local7"),
-			// 		"tag":      sec.Key("tag").MustString(""),
-			// 	}
+			loggersToClose = append(loggersToClose, sysLogHandler)
+			handler = sysLogHandler
 		}
 
 		for key, value := range defaultFilters {
@@ -174,10 +179,6 @@ func ReadLoggingConfig(modes []string, logsPath string, cfg *ini.File) {
 			}
 		}
 
-		for key, value := range modeFilters {
-			fmt.Printf("key: %v, value: %v \n", key, value)
-		}
-
 		handler = LogFilterHandler(level, modeFilters, handler)
 		handlers = append(handlers, handler)
 	}

+ 85 - 92
pkg/log/syslog.go

@@ -2,95 +2,88 @@
 
 package log
 
-//
-// import (
-// 	"encoding/json"
-// 	"errors"
-// 	"log/syslog"
-// )
-//
-// type SyslogWriter struct {
-// 	syslog   *syslog.Writer
-// 	Network  string `json:"network"`
-// 	Address  string `json:"address"`
-// 	Facility string `json:"facility"`
-// 	Tag      string `json:"tag"`
-// }
-//
-// func NewSyslog() LoggerInterface {
-// 	return new(SyslogWriter)
-// }
-//
-// func (sw *SyslogWriter) Init(config string) error {
-// 	if err := json.Unmarshal([]byte(config), sw); err != nil {
-// 		return err
-// 	}
-//
-// 	prio, err := parseFacility(sw.Facility)
-// 	if err != nil {
-// 		return err
-// 	}
-//
-// 	w, err := syslog.Dial(sw.Network, sw.Address, prio, sw.Tag)
-// 	if err != nil {
-// 		return err
-// 	}
-//
-// 	sw.syslog = w
-// 	return nil
-// }
-//
-// func (sw *SyslogWriter) WriteMsg(msg string, skip int, level LogLevel) error {
-// 	var err error
-//
-// 	switch level {
-// 	case TRACE, DEBUG:
-// 		err = sw.syslog.Debug(msg)
-// 	case INFO:
-// 		err = sw.syslog.Info(msg)
-// 	case WARN:
-// 		err = sw.syslog.Warning(msg)
-// 	case ERROR:
-// 		err = sw.syslog.Err(msg)
-// 	case CRITICAL:
-// 		err = sw.syslog.Crit(msg)
-// 	case FATAL:
-// 		err = sw.syslog.Alert(msg)
-// 	default:
-// 		err = errors.New("invalid syslog level")
-// 	}
-//
-// 	return err
-// }
-//
-// func (sw *SyslogWriter) Destroy() {
-// 	sw.syslog.Close()
-// }
-//
-// func (sw *SyslogWriter) Flush() {}
-//
-// var facilities = map[string]syslog.Priority{
-// 	"user":   syslog.LOG_USER,
-// 	"daemon": syslog.LOG_DAEMON,
-// 	"local0": syslog.LOG_LOCAL0,
-// 	"local1": syslog.LOG_LOCAL1,
-// 	"local2": syslog.LOG_LOCAL2,
-// 	"local3": syslog.LOG_LOCAL3,
-// 	"local4": syslog.LOG_LOCAL4,
-// 	"local5": syslog.LOG_LOCAL5,
-// 	"local6": syslog.LOG_LOCAL6,
-// 	"local7": syslog.LOG_LOCAL7,
-// }
-//
-// func parseFacility(facility string) (syslog.Priority, error) {
-// 	prio, ok := facilities[facility]
-// 	if !ok {
-// 		return syslog.LOG_LOCAL0, errors.New("invalid syslog facility")
-// 	}
-//
-// 	return prio, nil
-// }
-//
-// func init() {
-// 	Register("syslog", NewSyslog)
-// }
+import (
+	"errors"
+	"log/syslog"
+
+	"github.com/inconshreveable/log15"
+)
+
+type SysLogHandler struct {
+	syslog   *syslog.Writer
+	Network  string
+	Address  string
+	Facility string
+	Tag      string
+	Format   log15.Format
+}
+
+func NewSyslog() *SysLogHandler {
+	return &SysLogHandler{
+		Format: log15.LogfmtFormat(),
+	}
+}
+
+func (sw *SysLogHandler) Init() error {
+	prio, err := parseFacility(sw.Facility)
+	if err != nil {
+		return err
+	}
+
+	w, err := syslog.Dial(sw.Network, sw.Address, prio, sw.Tag)
+	if err != nil {
+		return err
+	}
+
+	sw.syslog = w
+	return nil
+}
+
+func (sw *SysLogHandler) Log(r *log15.Record) error {
+	var err error
+
+	msg := string(sw.Format.Format(r))
+
+	switch r.Lvl {
+	case log15.LvlDebug:
+		err = sw.syslog.Debug(msg)
+	case log15.LvlInfo:
+		err = sw.syslog.Info(msg)
+	case log15.LvlWarn:
+		err = sw.syslog.Warning(msg)
+	case log15.LvlError:
+		err = sw.syslog.Err(msg)
+	case log15.LvlCrit:
+		err = sw.syslog.Crit(msg)
+	default:
+		err = errors.New("invalid syslog level")
+	}
+
+	return err
+}
+
+func (sw *SysLogHandler) Close() {
+	sw.syslog.Close()
+}
+
+var facilities = map[string]syslog.Priority{
+	"user":   syslog.LOG_USER,
+	"daemon": syslog.LOG_DAEMON,
+	"local0": syslog.LOG_LOCAL0,
+	"local1": syslog.LOG_LOCAL1,
+	"local2": syslog.LOG_LOCAL2,
+	"local3": syslog.LOG_LOCAL3,
+	"local4": syslog.LOG_LOCAL4,
+	"local5": syslog.LOG_LOCAL5,
+	"local6": syslog.LOG_LOCAL6,
+	"local7": syslog.LOG_LOCAL7,
+}
+
+func parseFacility(facility string) (syslog.Priority, error) {
+	prio, ok := facilities[facility]
+	if !ok {
+		return syslog.LOG_LOCAL0, errors.New("invalid syslog facility")
+	}
+
+	return prio, nil
+}