github.com/livekit/protocol@v1.16.1-0.20240517185851-47e4c6bba773/logger/zaputil/deferrer.go (about) 1 // Copyright 2023 LiveKit, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package zaputil 16 17 import ( 18 "sync" 19 20 "go.uber.org/zap" 21 "go.uber.org/zap/zapcore" 22 ) 23 24 type deferredWrite struct { 25 core zapcore.Core 26 ent zapcore.Entry 27 fields []zapcore.Field 28 } 29 30 type Deferrer struct { 31 mu sync.Mutex 32 ready bool 33 fields []zapcore.Field 34 writes []*deferredWrite 35 } 36 37 func (b *Deferrer) buffer(core zapcore.Core, ent zapcore.Entry, fields []zapcore.Field) bool { 38 b.mu.Lock() 39 defer b.mu.Unlock() 40 if b.ready { 41 return false 42 } 43 b.writes = append(b.writes, &deferredWrite{core, ent, fields}) 44 return true 45 } 46 47 func (b *Deferrer) flush() { 48 b.mu.Lock() 49 b.ready = true 50 writes := b.writes 51 b.writes = nil 52 b.mu.Unlock() 53 54 var fields []zapcore.Field 55 for _, w := range writes { 56 fields = append(fields[:0], b.fields...) 57 fields = append(fields, w.fields...) 58 w.core.Write(w.ent, fields) 59 } 60 } 61 62 func (b *Deferrer) write(core zapcore.Core, ent zapcore.Entry, fields []zapcore.Field) error { 63 if !b.buffer(core, ent, fields) { 64 return core.Write(ent, append(fields[0:len(fields):len(fields)], b.fields...)) 65 } 66 return nil 67 } 68 69 type DeferredFieldResolver func(args ...any) 70 71 func NewDeferrer() (*Deferrer, DeferredFieldResolver) { 72 buf := &Deferrer{} 73 var resolveOnce sync.Once 74 resolve := func(args ...any) { 75 resolveOnce.Do(func() { 76 fields := make([]zapcore.Field, 0, len(args)) 77 for i := 0; i < len(args); i++ { 78 switch arg := args[i].(type) { 79 case zapcore.Field: 80 fields = append(fields, arg) 81 case string: 82 if i < len(args)-1 { 83 fields = append(fields, zap.Any(arg, args[i+1])) 84 i++ 85 } 86 } 87 } 88 89 buf.fields = fields 90 buf.flush() 91 }) 92 } 93 return buf, resolve 94 } 95 96 type deferredValueCore struct { 97 zapcore.Core 98 def *Deferrer 99 } 100 101 func NewDeferredValueCore(core zapcore.Core, def *Deferrer) zapcore.Core { 102 def.mu.Lock() 103 defer def.mu.Unlock() 104 return &deferredValueCore{core, def} 105 } 106 107 func (c *deferredValueCore) With(fields []zapcore.Field) zapcore.Core { 108 return &deferredValueCore{ 109 Core: c.Core.With(fields), 110 def: c.def, 111 } 112 } 113 114 func (c *deferredValueCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry { 115 if c.Enabled(ent.Level) { 116 return ce.AddCore(ent, c) 117 } 118 return ce 119 } 120 121 func (c *deferredValueCore) Write(ent zapcore.Entry, fields []zapcore.Field) error { 122 return c.def.write(c.Core, ent, fields) 123 }