@@ -226,8 +226,13 @@ var (
226
226
)
227
227
228
228
var (
229
- StageParseCache dumps.ParserResults
229
+ StageParseCache dumps.ParserResults = make (dumps. ParserResults )
230
230
StageParseMutex sync.Mutex
231
+ // initialize the cache only once, even if called concurrently
232
+ ensureStageCache = sync .OnceFunc (func () {
233
+ StageParseCache ["success" ] = make (map [string ][]dumps.ParserResult )
234
+ StageParseCache ["success" ]["" ] = make ([]dumps.ParserResult , 0 )
235
+ })
231
236
)
232
237
233
238
func Parse (ctx UnixParserCtx , xp types.Event , nodes []Node ) (types.Event , error ) {
@@ -260,23 +265,10 @@ func Parse(ctx UnixParserCtx, xp types.Event, nodes []Node) (types.Event, error)
260
265
}
261
266
262
267
if ParseDump {
263
- if StageParseCache == nil {
264
- StageParseMutex .Lock ()
265
- StageParseCache = make (dumps.ParserResults )
266
- StageParseCache ["success" ] = make (map [string ][]dumps.ParserResult )
267
- StageParseCache ["success" ]["" ] = make ([]dumps.ParserResult , 0 )
268
- StageParseMutex .Unlock ()
269
- }
268
+ ensureStageCache ()
270
269
}
271
270
272
271
for _ , stage := range ctx .Stages {
273
- if ParseDump {
274
- StageParseMutex .Lock ()
275
- if _ , ok := StageParseCache [stage ]; ! ok {
276
- StageParseCache [stage ] = make (map [string ][]dumps.ParserResult )
277
- }
278
- StageParseMutex .Unlock ()
279
- }
280
272
/* if the node is forward in stages, seek to this stage */
281
273
/* this is for example used by testing system to inject logs in post-syslog-parsing phase*/
282
274
if stageidx (event .Stage , ctx .Stages ) > stageidx (stage , ctx .Stages ) {
@@ -314,19 +306,31 @@ func Parse(ctx UnixParserCtx, xp types.Event, nodes []Node) (types.Event, error)
314
306
clog .Tracef ("node (%s) ret : %v" , nodes [idx ].rn , ret )
315
307
if ParseDump {
316
308
var parserIdxInStage int
309
+
310
+ // copy outside of critical section
311
+ evtcopy := deepcopy .Copy (event )
312
+ name := nodes [idx ].Name
313
+
314
+ // ensure the stage map exists
317
315
StageParseMutex .Lock ()
318
- if len (StageParseCache [stage ][nodes [idx ].Name ]) == 0 {
319
- StageParseCache [stage ][nodes [idx ].Name ] = make ([]dumps.ParserResult , 0 )
320
- parserIdxInStage = len (StageParseCache [stage ])
316
+ stageMap , ok := StageParseCache [stage ]
317
+ if ! ok {
318
+ stageMap = make (map [string ][]dumps.ParserResult )
319
+ StageParseCache [stage ] = stageMap
320
+ }
321
+
322
+ // ensure the slice for this parser exists
323
+ if _ , ok := stageMap [name ]; ! ok {
324
+ stageMap [name ] = make ([]dumps.ParserResult , 0 )
325
+ parserIdxInStage = len (stageMap )
321
326
} else {
322
- parserIdxInStage = StageParseCache [ stage ][ nodes [ idx ]. Name ][0 ].Idx
327
+ parserIdxInStage = stageMap [ name ][0 ].Idx
323
328
}
324
- StageParseMutex .Unlock ()
325
329
326
- evtcopy := deepcopy . Copy ( event )
327
- parserInfo := dumps. ParserResult { Evt : evtcopy .(types.Event ), Success : ret , Idx : parserIdxInStage }
328
- StageParseMutex . Lock ()
329
- StageParseCache [ stage ][ nodes [ idx ]. Name ] = append ( StageParseCache [ stage ][ nodes [ idx ]. Name ], parserInfo )
330
+ stageMap [ name ] = append ( stageMap [ name ], dumps. ParserResult {
331
+ Evt : evtcopy .(types.Event ),
332
+ Success : ret , Idx : parserIdxInStage ,
333
+ } )
330
334
StageParseMutex .Unlock ()
331
335
}
332
336
if ret {
0 commit comments