aboutsummaryrefslogtreecommitdiffstats
path: root/community/docker-registry/log-hook-syslog.patch
blob: 8f836fb046067fb802b419b0d7a37850e6f4be15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
Add a logging hook "syslog" for logging to the system syslog.

I didn't contribute this patch to the upstream because I don't wanna
contribute to any Go projects. However, if you find this patch useful,
feel free to send it to the upstream under your name.

--- a/registry/handlers/app.go
+++ b/registry/handlers/app.go
@@ -42,6 +42,9 @@
 	"github.com/garyburd/redigo/redis"
 	"github.com/gorilla/mux"
 	"github.com/sirupsen/logrus"
+
+	"log/syslog"
+	lSyslog "github.com/sirupsen/logrus/hooks/syslog"
 )
 
 // randomSecretSize is the number of random bytes to generate if no secret
@@ -600,6 +603,11 @@
 					To:       configHook.MailOptions.To,
 				}
 				logger.Hooks.Add(hook)
+			case "syslog":
+				hook, err := lSyslog.NewSyslogHook("", "", syslog.LOG_DAEMON | syslog.LOG_INFO, "docker-registry")
+				if err == nil {
+					logger.Hooks.Add(hook)
+				}
 			default:
 			}
 		}
--- a/registry/registry.go
+++ b/registry/registry.go
@@ -32,4 +32,6 @@
 	"github.com/spf13/cobra"
 	"github.com/yvasiyarov/gorelic"
+
+	"bytes"
 )
 
@@ -367,6 +369,8 @@
 		log.SetFormatter(&logstash.LogstashFormatter{
 			TimestampFormat: time.RFC3339Nano,
 		})
+	case "syslog":
+		log.SetFormatter(&SyslogFormatter{})
 	default:
 		// just let the library use default on empty string.
 		if config.Log.Formatter != "" {
@@ -390,6 +394,50 @@
 	}
 
 	return ctx, nil
+}
+
+type SyslogFormatter struct {
+}
+
+func (f *SyslogFormatter) Format(entry *log.Entry) ([]byte, error) {
+	var b *bytes.Buffer
+	if entry.Buffer != nil {
+		b = entry.Buffer
+	} else {
+		b = &bytes.Buffer{}
+	}
+
+	if entry.Message != "" {
+		b.WriteString(entry.Message)
+	}
+	dataWritten := false
+	for key, val := range entry.Data {
+		switch key {
+		// Omit these keys in syslog for brevity.
+		case "go.version", "instance.id", "version":
+			continue
+		}
+
+		stringVal, ok := val.(string)
+		if !ok {
+			stringVal = fmt.Sprint(val)
+		}
+
+		// The format is inspired by RFC 5424 STRUCTURED-DATA.
+		if dataWritten {
+			b.WriteByte(' ')
+		} else {
+			b.WriteString(" [meta ")
+			dataWritten = true
+		}
+		b.WriteString(fmt.Sprintf("%s=%q", key, stringVal))
+	}
+	if dataWritten {
+		b.WriteByte(']')
+	}
+	b.WriteByte('\n')
+
+	return b.Bytes(), nil
 }
 
 func logLevel(level configuration.Loglevel) log.Level {
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/hooks/syslog/syslog.go
@@ -0,0 +1,54 @@
+// +build !windows,!nacl,!plan9
+
+package logrus_syslog
+
+import (
+	"fmt"
+	"github.com/sirupsen/logrus"
+	"log/syslog"
+	"os"
+)
+
+// SyslogHook to send logs via syslog.
+type SyslogHook struct {
+	Writer        *syslog.Writer
+	SyslogNetwork string
+	SyslogRaddr   string
+}
+
+// Creates a hook to be added to an instance of logger. This is called with
+// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
+// `if err == nil { log.Hooks.Add(hook) }`
+func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
+	w, err := syslog.Dial(network, raddr, priority, tag)
+	return &SyslogHook{w, network, raddr}, err
+}
+
+func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
+	line, err := entry.String()
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
+		return err
+	}
+
+	switch entry.Level {
+	case logrus.PanicLevel:
+		return hook.Writer.Crit(line)
+	case logrus.FatalLevel:
+		return hook.Writer.Crit(line)
+	case logrus.ErrorLevel:
+		return hook.Writer.Err(line)
+	case logrus.WarnLevel:
+		return hook.Writer.Warning(line)
+	case logrus.InfoLevel:
+		return hook.Writer.Info(line)
+	case logrus.DebugLevel:
+		return hook.Writer.Debug(line)
+	default:
+		return nil
+	}
+}
+
+func (hook *SyslogHook) Levels() []logrus.Level {
+	return logrus.AllLevels
+}