Last active
December 7, 2017 09:51
-
-
Save devishot/c0e0813a2cc2370ed476cd757dc5e6b4 to your computer and use it in GitHub Desktop.
Gelf with log15 UPD: use go-gelf.v2 by Graylog2
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
package gelflog15 | |
import ( | |
"os" | |
"strconv" | |
"strings" | |
"gopkg.in/inconshreveable/log15.v2" | |
"gopkg.in/Graylog2/go-gelf.v2/gelf" | |
) | |
// Handler sends logs to Graylog in GELF. | |
type Handler struct { | |
writer gelf.Writer | |
host string | |
facility string | |
} | |
// New creates a log15 handler that emits GELF to addr. It is already wrapped | |
// in log15's LazyHandler and SyncHandler helpers. Its error is non-nil if there | |
// is a problem creating the GELF writer or determining our hostname. | |
func New(addr string, facility string) (log15.Handler, error) { | |
w, err := gelf.NewUDPWriter(addr) | |
if err != nil { | |
return nil, err | |
} | |
host, err := os.Hostname() | |
if err != nil { | |
return nil, err | |
} | |
return log15.CallerFileHandler(log15.LazyHandler(log15.SyncHandler(Handler{ | |
writer: w, | |
host: host, | |
facility: facility, | |
}))), nil | |
} | |
// Log forwards a log message to the specified receiever. | |
func (h Handler) Log(r *log15.Record) error { | |
short, full := shortAndFull(r.Msg) | |
ctx := ctxToMap(r.Ctx) | |
callerFile, callerLine := caller(ctx) | |
delete(ctx, "_caller") | |
ctx["_file"] = callerFile | |
ctx["_line"] = callerLine | |
m := &gelf.Message{ | |
Version: "1.1", | |
Host: h.host, | |
Short: short, | |
Full: full, | |
TimeUnix: float64(r.Time.Unix()), | |
Level: log15LevelsToSyslog[r.Lvl], | |
Facility: h.facility, | |
Extra: ctx, | |
} | |
return h.writer.WriteMessage(m) | |
} | |
func ctxToMap(ctx []interface{}) map[string]interface{} { | |
m := make(map[string]interface{}, len(ctx)/2) | |
for i := 0; i < len(ctx); i += 2 { | |
s := ctx[i].(string) | |
m["_" + s] = ctx[i+1] | |
} | |
return m | |
} | |
func shortAndFull(msg string) (short, full string) { | |
lines := strings.SplitN(msg, "\n", 2) | |
short = lines[0] | |
if len(lines) > 1 { | |
full = msg | |
} | |
return | |
} | |
// caller searches a context list for an entry called "caller" and splits it into | |
// filename and line number. | |
func caller(ctx map[string]interface{}) (string, int) { | |
info, present := ctx["_caller"] | |
if !present { | |
return "", 0 | |
} | |
parts := strings.Split(info.(string), ":") | |
line, _ := strconv.Atoi(parts[1]) | |
return parts[0], line | |
} | |
// source: http://www.cisco.com/c/en/us/td/docs/security/asa/syslog-guide/syslogs/logsevp.html | |
var log15LevelsToSyslog = map[log15.Lvl]int32{ | |
log15.LvlCrit: 2, | |
log15.LvlError: 3, | |
log15.LvlWarn: 4, | |
log15.LvlInfo: 6, | |
log15.LvlDebug: 7, | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment