github.com/matrixorigin/matrixone@v1.2.0/pkg/logutil/report.go (about) 1 // Copyright 2021 Matrix Origin 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 logutil 16 17 import ( 18 "context" 19 "io" 20 "sync/atomic" 21 22 "go.uber.org/zap" 23 "go.uber.org/zap/buffer" 24 "go.uber.org/zap/zapcore" 25 ) 26 27 var gLogConfigs atomic.Value 28 29 // EnableLog to get log config's !DisableLog 30 func EnableLog() bool { 31 return !gLogConfigs.Load().(*LogConfig).DisableLog 32 } 33 34 func EnableStoreDB() bool { 35 return !gLogConfigs.Load().(*LogConfig).DisableStore 36 } 37 38 func setGlobalLogConfig(cfg *LogConfig) { 39 gLogConfigs.Store(cfg) 40 } 41 42 func getGlobalLogConfig() *LogConfig { 43 return gLogConfigs.Load().(*LogConfig) 44 } 45 46 type ZapSink struct { 47 enc zapcore.Encoder 48 out zapcore.WriteSyncer 49 } 50 51 // zapReporter should be trace.ReportZap 52 var zapReporter atomic.Value 53 54 // contextField should be trace.ContextField function 55 var contextField atomic.Value 56 57 type TraceReporter struct { 58 ReportZap reportZapFunc 59 ContextField contextFieldFunc 60 } 61 62 type reportZapFunc func(zapcore.Encoder, zapcore.Entry, []zapcore.Field) (*buffer.Buffer, error) 63 type contextFieldFunc func(context.Context) zap.Field 64 65 func noopReportZap(zapcore.Encoder, zapcore.Entry, []zapcore.Field) (*buffer.Buffer, error) { 66 return buffer.NewPool().Get(), nil 67 } 68 func noopContextField(context.Context) zap.Field { return zap.String("span", "{}") } 69 70 func SetLogReporter(r *TraceReporter) { 71 if r.ReportZap != nil { 72 zapReporter.Store(r.ReportZap) 73 } 74 if r.ContextField != nil { 75 contextField.Store(r.ContextField) 76 } 77 } 78 79 func GetReportZapFunc() reportZapFunc { 80 return zapReporter.Load().(reportZapFunc) 81 } 82 83 func GetContextFieldFunc() contextFieldFunc { 84 return contextField.Load().(contextFieldFunc) 85 } 86 87 var _ zapcore.Encoder = (*TraceLogEncoder)(nil) 88 89 type TraceLogEncoder struct { 90 zapcore.Encoder 91 spanContextField zap.Field 92 discardable bool 93 } 94 95 func (e *TraceLogEncoder) Clone() zapcore.Encoder { 96 return &TraceLogEncoder{ 97 Encoder: e.Encoder.Clone(), 98 } 99 } 100 101 var SpanFieldKey atomic.Value 102 103 func (e *TraceLogEncoder) AddObject(key string, val zapcore.ObjectMarshaler) error { 104 if key == SpanFieldKey.Load().(string) { 105 //e.sp = obj.(*trace.SpanContext) 106 e.spanContextField = zap.Object(key, val) 107 return nil 108 } 109 return e.Encoder.AddObject(key, val) 110 } 111 112 // AddBool implements zapcore.ObjectEncoder, hook zapcore.Core's With(...) api 113 func (e *TraceLogEncoder) AddBool(key string, value bool) { 114 if key == MOInternalFiledKeyDiscardable { 115 e.discardable = true 116 } 117 } 118 119 func (e *TraceLogEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) { 120 if e.spanContextField.Key == SpanFieldKey.Load().(string) { 121 fields = append(fields, e.spanContextField) 122 } 123 if e.discardable { 124 fields = append(fields, Discardable()) 125 } 126 for _, v := range fields { 127 if v.Type == zapcore.BoolType && v.Key == MOInternalFiledKeyNoopReport { 128 return e.Encoder.EncodeEntry(entry, fields[:0]) 129 } 130 } 131 return GetReportZapFunc()(e.Encoder, entry, fields) 132 } 133 134 const MOInternalFiledKeyNoopReport = "MOInternalFiledKeyNoopReport" 135 136 // MOInternalFiledKeyDiscardable mark 137 const MOInternalFiledKeyDiscardable = "MODiscardable" 138 139 func newTraceLogEncoder() *TraceLogEncoder { 140 // default like zap.NewProductionEncoderConfig(), but clean core-elems ENCODE 141 e := &TraceLogEncoder{ 142 Encoder: zapcore.NewJSONEncoder( 143 zapcore.EncoderConfig{ 144 StacktraceKey: "", 145 SkipLineEnding: true, 146 LineEnding: zapcore.DefaultLineEnding, 147 EncodeLevel: zapcore.LowercaseLevelEncoder, 148 EncodeTime: zapcore.EpochTimeEncoder, 149 EncodeDuration: zapcore.SecondsDurationEncoder, 150 EncodeCaller: zapcore.ShortCallerEncoder, 151 }), 152 } 153 return e 154 } 155 156 func getTraceLogSinks() (zapcore.Encoder, zapcore.WriteSyncer) { 157 return newTraceLogEncoder(), zapcore.AddSync(io.Discard) 158 } 159 160 func init() { 161 SpanFieldKey.Store("__MO_NOT_SET_SPAN") 162 }