github.com/matrixorigin/matrixone@v0.7.0/pkg/util/trace/impl/motrace/schema.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  	"time"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/util/export/table"
    22  
    23  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    24  	"github.com/matrixorigin/matrixone/pkg/logutil"
    25  	ie "github.com/matrixorigin/matrixone/pkg/util/internalExecutor"
    26  )
    27  
    28  const (
    29  	SystemDBConst = "system"
    30  	StatsDatabase = SystemDBConst
    31  )
    32  const (
    33  	// statementInfoTbl is an EXTERNAL table
    34  	statementInfoTbl = "statement_info"
    35  	rawLogTbl        = "rawlog"
    36  
    37  	// spanInfoTbl is a view
    38  	spanInfoTbl  = "span_info"
    39  	logInfoTbl   = "log_info"
    40  	errorInfoTbl = "error_info"
    41  )
    42  
    43  var (
    44  	stmtIDCol    = table.UuidStringColumn("statement_id", "statement uniq id")
    45  	txnIDCol     = table.UuidStringColumn("transaction_id", "txn uniq id")
    46  	sesIDCol     = table.UuidStringColumn("session_id", "session uniq id")
    47  	accountCol   = table.StringColumn("account", "account name")
    48  	roleIdCol    = table.Int64Column("role_id", "role id")
    49  	userCol      = table.StringColumn("user", "user name")
    50  	hostCol      = table.StringColumn("host", "user client ip")
    51  	dbCol        = table.StringColumn("database", "what database current session stay in.")
    52  	stmtCol      = table.TextColumn("statement", "sql statement")
    53  	stmtTagCol   = table.TextColumn("statement_tag", "note tag in statement(Reserved)")
    54  	stmtFgCol    = table.TextColumn("statement_fingerprint", "note tag in statement(Reserved)")
    55  	nodeUUIDCol  = table.UuidStringColumn("node_uuid", "node uuid, which node gen this data.")
    56  	nodeTypeCol  = table.StringColumn("node_type", "node type in MO, val in [DN, CN, LOG]")
    57  	reqAtCol     = table.DatetimeColumn("request_at", "request accept datetime")
    58  	respAtCol    = table.DatetimeColumn("response_at", "response send datetime")
    59  	durationCol  = table.UInt64Column("duration", "exec time, unit: ns")
    60  	statusCol    = table.StringColumn("status", "sql statement running status, enum: Running, Success, Failed")
    61  	errorCol     = table.TextColumn("error", "error message")
    62  	execPlanCol  = table.JsonColumn("exec_plan", "statement execution plan")
    63  	rowsReadCol  = table.Int64Column("rows_read", "rows read total")
    64  	bytesScanCol = table.Int64Column("bytes_scan", "bytes scan total")
    65  	statsCol     = table.JsonColumn("stats", "global stats info in exec_plan")
    66  	stmtTypeCol  = table.StringColumn("statement_type", "statement type, val in [Insert, Delete, Update, Drop Table, Drop User, ...]")
    67  	queryTypeCol = table.StringColumn("query_type", "query type, val in [DQL, DDL, DML, DCL, TCL]")
    68  	sqlTypeCol   = table.TextColumn("sql_source_type", "sql statement source type")
    69  
    70  	SingleStatementTable = &table.Table{
    71  		Account:  table.AccountAll,
    72  		Database: StatsDatabase,
    73  		Table:    statementInfoTbl,
    74  		Columns: []table.Column{
    75  			stmtIDCol,
    76  			txnIDCol,
    77  			sesIDCol,
    78  			accountCol,
    79  			userCol,
    80  			hostCol,
    81  			dbCol,
    82  			stmtCol,
    83  			stmtTagCol,
    84  			stmtFgCol,
    85  			nodeUUIDCol,
    86  			nodeTypeCol,
    87  			reqAtCol,
    88  			respAtCol,
    89  			durationCol,
    90  			statusCol,
    91  			errCodeCol,
    92  			errorCol,
    93  			execPlanCol,
    94  			rowsReadCol,
    95  			bytesScanCol,
    96  			statsCol,
    97  			stmtTypeCol,
    98  			queryTypeCol,
    99  			roleIdCol,
   100  			sqlTypeCol,
   101  		},
   102  		PrimaryKeyColumn: []table.Column{stmtIDCol},
   103  		Engine:           table.ExternalTableEngine,
   104  		Comment:          "record each statement and stats info",
   105  		PathBuilder:      table.NewAccountDatePathBuilder(),
   106  		AccountColumn:    &accountCol,
   107  		// SupportUserAccess
   108  		SupportUserAccess: true,
   109  	}
   110  
   111  	rawItemCol      = table.StringColumn("raw_item", "raw log item")
   112  	timestampCol    = table.DatetimeColumn("timestamp", "timestamp of action")
   113  	loggerNameCol   = table.StringColumn("logger_name", "logger name")
   114  	levelCol        = table.StringColumn("level", "log level, enum: debug, info, warn, error, panic, fatal")
   115  	callerCol       = table.StringColumn("caller", "where it log, like: package/file.go:123")
   116  	messageCol      = table.TextColumn("message", "log message")
   117  	extraCol        = table.JsonColumn("extra", "log dynamic fields")
   118  	errCodeCol      = table.StringDefaultColumn("err_code", `0`, "error code info")
   119  	stackCol        = table.StringWithPrecision("stack", 4096, "stack info")
   120  	traceIDCol      = table.UuidStringColumn("trace_id", "trace uniq id")
   121  	spanIDCol       = table.SpanIDStringColumn("span_id", "span uniq id")
   122  	spanKindCol     = table.StringColumn("span_kind", "span kind, enum: internal, statement, remote")
   123  	parentSpanIDCol = table.SpanIDStringColumn("parent_span_id", "parent span uniq id")
   124  	spanNameCol     = table.StringColumn("span_name", "span name, for example: step name of execution plan, function name in code, ...")
   125  	startTimeCol    = table.DatetimeColumn("start_time", "start time")
   126  	endTimeCol      = table.DatetimeColumn("end_time", "end time")
   127  	resourceCol     = table.JsonColumn("resource", "static resource information")
   128  
   129  	SingleRowLogTable = &table.Table{
   130  		Account:  table.AccountAll,
   131  		Database: StatsDatabase,
   132  		Table:    rawLogTbl,
   133  		Columns: []table.Column{
   134  			rawItemCol,
   135  			nodeUUIDCol,
   136  			nodeTypeCol,
   137  			spanIDCol,
   138  			traceIDCol,
   139  			loggerNameCol,
   140  			timestampCol,
   141  			levelCol,
   142  			callerCol,
   143  			messageCol,
   144  			extraCol,
   145  			errCodeCol,
   146  			errorCol,
   147  			stackCol,
   148  			spanNameCol,
   149  			parentSpanIDCol,
   150  			startTimeCol,
   151  			endTimeCol,
   152  			durationCol,
   153  			resourceCol,
   154  			spanKindCol,
   155  		},
   156  		PrimaryKeyColumn: nil,
   157  		Engine:           table.ExternalTableEngine,
   158  		Comment:          "read merge data from log, error, span",
   159  		PathBuilder:      table.NewAccountDatePathBuilder(),
   160  		AccountColumn:    nil,
   161  		// SupportUserAccess
   162  		SupportUserAccess: false,
   163  	}
   164  
   165  	logView = &table.View{
   166  		Database:    StatsDatabase,
   167  		Table:       logInfoTbl,
   168  		OriginTable: SingleRowLogTable,
   169  		Columns: []table.Column{
   170  			traceIDCol,
   171  			spanIDCol,
   172  			spanKindCol,
   173  			nodeUUIDCol,
   174  			nodeTypeCol,
   175  			timestampCol,
   176  			loggerNameCol,
   177  			levelCol,
   178  			callerCol,
   179  			messageCol,
   180  			extraCol,
   181  			stackCol,
   182  		},
   183  		Condition: &table.ViewSingleCondition{Column: rawItemCol, Table: logInfoTbl},
   184  	}
   185  
   186  	errorView = &table.View{
   187  		Database:    StatsDatabase,
   188  		Table:       errorInfoTbl,
   189  		OriginTable: SingleRowLogTable,
   190  		Columns: []table.Column{
   191  			timestampCol,
   192  			errCodeCol,
   193  			errorCol,
   194  			traceIDCol,
   195  			spanIDCol,
   196  			spanKindCol,
   197  			nodeUUIDCol,
   198  			nodeTypeCol,
   199  			stackCol,
   200  		},
   201  		Condition: &table.ViewSingleCondition{Column: rawItemCol, Table: errorInfoTbl},
   202  	}
   203  
   204  	spanView = &table.View{
   205  		Database:    StatsDatabase,
   206  		Table:       spanInfoTbl,
   207  		OriginTable: SingleRowLogTable,
   208  		Columns: []table.Column{
   209  			traceIDCol,
   210  			spanIDCol,
   211  			parentSpanIDCol,
   212  			spanKindCol,
   213  			nodeUUIDCol,
   214  			nodeTypeCol,
   215  			spanNameCol,
   216  			startTimeCol,
   217  			endTimeCol,
   218  			durationCol,
   219  			resourceCol,
   220  		},
   221  		Condition: &table.ViewSingleCondition{Column: rawItemCol, Table: spanInfoTbl},
   222  	}
   223  )
   224  
   225  const (
   226  	sqlCreateDBConst = `create database if not exists ` + StatsDatabase
   227  )
   228  
   229  var tables = []*table.Table{SingleStatementTable, SingleRowLogTable}
   230  var views = []*table.View{logView, errorView, spanView}
   231  
   232  // InitSchemaByInnerExecutor init schema, which can access db by io.InternalExecutor on any Node.
   233  func InitSchemaByInnerExecutor(ctx context.Context, ieFactory func() ie.InternalExecutor) error {
   234  	exec := ieFactory()
   235  	if exec == nil {
   236  		return nil
   237  	}
   238  	exec.ApplySessionOverride(ie.NewOptsBuilder().Database(StatsDatabase).Internal(true).Finish())
   239  	mustExec := func(sql string) error {
   240  		if err := exec.Exec(ctx, sql, ie.NewOptsBuilder().Finish()); err != nil {
   241  			return moerr.NewInternalError(ctx, "[Trace] init table error: %v, sql: %s", err, sql)
   242  		}
   243  		return nil
   244  	}
   245  
   246  	if err := mustExec(sqlCreateDBConst); err != nil {
   247  		return err
   248  	}
   249  	var createCost time.Duration
   250  	defer func() {
   251  		logutil.Debugf("[Trace] init tables: create cost %d ms",
   252  			createCost.Milliseconds())
   253  	}()
   254  	instant := time.Now()
   255  
   256  	for _, tbl := range tables {
   257  		if err := mustExec(tbl.ToCreateSql(ctx, true)); err != nil {
   258  			return err
   259  		}
   260  	}
   261  	for _, v := range views {
   262  		if err := mustExec(v.ToCreateSql(ctx, true)); err != nil {
   263  			return err
   264  		}
   265  	}
   266  
   267  	createCost = time.Since(instant)
   268  	return nil
   269  }
   270  
   271  // GetSchemaForAccount return account's table, and view's schema
   272  func GetSchemaForAccount(ctx context.Context, account string) []string {
   273  	var sqls = make([]string, 0, 1)
   274  	for _, tbl := range tables {
   275  		if tbl.SupportUserAccess {
   276  			t := tbl.Clone()
   277  			t.Account = account
   278  			sqls = append(sqls, t.ToCreateSql(ctx, true))
   279  		}
   280  	}
   281  	for _, v := range views {
   282  		if v.OriginTable.SupportUserAccess {
   283  			sqls = append(sqls, v.ToCreateSql(ctx, true))
   284  		}
   285  
   286  	}
   287  	return sqls
   288  }
   289  
   290  func init() {
   291  	for _, tbl := range tables {
   292  		tbl.GetRow(context.Background()).Free()
   293  		if old := table.RegisterTableDefine(tbl); old != nil {
   294  			panic(moerr.NewInternalError(context.Background(), "table already registered: %s", old.GetIdentify()))
   295  		}
   296  	}
   297  }