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 }