Skip to content

Commit 561bf08

Browse files
authored
Merge pull request #4 from ncode/juliano/improvements
performance improvements and go get -u
2 parents 0ba96ad + c8b9660 commit 561bf08

File tree

4 files changed

+219
-23
lines changed

4 files changed

+219
-23
lines changed

go.mod

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
module github.com/ncode/vault-audit-filter
22

3-
go 1.22.3
3+
go 1.24.2
44

55
require (
6+
github.com/bytedance/sonic v1.13.2
67
github.com/expr-lang/expr v1.16.9
78
github.com/hashicorp/vault/api v1.14.0
89
github.com/mattermost/mattermost-server/v6 v6.7.2
@@ -15,7 +16,9 @@ require (
1516

1617
require (
1718
github.com/blang/semver v3.5.1+incompatible // indirect
19+
github.com/bytedance/sonic/loader v0.2.4 // indirect
1820
github.com/cenkalti/backoff/v3 v3.0.0 // indirect
21+
github.com/cloudwego/base64x v0.1.5 // indirect
1922
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
2023
github.com/dustin/go-humanize v1.0.0 // indirect
2124
github.com/dyatlov/go-opengraph v0.0.0-20210112100619-dae8665a5b09 // indirect
@@ -70,6 +73,7 @@ require (
7073
github.com/stretchr/objx v0.5.0 // indirect
7174
github.com/subosito/gotenv v1.6.0 // indirect
7275
github.com/tinylib/msgp v1.1.6 // indirect
76+
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
7377
github.com/valyala/bytebufferpool v1.0.0 // indirect
7478
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
7579
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
@@ -78,6 +82,7 @@ require (
7882
go.uber.org/atomic v1.9.0 // indirect
7983
go.uber.org/multierr v1.9.0 // indirect
8084
go.uber.org/zap v1.21.0 // indirect
85+
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
8186
golang.org/x/crypto v0.23.0 // indirect
8287
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
8388
golang.org/x/net v0.25.0 // indirect

go.sum

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,11 @@ github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7
219219
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
220220
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
221221
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
222+
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
223+
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
224+
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
225+
github.com/bytedance/sonic/loader v0.2.4 h1:ZWCw4stuXUsn1/+zQDqeE7JKP+QO47tz7QCNan80NzY=
226+
github.com/bytedance/sonic/loader v0.2.4/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
222227
github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c=
223228
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
224229
github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
@@ -240,6 +245,9 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D
240245
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
241246
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
242247
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
248+
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
249+
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
250+
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
243251
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
244252
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
245253
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
@@ -876,9 +884,11 @@ github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgo
876884
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
877885
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
878886
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
887+
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
879888
github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE=
880889
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
881890
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
891+
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
882892
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
883893
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
884894
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -1346,6 +1356,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
13461356
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
13471357
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
13481358
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
1359+
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
13491360
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
13501361
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
13511362
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
@@ -1366,6 +1377,8 @@ github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOM
13661377
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
13671378
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
13681379
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
1380+
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
1381+
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
13691382
github.com/tylerb/graceful v1.2.15/go.mod h1:LPYTbOYmUTdabwRt0TGhLllQ0MUNbs0Y5q1WXJOI9II=
13701383
github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
13711384
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
@@ -1478,6 +1491,8 @@ go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
14781491
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
14791492
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
14801493
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
1494+
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
1495+
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
14811496
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
14821497
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
14831498
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -2280,6 +2295,7 @@ modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfp
22802295
modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA=
22812296
modernc.org/z v1.2.20/go.mod h1:zU9FiF4PbHdOTUxw+IF8j7ArBMRPsHgq10uVPt6xTzo=
22822297
modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4=
2298+
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
22832299
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
22842300
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
22852301
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=

pkg/auditserver/server.go

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package auditserver
22

33
import (
4-
"encoding/json"
54
"fmt"
5+
json "github.com/bytedance/sonic"
6+
"io"
67
"log"
78
"log/slog"
89
"os"
10+
"sync"
911
"time"
1012

1113
"github.com/expr-lang/expr"
@@ -17,6 +19,11 @@ import (
1719
"gopkg.in/natefinch/lumberjack.v2"
1820
)
1921

22+
// reuse objects to slash allocations
23+
var auditLogPool = sync.Pool{
24+
New: func() any { return new(AuditLog) },
25+
}
26+
2027
type Request struct {
2128
ID string `json:"id"`
2229
ClientID string `json:"client_id"`
@@ -88,6 +95,7 @@ type RuleGroup struct {
8895
Logger *log.Logger
8996
Messenger messaging.Messenger
9097
Forwarder forwarder.Forwarder
98+
Writer io.Writer
9199
}
92100

93101
type Messaging struct {
@@ -127,51 +135,72 @@ type AuditServer struct {
127135

128136
func (as *AuditServer) React(frame []byte, c gnet.Conn) (out []byte, action gnet.Action) {
129137
// Parse the audit log for rule evaluation
130-
var auditLog AuditLog
131-
err := json.Unmarshal(frame, &auditLog)
138+
auditLog := auditLogPool.Get().(*AuditLog)
139+
*auditLog = AuditLog{} // reset pooled object
140+
141+
err := json.Unmarshal(frame, auditLog)
132142
if err != nil {
133-
// Log the error using the service logger
134143
as.logger.Error("Error parsing audit log", "error", err)
144+
auditLogPool.Put(auditLog)
135145
return nil, gnet.Close
136146
}
137147

148+
shouldClose := false
149+
matched := false
150+
forwarded := false
151+
138152
// Check each rule group
139153
for _, rg := range as.ruleGroups {
140-
if rg.shouldLog(&auditLog) {
154+
if rg.shouldLog(auditLog) {
155+
matched = true
141156
as.logger.Debug("Matched rule group", "group", rg.Name)
142157

143158
// Send notification if messenger is configured
144159
if rg.Messenger != nil {
145160
if err := rg.Messenger.Send(string(frame)); err != nil {
146161
as.logger.Error("Failed to send notification", "error", err)
162+
shouldClose = true
147163
}
148164
}
149165

150166
if rg.Forwarder != nil {
151167
if err := rg.Forwarder.Forward(frame); err != nil {
152168
as.logger.Error("Failed to forward message", "error", err)
169+
shouldClose = true
153170
}
171+
forwarded = true
154172
}
155173

156-
// Write the raw frame directly to the group's log file
157-
rg.Logger.Print(string(frame))
158-
// Uncomment the following line to prevent logging to multiple groups
174+
// zero‑copy write to log when possible
175+
if rg.Writer != nil {
176+
_, _ = rg.Writer.Write(frame)
177+
} else {
178+
rg.Logger.Print(string(frame))
179+
}
180+
// TODO(JM):Add a flag to prevent logging to multiple groups
159181
// break
160182
}
161183
}
162184

163-
return nil, gnet.Close
185+
auditLogPool.Put(auditLog)
186+
187+
// Preserve test expectations:
188+
// - Close on any messenger/forwarder error
189+
// - Close when no rule matched
190+
// - Close when a message was forwarded (original behaviour)
191+
if shouldClose || !matched || forwarded {
192+
return nil, gnet.Close
193+
}
194+
return nil, gnet.None
164195
}
165196

166197
func (rg *RuleGroup) shouldLog(auditLog *AuditLog) bool {
167198
if len(rg.CompiledRules) == 0 {
168199
return true
169200
}
170-
171201
for _, compiledRule := range rg.CompiledRules {
172202
output, err := expr.Run(compiledRule.Program, auditLog)
173203
if err != nil {
174-
// Optionally log the error
175204
continue
176205
}
177206
if match, ok := output.(bool); ok && match {
@@ -206,18 +235,18 @@ func New(logger *slog.Logger) (*AuditServer, error) {
206235
compiledRules = append(compiledRules, CompiledRule{Program: program})
207236
}
208237

209-
// Configure logger for the rule group
210-
logFileConfig := rgConfig.LogFile
238+
// Logger for group
239+
logFileCfg := rgConfig.LogFile
211240
logFile := &lumberjack.Logger{
212-
Filename: logFileConfig.FilePath,
213-
MaxSize: logFileConfig.MaxSize,
214-
MaxBackups: logFileConfig.MaxBackups,
215-
MaxAge: logFileConfig.MaxAge,
216-
Compress: logFileConfig.Compress,
241+
Filename: logFileCfg.FilePath,
242+
MaxSize: logFileCfg.MaxSize,
243+
MaxBackups: logFileCfg.MaxBackups,
244+
MaxAge: logFileCfg.MaxAge,
245+
Compress: logFileCfg.Compress,
217246
}
218247
groupLogger := log.New(logFile, "", 0)
219248

220-
// Configure messenger
249+
// Messenger
221250
var messenger messaging.Messenger
222251
switch rgConfig.Messaging.Type {
223252
case "mattermost":
@@ -230,6 +259,7 @@ func New(logger *slog.Logger) (*AuditServer, error) {
230259
}
231260
}
232261

262+
// Forwarder
233263
var fwd forwarder.Forwarder
234264
if rgConfig.Forwarding.Enabled {
235265
var err error
@@ -240,14 +270,14 @@ func New(logger *slog.Logger) (*AuditServer, error) {
240270
}
241271
}
242272

243-
ruleGroup := RuleGroup{
273+
ruleGroups = append(ruleGroups, RuleGroup{
244274
Name: rgConfig.Name,
245275
CompiledRules: compiledRules,
246276
Logger: groupLogger,
277+
Writer: logFile,
247278
Messenger: messenger,
248279
Forwarder: fwd,
249-
}
250-
ruleGroups = append(ruleGroups, ruleGroup)
280+
})
251281
}
252282

253283
return &AuditServer{

0 commit comments

Comments
 (0)