Skip to content

Commit 2d087bf

Browse files
authored
Merge pull request #3624 from semaphoreui/syslog_rfc
feat(syslog): use rfc 5424 output format
2 parents 4a85490 + a4d0f90 commit 2d087bf

4 files changed

Lines changed: 129 additions & 15 deletions

File tree

api-docs.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -831,8 +831,9 @@ definitions:
831831
type: string
832832
message:
833833
type: string
834-
inventory_id:
835-
type: integer
834+
# inventory_id:
835+
# type: integer
836+
# x-nullable: true
836837
arguments:
837838
type: string
838839
params:

cli/cmd/syslog.go

Lines changed: 114 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,130 @@
44
package cmd
55

66
import (
7+
"fmt"
78
"log/syslog"
9+
"net"
10+
"os"
11+
"strings"
12+
"sync"
13+
"time"
814

915
"github.com/semaphoreui/semaphore/util"
1016
log "github.com/sirupsen/logrus"
1117
lSyslog "github.com/sirupsen/logrus/hooks/syslog"
1218
)
1319

20+
var localSyslogPaths = []string{"/dev/log", "/var/run/syslog", "/var/run/log"}
21+
1422
func initSyslog(conf *util.SyslogConfig) {
15-
if conf.Enabled {
23+
if !conf.Enabled {
24+
return
25+
}
26+
27+
switch conf.Format {
28+
case util.SyslogRFC5424:
29+
hook, err := newRFC5424Hook(conf.Network, conf.Address, conf.Tag)
30+
if err != nil {
31+
log.WithError(err).Fatal("Failed to create syslog hook")
32+
return
33+
}
34+
log.AddHook(hook)
35+
log.Info("Syslog logging enabled (RFC 5424)")
36+
default:
1637
hook, err := lSyslog.NewSyslogHook(conf.Network, conf.Address, syslog.LOG_DEBUG, conf.Tag)
17-
if err == nil {
18-
log.AddHook(hook)
19-
log.Info("Syslog logging enabled")
20-
} else {
38+
if err != nil {
2139
log.WithError(err).Fatal("Failed to create syslog hook")
40+
return
2241
}
42+
log.AddHook(hook)
43+
log.Info("Syslog logging enabled")
2344
}
2445
}
46+
47+
type rfc5424Hook struct {
48+
conn net.Conn
49+
tag string
50+
hostname string
51+
mu sync.Mutex
52+
}
53+
54+
func newRFC5424Hook(network, address, tag string) (*rfc5424Hook, error) {
55+
var conn net.Conn
56+
var err error
57+
58+
if network != "" && address != "" {
59+
conn, err = net.Dial(network, address)
60+
} else {
61+
for _, path := range localSyslogPaths {
62+
conn, err = net.Dial("unixgram", path)
63+
if err == nil {
64+
break
65+
}
66+
}
67+
}
68+
if err != nil {
69+
return nil, err
70+
}
71+
72+
hostname, _ := os.Hostname()
73+
74+
return &rfc5424Hook{
75+
conn: conn,
76+
tag: tag,
77+
hostname: hostname,
78+
}, nil
79+
}
80+
81+
var levelToSeverity = map[log.Level]syslog.Priority{
82+
log.PanicLevel: syslog.LOG_CRIT,
83+
log.FatalLevel: syslog.LOG_CRIT,
84+
log.ErrorLevel: syslog.LOG_ERR,
85+
log.WarnLevel: syslog.LOG_WARNING,
86+
log.InfoLevel: syslog.LOG_INFO,
87+
log.DebugLevel: syslog.LOG_DEBUG,
88+
log.TraceLevel: syslog.LOG_DEBUG,
89+
}
90+
91+
func (h *rfc5424Hook) Levels() []log.Level {
92+
return log.AllLevels
93+
}
94+
95+
func (h *rfc5424Hook) Fire(entry *log.Entry) error {
96+
severity, ok := levelToSeverity[entry.Level]
97+
if !ok {
98+
severity = syslog.LOG_INFO
99+
}
100+
pri := syslog.LOG_USER | severity
101+
102+
sd := "-"
103+
if len(entry.Data) > 0 {
104+
var pairs []string
105+
for k, v := range entry.Data {
106+
pairs = append(pairs, fmt.Sprintf(`%s="%s"`, k, escapeSDValue(fmt.Sprintf("%v", v))))
107+
}
108+
sd = fmt.Sprintf("[%s@0 %s]", h.tag, strings.Join(pairs, " "))
109+
}
110+
111+
// RFC 5424: <PRI>VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID SP STRUCTURED-DATA [SP MSG]
112+
msg := fmt.Sprintf("<%d>1 %s %s %s %d - %s %s",
113+
pri,
114+
entry.Time.Format(time.RFC3339),
115+
h.hostname,
116+
h.tag,
117+
os.Getpid(),
118+
sd,
119+
entry.Message,
120+
)
121+
122+
h.mu.Lock()
123+
defer h.mu.Unlock()
124+
_, err := fmt.Fprintln(h.conn, msg)
125+
return err
126+
}
127+
128+
func escapeSDValue(v string) string {
129+
v = strings.ReplaceAll(v, `\`, `\\`)
130+
v = strings.ReplaceAll(v, `"`, `\"`)
131+
v = strings.ReplaceAll(v, `]`, `\]`)
132+
return v
133+
}

go.sum

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,6 @@ github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
145145
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
146146
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
147147
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
148-
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
149-
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
150148
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
151149
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
152150
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
@@ -161,7 +159,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
161159
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
162160
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
163161
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
164-
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
165162
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
166163
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
167164
github.com/thedevsaddam/gojsonq/v2 v2.5.2 h1:CoMVaYyKFsVj6TjU6APqAhAvC07hTI6IQen8PHzHYY0=
@@ -214,7 +211,6 @@ gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
214211
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
215212
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
216213
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
217-
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
218214
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
219215
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
220216
modernc.org/cc/v4 v4.26.5 h1:xM3bX7Mve6G8K8b+T11ReenJOT+BmVqQj0FY5T4+5Y4=

util/config.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,19 @@ type ConfigLog struct {
169169
Tasks *TaskLogType `json:"tasks,omitempty"`
170170
}
171171

172+
type SyslogFormat string
173+
174+
const (
175+
SyslogDefault SyslogFormat = ""
176+
SyslogRFC5424 SyslogFormat = "rfc5424"
177+
)
178+
172179
type SyslogConfig struct {
173-
Enabled bool `json:"enabled" env:"SEMAPHORE_SYSLOG_ENABLED"`
174-
Network string `json:"network,omitempty" env:"SEMAPHORE_SYSLOG_NETWORK"`
175-
Address string `json:"address,omitempty" env:"SEMAPHORE_SYSLOG_ADDRESS"`
176-
Tag string `json:"tag,omitempty" env:"SEMAPHORE_SYSLOG_TAG"`
180+
Enabled bool `json:"enabled" env:"SEMAPHORE_SYSLOG_ENABLED"`
181+
Network string `json:"network,omitempty" env:"SEMAPHORE_SYSLOG_NETWORK"`
182+
Address string `json:"address,omitempty" env:"SEMAPHORE_SYSLOG_ADDRESS"`
183+
Tag string `json:"tag,omitempty" env:"SEMAPHORE_SYSLOG_TAG"`
184+
Format SyslogFormat `json:"format,omitempty" env:"SEMAPHORE_SYSLOG_FORMAT"`
177185
}
178186

179187
type ConfigProcess struct {

0 commit comments

Comments
 (0)