github.com/matrixorigin/matrixone@v1.2.0/pkg/util/trace/impl/motrace/trace.go (about)

     1  // Copyright The OpenTelemetry Authors
     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  // Portions of this file are additionally subject to the following
    16  // copyright.
    17  //
    18  // Copyright (C) 2022 Matrix Origin.
    19  //
    20  // Modified the behavior and the interface of the step.
    21  
    22  package motrace
    23  
    24  import (
    25  	"context"
    26  	"sync/atomic"
    27  	"time"
    28  
    29  	"github.com/matrixorigin/matrixone/pkg/catalog"
    30  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    31  	"github.com/matrixorigin/matrixone/pkg/config"
    32  	"github.com/matrixorigin/matrixone/pkg/defines"
    33  	"github.com/matrixorigin/matrixone/pkg/logutil"
    34  	"github.com/matrixorigin/matrixone/pkg/util/batchpipe"
    35  	"github.com/matrixorigin/matrixone/pkg/util/errutil"
    36  	"github.com/matrixorigin/matrixone/pkg/util/executor"
    37  	db_holder "github.com/matrixorigin/matrixone/pkg/util/export/etl/db"
    38  	ie "github.com/matrixorigin/matrixone/pkg/util/internalExecutor"
    39  	"github.com/matrixorigin/matrixone/pkg/util/trace"
    40  )
    41  
    42  var gTracerProvider atomic.Value
    43  var gTracer trace.Tracer
    44  var gTraceContext atomic.Value
    45  var gSpanContext atomic.Value
    46  
    47  func init() {
    48  	SetDefaultSpanContext(&trace.SpanContext{})
    49  	SetDefaultContext(context.Background())
    50  	tp := newMOTracerProvider(EnableTracer(false))
    51  	gTracer = tp.Tracer("default")
    52  	SetTracerProvider(tp)
    53  }
    54  
    55  var inited uint32
    56  
    57  func InitWithConfig(ctx context.Context, SV *config.ObservabilityParameters, opts ...TracerProviderOption) (error, bool) {
    58  	opts = append(opts,
    59  		withMOVersion(SV.MoVersion),
    60  		EnableTracer(!SV.DisableTrace),
    61  		WithExportInterval(SV.TraceExportInterval),
    62  		WithLongQueryTime(SV.LongQueryTime),
    63  		WithLongSpanTime(SV.LongSpanTime.Duration),
    64  		WithSpanDisable(SV.DisableSpan),
    65  		WithErrorDisable(SV.DisableError),
    66  		WithSkipRunningStmt(SV.SkipRunningStmt),
    67  		WithSQLWriterDisable(SV.DisableSqlWriter),
    68  		WithAggregatorDisable(SV.DisableStmtAggregation),
    69  		WithAggregatorWindow(SV.AggregationWindow.Duration),
    70  		WithSelectThreshold(SV.SelectAggrThreshold.Duration),
    71  		WithStmtMergeEnable(SV.EnableStmtMerge),
    72  		WithCUConfig(SV.CU, SV.CUv1),
    73  		WithTCPPacket(SV.TCPPacket),
    74  		WithLabels(SV.LabelSelector),
    75  
    76  		DebugMode(SV.EnableTraceDebug),
    77  		WithBufferSizeThreshold(SV.BufferSize),
    78  	)
    79  	return Init(ctx, opts...)
    80  }
    81  
    82  // Init initializes the tracer with the given options.
    83  // If EnableTracer is set to false, this function does nothing.
    84  // If EnableTracer is set to true, the tracer is initialized.
    85  // Init only allow called once.
    86  func Init(ctx context.Context, opts ...TracerProviderOption) (err error, act bool) {
    87  	// fix multi-init in standalone
    88  	if !atomic.CompareAndSwapUint32(&inited, 0, 1) {
    89  		return nil, false
    90  	}
    91  
    92  	// init TraceProvider
    93  	SetTracerProvider(newMOTracerProvider(opts...))
    94  	config := &GetTracerProvider().tracerProviderConfig
    95  
    96  	if !config.disableSpan {
    97  		// init Tracer
    98  		gTracer = GetTracerProvider().Tracer("MatrixOne")
    99  		_, span := gTracer.Start(ctx, "TraceInit")
   100  		defer span.End()
   101  		defer trace.SetDefaultTracer(gTracer)
   102  	}
   103  	if config.disableError {
   104  		DisableLogErrorReport(true)
   105  	}
   106  
   107  	// init DefaultContext / DefaultSpanContext
   108  	var spanId trace.SpanID
   109  	spanId.SetByUUID(config.getNodeResource().NodeUuid)
   110  	sc := trace.SpanContextWithIDs(trace.NilTraceID, spanId)
   111  	SetDefaultSpanContext(&sc)
   112  	serviceCtx := context.Background()
   113  	SetDefaultContext(trace.ContextWithSpanContext(serviceCtx, sc))
   114  	SetCuConfig(&config.cuConfig, &config.cuConfigV1)
   115  
   116  	// init Exporter
   117  	if err := initExporter(ctx, config); err != nil {
   118  		return err, true
   119  	}
   120  
   121  	// init all mo_ctl controlled spans
   122  	trace.InitMOCtledSpan()
   123  
   124  	// init tool dependence
   125  	logutil.SetLogReporter(&logutil.TraceReporter{ReportZap: ReportZap, ContextField: trace.ContextField})
   126  	logutil.SpanFieldKey.Store(trace.SpanFieldKey)
   127  	errutil.SetErrorReporter(ReportError)
   128  
   129  	// init db_hodler
   130  	db_holder.SetLabelSelector(config.labels)
   131  
   132  	logutil.Debugf("trace with LongQueryTime: %v", time.Duration(GetTracerProvider().longQueryTime))
   133  	logutil.Debugf("trace with LongSpanTime: %v", GetTracerProvider().longSpanTime)
   134  	logutil.Debugf("trace with DisableSpan: %v", GetTracerProvider().disableSpan)
   135  
   136  	return nil, true
   137  }
   138  
   139  func initExporter(ctx context.Context, config *tracerProviderConfig) error {
   140  	if !config.IsEnable() {
   141  		return nil
   142  	}
   143  	if config.needInit {
   144  		if err := InitSchema(ctx, config.sqlExecutor); err != nil {
   145  			return err
   146  		}
   147  	}
   148  	defaultReminder := batchpipe.NewConstantClock(config.exportInterval)
   149  	defaultOptions := []BufferOption{BufferWithReminder(defaultReminder), BufferWithSizeThreshold(config.bufferSizeThreshold)}
   150  	var p = config.batchProcessor
   151  	// init BatchProcess for trace/log/error
   152  	p.Register(&MOSpan{}, NewBufferPipe2CSVWorker(defaultOptions...))
   153  	p.Register(&MOZapLog{}, NewBufferPipe2CSVWorker(defaultOptions...))
   154  	p.Register(&StatementInfo{}, NewBufferPipe2CSVWorker(defaultOptions...))
   155  	p.Register(&MOErrorHolder{}, NewBufferPipe2CSVWorker(defaultOptions...))
   156  	logutil.Info("init GlobalBatchProcessor")
   157  	if !p.Start() {
   158  		return moerr.NewInternalError(ctx, "trace exporter already started")
   159  	}
   160  	config.spanProcessors = append(config.spanProcessors, NewBatchSpanProcessor(p))
   161  	logutil.Info("init trace span processor")
   162  	return nil
   163  }
   164  
   165  // InitSchema
   166  // PS: only in standalone or CN node can init schema
   167  func InitSchema(ctx context.Context, sqlExecutor func() ie.InternalExecutor) error {
   168  	ctx = defines.AttachAccount(ctx, catalog.System_Account, catalog.System_User, catalog.System_Role)
   169  	c := &GetTracerProvider().tracerProviderConfig
   170  	WithSQLExecutor(sqlExecutor).apply(c)
   171  	if err := InitSchemaByInnerExecutor(ctx, sqlExecutor); err != nil {
   172  		return err
   173  	}
   174  	return nil
   175  }
   176  
   177  // InitSchema2
   178  // PS: only in system bootstrap init schema with `executor.TxnExecutor`
   179  func InitSchemaWithTxn(ctx context.Context, txn executor.TxnExecutor) error {
   180  	_, err := txn.Exec(sqlCreateDBConst, executor.StatementOption{})
   181  	if err != nil {
   182  		return err
   183  	}
   184  
   185  	var createCost time.Duration
   186  	defer func() {
   187  		logutil.Debugf("[Trace] init tables: create cost %d ms", createCost.Milliseconds())
   188  	}()
   189  
   190  	instant := time.Now()
   191  	for _, tbl := range tables {
   192  		_, err = txn.Exec(tbl.ToCreateSql(ctx, true), executor.StatementOption{})
   193  		if err != nil {
   194  			return err
   195  		}
   196  	}
   197  
   198  	for _, v := range views {
   199  		_, err = txn.Exec(v.ToCreateSql(ctx, true), executor.StatementOption{})
   200  		if err != nil {
   201  			return err
   202  		}
   203  	}
   204  	createCost = time.Since(instant)
   205  	return nil
   206  }
   207  
   208  func Shutdown(ctx context.Context) error {
   209  	if !GetTracerProvider().IsEnable() {
   210  		return nil
   211  	}
   212  	GetTracerProvider().SetEnable(false)
   213  
   214  	shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
   215  	defer cancel()
   216  	for _, p := range GetTracerProvider().spanProcessors {
   217  		if err := p.Shutdown(shutdownCtx); err != nil {
   218  			return err
   219  		}
   220  	}
   221  	logutil.Info("Shutdown trace complete.")
   222  	return nil
   223  }
   224  
   225  type contextHolder struct {
   226  	ctx context.Context
   227  }
   228  
   229  func SetDefaultContext(ctx context.Context) {
   230  	gTraceContext.Store(&contextHolder{ctx})
   231  }
   232  
   233  func DefaultContext() context.Context {
   234  	return gTraceContext.Load().(*contextHolder).ctx
   235  }
   236  
   237  func SetDefaultSpanContext(sc *trace.SpanContext) {
   238  	gSpanContext.Store(sc)
   239  }
   240  
   241  func DefaultSpanContext() *trace.SpanContext {
   242  	return gSpanContext.Load().(*trace.SpanContext)
   243  }
   244  
   245  func GetNodeResource() *trace.MONodeResource {
   246  	return GetTracerProvider().getNodeResource()
   247  }
   248  
   249  func SetTracerProvider(p *MOTracerProvider) {
   250  	gTracerProvider.Store(p)
   251  }
   252  
   253  // GetTracerProvider returns the global TracerProvider.
   254  // It will be initialized at startup.
   255  var GetTracerProvider = func() *MOTracerProvider {
   256  	return gTracerProvider.Load().(*MOTracerProvider)
   257  }
   258  
   259  func GetSQLExecutorFactory() func() ie.InternalExecutor {
   260  	p := GetTracerProvider()
   261  	if p != nil {
   262  		p.mux.Lock()
   263  		defer p.mux.Unlock()
   264  		return p.tracerProviderConfig.sqlExecutor
   265  	}
   266  	return nil
   267  }
   268  
   269  type PipeImpl batchpipe.PipeImpl[batchpipe.HasName, any]
   270  
   271  type BatchProcessor interface {
   272  	Collect(context.Context, batchpipe.HasName) error
   273  	Start() bool
   274  	Stop(graceful bool) error
   275  	Register(name batchpipe.HasName, impl PipeImpl)
   276  }
   277  
   278  type DiscardableCollector interface {
   279  	DiscardableCollect(context.Context, batchpipe.HasName) error
   280  }
   281  
   282  var _ BatchProcessor = &NoopBatchProcessor{}
   283  
   284  type NoopBatchProcessor struct {
   285  }
   286  
   287  func (n NoopBatchProcessor) Collect(context.Context, batchpipe.HasName) error { return nil }
   288  func (n NoopBatchProcessor) Start() bool                                      { return true }
   289  func (n NoopBatchProcessor) Stop(bool) error                                  { return nil }
   290  func (n NoopBatchProcessor) Register(batchpipe.HasName, PipeImpl)             {}
   291  
   292  func GetGlobalBatchProcessor() BatchProcessor {
   293  	return GetTracerProvider().batchProcessor
   294  }