github.com/matrixorigin/matrixone@v1.2.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 "fmt" 20 "time" 21 22 "github.com/matrixorigin/matrixone/pkg/catalog" 23 "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace/statistic" 24 25 "github.com/matrixorigin/matrixone/pkg/util/export/table" 26 27 "github.com/matrixorigin/matrixone/pkg/common/moerr" 28 "github.com/matrixorigin/matrixone/pkg/logutil" 29 ie "github.com/matrixorigin/matrixone/pkg/util/internalExecutor" 30 ) 31 32 const ( 33 SystemDBConst = "system" 34 StatsDatabase = SystemDBConst 35 ) 36 const ( 37 // statementInfoTbl is an EXTERNAL table 38 statementInfoTbl = "statement_info" 39 RawLogTbl = "rawlog" 40 41 // spanInfoTbl is a view 42 spanInfoTbl = "span_info" 43 logInfoTbl = "log_info" 44 errorInfoTbl = "error_info" 45 46 SqlStatementHotspotTbl = "sql_statement_hotspot" 47 ) 48 49 var ( 50 stmtIDCol = table.UuidStringColumn("statement_id", "statement uniq id") 51 txnIDCol = table.UuidStringColumn("transaction_id", "txn uniq id") 52 sesIDCol = table.UuidStringColumn("session_id", "session uniq id") 53 accountCol = table.StringColumn("account", "account name") 54 roleIdCol = table.Int64Column("role_id", "role id") 55 userCol = table.StringColumn("user", "user name") 56 hostCol = table.StringColumn("host", "user client ip") 57 dbCol = table.StringColumn("database", "what database current session stay in.") 58 stmtCol = table.TextColumn("statement", "sql statement") 59 stmtTagCol = table.TextColumn("statement_tag", "note tag in statement(Reserved)") 60 stmtFgCol = table.TextColumn("statement_fingerprint", "note tag in statement(Reserved)") 61 nodeUUIDCol = table.UuidStringColumn("node_uuid", "node uuid, which node gen this data.") 62 nodeTypeCol = table.StringColumn("node_type", "node type in MO, val in [DN, CN, LOG]") 63 reqAtCol = table.DatetimeColumn("request_at", "request accept datetime") 64 respAtCol = table.DatetimeColumn("response_at", "response send datetime") 65 durationCol = table.UInt64Column("duration", "exec time, unit: ns") 66 statusCol = table.StringColumn("status", "sql statement running status, enum: Running, Success, Failed") 67 errorCol = table.TextColumn("error", "error message") 68 execPlanCol = table.TextDefaultColumn("exec_plan", `{}`, "statement execution plan") 69 rowsReadCol = table.Int64Column("rows_read", "rows read total") 70 bytesScanCol = table.Int64Column("bytes_scan", "bytes scan total") 71 statsCol = table.TextDefaultColumn("stats", `[]`, "global stats info in exec_plan") 72 stmtTypeCol = table.StringColumn("statement_type", "statement type, val in [Insert, Delete, Update, Drop Table, Drop User, ...]") 73 queryTypeCol = table.StringColumn("query_type", "query type, val in [DQL, DDL, DML, DCL, TCL]") 74 sqlTypeCol = table.TextColumn("sql_source_type", "sql statement source type") 75 aggrCntCol = table.Int64Column("aggr_count", "the number of statements aggregated") 76 resultCntCol = table.Int64Column("result_count", "the number of rows of sql execution results") 77 78 SingleStatementTable = &table.Table{ 79 Account: table.AccountSys, 80 Database: StatsDatabase, 81 Table: statementInfoTbl, 82 Columns: []table.Column{ 83 stmtIDCol, 84 txnIDCol, 85 sesIDCol, 86 accountCol, 87 userCol, 88 hostCol, 89 dbCol, 90 stmtCol, 91 stmtTagCol, 92 stmtFgCol, 93 nodeUUIDCol, 94 nodeTypeCol, 95 reqAtCol, 96 respAtCol, 97 durationCol, 98 statusCol, 99 errCodeCol, 100 errorCol, 101 execPlanCol, 102 rowsReadCol, 103 bytesScanCol, 104 statsCol, 105 stmtTypeCol, 106 queryTypeCol, 107 roleIdCol, 108 sqlTypeCol, 109 aggrCntCol, 110 resultCntCol, 111 }, 112 PrimaryKeyColumn: nil, 113 ClusterBy: []table.Column{reqAtCol}, 114 // Engine 115 Engine: table.NormalTableEngine, 116 Comment: "record each statement and stats info" + catalog.MO_COMMENT_NO_DEL_HINT, 117 PathBuilder: table.NewAccountDatePathBuilder(), 118 AccountColumn: &accountCol, 119 // TimestampColumn 120 TimestampColumn: &respAtCol, 121 // SupportUserAccess 122 SupportUserAccess: true, 123 // SupportConstAccess 124 SupportConstAccess: true, 125 } 126 127 rawItemCol = table.StringColumn("raw_item", "raw log item") 128 timestampCol = table.DatetimeColumn("timestamp", "timestamp of action") 129 loggerNameCol = table.StringColumn("logger_name", "logger name") 130 levelCol = table.StringColumn("level", "log level, enum: debug, info, warn, error, panic, fatal") 131 callerCol = table.StringColumn("caller", "where it log, like: package/file.go:123") 132 messageCol = table.TextColumn("message", "log message") 133 extraCol = table.TextDefaultColumn("extra", `{}`, "log dynamic fields") 134 errCodeCol = table.StringDefaultColumn("err_code", `0`, "error code info") 135 stackCol = table.StringWithScale("stack", 2048, "stack info") 136 traceIDCol = table.UuidStringColumn("trace_id", "trace uniq id") 137 spanIDCol = table.SpanIDStringColumn("span_id", "span uniq id") 138 sessionIDCol = table.UuidStringColumn("session_id", "session id") 139 statementIDCol = table.UuidStringColumn("statement_id", "statement id") 140 spanKindCol = table.StringColumn("span_kind", "span kind, enum: internal, statement, remote") 141 parentSpanIDCol = table.SpanIDStringColumn("parent_span_id", "parent span uniq id") 142 spanNameCol = table.StringColumn("span_name", "span name, for example: step name of execution plan, function name in code, ...") 143 startTimeCol = table.DatetimeColumn("start_time", "start time") 144 endTimeCol = table.DatetimeColumn("end_time", "end time") 145 resourceCol = table.TextDefaultColumn("resource", `{}`, "static resource information") 146 147 UpgradeColumns = map[string]map[string][]table.Column{ 148 "1.0": { 149 "ADD": { 150 statementIDCol, 151 sessionIDCol, 152 }, 153 }, 154 } 155 156 SingleRowLogTable = &table.Table{ 157 Account: table.AccountSys, 158 Database: StatsDatabase, 159 Table: RawLogTbl, 160 Columns: []table.Column{ 161 rawItemCol, 162 nodeUUIDCol, 163 nodeTypeCol, 164 spanIDCol, 165 traceIDCol, 166 loggerNameCol, 167 timestampCol, 168 levelCol, 169 callerCol, 170 messageCol, 171 extraCol, 172 errCodeCol, 173 errorCol, 174 stackCol, 175 spanNameCol, 176 parentSpanIDCol, 177 startTimeCol, 178 endTimeCol, 179 durationCol, 180 resourceCol, 181 spanKindCol, 182 statementIDCol, 183 sessionIDCol, 184 }, 185 PrimaryKeyColumn: nil, 186 ClusterBy: []table.Column{timestampCol}, 187 Engine: table.NormalTableEngine, 188 Comment: "read merge data from log, error, span" + catalog.MO_COMMENT_NO_DEL_HINT, 189 PathBuilder: table.NewAccountDatePathBuilder(), 190 AccountColumn: nil, 191 // TimestampColumn 192 TimestampColumn: ×tampCol, 193 // SupportUserAccess 194 SupportUserAccess: false, 195 // SupportConstAccess 196 SupportConstAccess: true, 197 } 198 199 logView = &table.View{ 200 Database: StatsDatabase, 201 Table: logInfoTbl, 202 OriginTable: SingleRowLogTable, 203 Columns: []table.Column{ 204 traceIDCol, 205 spanIDCol, 206 spanKindCol, 207 nodeUUIDCol, 208 nodeTypeCol, 209 timestampCol, 210 loggerNameCol, 211 levelCol, 212 callerCol, 213 messageCol, 214 extraCol, 215 stackCol, 216 }, 217 Condition: &table.ViewSingleCondition{Column: rawItemCol, Table: logInfoTbl}, 218 } 219 220 errorView = &table.View{ 221 Database: StatsDatabase, 222 Table: errorInfoTbl, 223 OriginTable: SingleRowLogTable, 224 Columns: []table.Column{ 225 timestampCol, 226 errCodeCol, 227 errorCol, 228 traceIDCol, 229 spanIDCol, 230 spanKindCol, 231 nodeUUIDCol, 232 nodeTypeCol, 233 stackCol, 234 }, 235 Condition: &table.ViewSingleCondition{Column: rawItemCol, Table: errorInfoTbl}, 236 } 237 238 spanView = &table.View{ 239 Database: StatsDatabase, 240 Table: spanInfoTbl, 241 OriginTable: SingleRowLogTable, 242 Columns: []table.Column{ 243 traceIDCol, 244 spanIDCol, 245 parentSpanIDCol, 246 spanKindCol, 247 nodeUUIDCol, 248 nodeTypeCol, 249 spanNameCol, 250 startTimeCol, 251 endTimeCol, 252 durationCol, 253 resourceCol, 254 extraCol, 255 }, 256 Condition: &table.ViewSingleCondition{Column: rawItemCol, Table: spanInfoTbl}, 257 } 258 259 SqlStatementHotspotView = &table.View{ 260 Database: StatsDatabase, 261 Table: SqlStatementHotspotTbl, 262 OriginTable: SingleStatementTable, 263 Columns: []table.Column{ 264 table.StringColumn("statement_id", "the statement's uuid"), 265 table.StringColumn("statement", "query's statement"), 266 table.ValueColumn("timeconsumed", "query's exec time (unit: ms)"), 267 table.ValueColumn("memorysize", "query's consume mem size (unit: MiB)"), 268 table.DatetimeColumn("collecttime", "collected time, same as query's response time"), 269 table.StringColumn("node", "cn node uuid"), 270 table.StringColumn("account", "account id "), 271 table.StringColumn("user", "user name"), 272 table.StringColumn("type", "statement type, like: [Insert, Delete, Update, Select, ...]"), 273 }, 274 CreateSql: table.ViewCreateSqlString(fmt.Sprintf(`CREATE VIEW IF NOT EXISTS system.sql_statement_hotspot AS 275 select statement_id, statement, duration / 1e6 as timeconsumed, 276 cast(json_unquote(json_extract(stats, '$[%d]')) / 1048576.00 as decimal(38,3)) as memorysize, 277 response_at as collecttime, 278 node_uuid as node, 279 account, 280 user, 281 statement_type as type 282 from system.statement_info 283 where response_at > date_sub(now(), interval 10 minute) and response_at < now() 284 and aggr_count = 0 order by duration desc limit 10;`, statistic.StatsArrayIndexMemorySize)), 285 SupportUserAccess: false, 286 } 287 ) 288 289 const ( 290 sqlCreateDBConst = `create database if not exists ` + StatsDatabase 291 ) 292 293 var tables = []*table.Table{SingleStatementTable, SingleRowLogTable} 294 var views = []*table.View{logView, errorView, spanView, SqlStatementHotspotView} 295 296 // InitSchemaByInnerExecutor init schema, which can access db by io.InternalExecutor on any Node. 297 func InitSchemaByInnerExecutor(ctx context.Context, ieFactory func() ie.InternalExecutor) error { 298 exec := ieFactory() 299 if exec == nil { 300 return nil 301 } 302 exec.ApplySessionOverride(ie.NewOptsBuilder().Database(StatsDatabase).Internal(true).Finish()) 303 mustExec := func(sql string) error { 304 if err := exec.Exec(ctx, sql, ie.NewOptsBuilder().Finish()); err != nil { 305 return moerr.NewInternalError(ctx, "[Trace] init table error: %v, sql: %s", err, sql) 306 } 307 return nil 308 } 309 310 if err := mustExec(sqlCreateDBConst); err != nil { 311 return err 312 } 313 var createCost time.Duration 314 defer func() { 315 logutil.Debugf("[Trace] init tables: create cost %d ms", 316 createCost.Milliseconds()) 317 }() 318 instant := time.Now() 319 320 for _, tbl := range tables { 321 if err := mustExec(tbl.ToCreateSql(ctx, true)); err != nil { 322 return err 323 } 324 } 325 for _, v := range views { 326 if err := mustExec(v.ToCreateSql(ctx, true)); err != nil { 327 return err 328 } 329 } 330 331 createCost = time.Since(instant) 332 return nil 333 } 334 335 // GetAllTables 336 // 337 // Deprecated: use table.GetAllTables() instead. 338 func GetAllTables() []*table.Table { 339 return tables 340 } 341 342 // GetSchemaForAccount return account's table, and view's schema 343 func GetSchemaForAccount(ctx context.Context, account string) []string { 344 var sqls = make([]string, 0, 1) 345 for _, tbl := range tables { 346 if tbl.SupportUserAccess { 347 t := tbl.Clone() 348 t.Account = account 349 sqls = append(sqls, t.ToCreateSql(ctx, true)) 350 } 351 } 352 for _, v := range views { 353 if v.SupportUserAccess && v.OriginTable.SupportUserAccess { 354 sqls = append(sqls, v.ToCreateSql(ctx, true)) 355 } 356 357 } 358 return sqls 359 } 360 361 func init() { 362 for _, tbl := range tables { 363 tbl.GetRow(context.Background()).Free() 364 if old := table.RegisterTableDefine(tbl); old != nil { 365 panic(moerr.NewInternalError(context.Background(), "table already registered: %s", old.GetIdentify())) 366 } 367 } 368 }