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  }