github.com/Laisky/zap@v1.27.0/zapcore/hook.go (about) 1 // Copyright (c) 2016 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package zapcore 22 23 import "go.uber.org/multierr" 24 25 type hooked struct { 26 Core 27 funcs []func(Entry) error 28 } 29 30 var ( 31 _ Core = (*hooked)(nil) 32 _ leveledEnabler = (*hooked)(nil) 33 ) 34 35 type hookedWithFields struct { 36 Core 37 funcs []func(Entry, []Field) error 38 } 39 40 // RegisterHooks wraps a Core and runs a collection of user-defined callback 41 // hooks each time a message is logged. Execution of the callbacks is blocking. 42 // 43 // This offers users an easy way to register simple callbacks (e.g., metrics 44 // collection) without implementing the full Core interface. 45 func RegisterHooks(core Core, hooks ...func(Entry) error) Core { 46 funcs := append([]func(Entry) error{}, hooks...) 47 return &hooked{ 48 Core: core, 49 funcs: funcs, 50 } 51 } 52 53 func (h *hooked) Level() Level { 54 return LevelOf(h.Core) 55 } 56 57 // RegisterHooksWithFields like RegisterHooks but and invoke hooks with arbitary fileds 58 func RegisterHooksWithFields(core Core, hooks ...func(Entry, []Field) error) Core { 59 return &hookedWithFields{ 60 Core: core, 61 funcs: hooks[:len(hooks):len(hooks)], 62 } 63 } 64 65 func (h *hooked) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { 66 // Let the wrapped Core decide whether to log this message or not. This 67 // also gives the downstream a chance to register itself directly with the 68 // CheckedEntry. 69 if downstream := h.Core.Check(ent, ce); downstream != nil { 70 return downstream.AddCore(ent, h) 71 } 72 return ce 73 } 74 75 func (h *hooked) With(fields []Field) Core { 76 return &hooked{ 77 Core: h.Core.With(fields), 78 funcs: h.funcs, 79 } 80 } 81 82 func (h *hooked) Write(ent Entry, _ []Field) error { 83 // Since our downstream had a chance to register itself directly with the 84 // CheckedMessage, we don't need to call it here. 85 var err error 86 for i := range h.funcs { 87 err = multierr.Append(err, h.funcs[i](ent)) 88 } 89 return err 90 } 91 92 func (h *hookedWithFields) Check(ent Entry, ce *CheckedEntry) *CheckedEntry { 93 // Let the wrapped Core decide whether to log this message or not. This 94 // also gives the downstream a chance to register itself directly with the 95 // CheckedEntry. 96 if downstream := h.Core.Check(ent, ce); downstream != nil { 97 return downstream.AddCore(ent, h) 98 } 99 return ce 100 } 101 102 func (h *hookedWithFields) With(fields []Field) Core { 103 return &hookedWithFields{ 104 Core: h.Core.With(fields), 105 funcs: h.funcs, 106 } 107 } 108 109 func (h *hookedWithFields) Write(ent Entry, fs []Field) error { 110 // Since our downstream had a chance to register itself directly with the 111 // CheckedMessage, we don't need to call it here. 112 var err error 113 for i := range h.funcs { 114 fs = append(fs[:len(fs):len(fs)], h.Core.Fields()...) 115 err = multierr.Append(err, h.funcs[i](ent, fs)) 116 } 117 return err 118 }