github.com/matrixorigin/matrixone@v1.2.0/pkg/util/trace/impl/motrace/report_log.go (about) 1 // Copyright 2022 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 motrace 16 17 import ( 18 "context" 19 "encoding/hex" 20 "sync" 21 "time" 22 "unsafe" 23 24 "github.com/matrixorigin/matrixone/pkg/logutil" 25 "github.com/matrixorigin/matrixone/pkg/util/batchpipe" 26 "github.com/matrixorigin/matrixone/pkg/util/export/table" 27 "github.com/matrixorigin/matrixone/pkg/util/metric" 28 "github.com/matrixorigin/matrixone/pkg/util/trace" 29 30 "go.uber.org/zap" 31 "go.uber.org/zap/buffer" 32 "go.uber.org/zap/zapcore" 33 ) 34 35 var _ batchpipe.HasName = (*MOZapLog)(nil) 36 37 // MOZapLog implement export.IBuffer2SqlItem and export.CsvFields 38 type MOZapLog struct { 39 Level zapcore.Level `json:"Level"` 40 SpanContext *trace.SpanContext `json:"span"` 41 Timestamp time.Time `json:"timestamp"` 42 LoggerName string 43 Caller string `json:"caller"` // like "util/trace/trace.go:666" 44 Message string `json:"message"` 45 Extra string `json:"extra"` // like json text 46 Stack string `json:"stack"` 47 SessionID [16]byte `json:"session_id"` 48 StatementID [16]byte `json:"statement_id"` 49 } 50 51 var logPool = sync.Pool{ 52 New: func() any { 53 return &MOZapLog{} 54 }, 55 } 56 57 func newMOZap() *MOZapLog { 58 return logPool.Get().(*MOZapLog) 59 } 60 61 func (m *MOZapLog) GetName() string { 62 return logView.OriginTable.GetName() 63 } 64 65 // deltaContentLength approximate value that may gen as table record 66 // timestamp: 26 67 // level: 5 68 // itemName: 8 69 // nodeInfo: 40 /*36+4*/ 70 // spanInfo: 36+16 71 const ( 72 deltaContentLength = int64(26 + 5 + 8 + 40 + 36 + 16) 73 74 session_id = "session_id" 75 76 statement_id = "statement_id" 77 ) 78 79 // Size 计算近似值 80 func (m *MOZapLog) Size() int64 { 81 return int64(unsafe.Sizeof(m)) + int64(len(m.LoggerName)+len(m.Caller)+len(m.Message)+len(m.Extra)+len(m.Stack)) + 82 deltaContentLength 83 } 84 85 func (m *MOZapLog) Free() { 86 m.SpanContext = nil 87 m.LoggerName = "" 88 m.Caller = "" 89 m.Message = "" 90 m.Extra = "" 91 logPool.Put(m) 92 } 93 94 func (m *MOZapLog) GetTable() *table.Table { return logView.OriginTable } 95 96 func (m *MOZapLog) FillRow(ctx context.Context, row *table.Row) { 97 row.Reset() 98 row.SetColumnVal(rawItemCol, table.StringField(logView.Table)) 99 if m.SpanContext.TraceID != trace.NilTraceID { 100 row.SetColumnVal(traceIDCol, table.UuidField(m.SpanContext.TraceID[:])) 101 } 102 if m.SpanContext.SpanID != trace.NilSpanID { 103 row.SetColumnVal(spanIDCol, table.StringField(hex.EncodeToString(m.SpanContext.SpanID[:]))) 104 } 105 row.SetColumnVal(spanKindCol, table.StringField(m.SpanContext.Kind.String())) 106 row.SetColumnVal(nodeUUIDCol, table.StringField(GetNodeResource().NodeUuid)) 107 row.SetColumnVal(nodeTypeCol, table.StringField(GetNodeResource().NodeType)) 108 row.SetColumnVal(timestampCol, table.TimeField(m.Timestamp)) 109 row.SetColumnVal(loggerNameCol, table.StringField(m.LoggerName)) 110 row.SetColumnVal(levelCol, table.StringField(m.Level.String())) 111 row.SetColumnVal(callerCol, table.StringField(m.Caller)) 112 row.SetColumnVal(messageCol, table.StringField(m.Message)) 113 row.SetColumnVal(extraCol, table.StringField(m.Extra)) 114 row.SetColumnVal(stackCol, table.StringField(m.Stack)) 115 if m.SessionID != [16]byte{} { 116 row.SetColumnVal(sessionIDCol, table.UuidField(m.SessionID[:])) 117 } 118 if m.StatementID != [16]byte{} { 119 row.SetColumnVal(sessionIDCol, table.UuidField(m.SessionID[:])) 120 } 121 } 122 123 func ReportZap(jsonEncoder zapcore.Encoder, entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) { 124 var discardable = false 125 // count log message each minute 126 metric.MOLogMessageCounter(entry.Level.String()).Add(1) 127 // check trace is enable 128 if !GetTracerProvider().IsEnable() { 129 return jsonEncoder.EncodeEntry(entry, []zap.Field{}) 130 } 131 log := newMOZap() 132 log.LoggerName = entry.LoggerName 133 log.Level = entry.Level 134 log.Message = entry.Message 135 log.Caller = entry.Caller.TrimmedPath() 136 log.Timestamp = entry.Time 137 log.SpanContext = DefaultSpanContext() 138 log.Stack = entry.Stack 139 // find SpanContext 140 endIdx := len(fields) - 1 141 for idx, v := range fields { 142 if v.Type == zapcore.BoolType && v.Key == logutil.MOInternalFiledKeyDiscardable { 143 discardable = true 144 } 145 if trace.IsSpanField(v) { 146 log.SpanContext = v.Interface.(*trace.SpanContext) 147 // find endIdx 148 for ; idx < endIdx && trace.IsSpanField(fields[endIdx]); endIdx-- { 149 } 150 if idx <= endIdx { 151 fields[idx], fields[endIdx] = fields[endIdx], fields[idx] 152 endIdx-- 153 } 154 continue 155 } 156 157 if v.Type == zapcore.ByteStringType { 158 if v.Key == session_id { 159 copy(log.SessionID[:], v.Interface.([]byte)) 160 } else if v.Key == statement_id { 161 copy(log.StatementID[:], v.Interface.([]byte)) 162 } 163 } 164 if idx == endIdx { 165 break 166 } 167 } 168 buffer, err := jsonEncoder.EncodeEntry(entry, fields[:endIdx+1]) 169 log.Extra = buffer.String() 170 collector := GetGlobalBatchProcessor() 171 var collectFunc = collector.Collect 172 if discardable { 173 if c, support := collector.(DiscardableCollector); support { 174 collectFunc = c.DiscardableCollect 175 } 176 } 177 switch entry.Level { 178 case zap.PanicLevel, zap.DPanicLevel, zap.FatalLevel: 179 syncer := NewItemSyncer(log) 180 collectFunc(DefaultContext(), syncer) 181 syncer.Wait() 182 default: 183 collectFunc(DefaultContext(), log) 184 } 185 return buffer, err 186 }