diff --git a/internal/testing/database.go b/internal/testing/database.go index cffff934..9fe242fe 100644 --- a/internal/testing/database.go +++ b/internal/testing/database.go @@ -509,18 +509,25 @@ func (m *DatabaseManager) DropDatabase(ctx context.Context, dbName string) error return nil } -// CloneExternalDatabase clones the xatu template database (default) to a per-test database. -// This clones schemas only (empty tables), not data. -// For ReplicatedMergeTree tables, it modifies the ZooKeeper paths to be unique per-test. -// CloneExternalDatabase clones specific tables from the xatu template to a per-test database. -// If tableNames is empty, clones all tables (legacy behavior). -func (m *DatabaseManager) CloneExternalDatabase(ctx context.Context, testID string, tableNames []string) (string, error) { +// cloneSpec describes a table clone operation with potentially different source and target names. +// This supports cross-database external models where the source table name differs from the model name +// (e.g., source observoor.cpu_utilization → target ext_123.observoor_cpu_utilization). +type cloneSpec struct { + sourceDB string + sourceTable string + targetTable string +} + +// CloneExternalDatabase clones specific external tables from the xatu cluster to a per-test database. +// Supports cross-database external models where the source table lives in a non-default database +// (e.g., observoor.cpu_utilization) and needs to be cloned under the model name in the test database. +func (m *DatabaseManager) CloneExternalDatabase(ctx context.Context, testID string, tableRefs []ExternalTableRef) (string, error) { extDBName := config.ExternalDBPrefix + testID logCtx := m.log.WithFields(logrus.Fields{ "cluster": "xatu", "database": extDBName, - "tables": len(tableNames), + "tables": len(tableRefs), }) start := time.Now() @@ -536,20 +543,32 @@ func (m *DatabaseManager) CloneExternalDatabase(ctx context.Context, testID stri } cancel() - // Build list of tables to clone (only specified tables, empty = no tables) - // Clone BOTH _local (ReplicatedMergeTree) AND distributed tables for each model - // Assertions query distributed tables which read from _local tables - tables := make([]tableInfo, 0, len(tableNames)*2) + // Build clone specs for each external table ref. + // Clone BOTH _local (ReplicatedMergeTree) AND distributed tables for each model. + // For cross-database models, the source table name may differ from the target (model) name. + specs := make([]cloneSpec, 0, len(tableRefs)*2) - for _, name := range tableNames { - tables = append(tables, - tableInfo{name: name + "_local"}, // ReplicatedMergeTree table - tableInfo{name: name}, // Distributed table + for _, ref := range tableRefs { + sourceDB := config.DefaultDatabase + sourceTable := ref.ModelName + + if ref.SourceDB != "" { + sourceDB = ref.SourceDB + } + + if ref.SourceTable != "" { + sourceTable = ref.SourceTable + } + + // Clone _local table first (ReplicatedMergeTree), then distributed table + specs = append(specs, + cloneSpec{sourceDB: sourceDB, sourceTable: sourceTable + "_local", targetTable: ref.ModelName + "_local"}, + cloneSpec{sourceDB: sourceDB, sourceTable: sourceTable, targetTable: ref.ModelName}, ) } // If no tables to clone, just return the empty database - if len(tables) == 0 { + if len(specs) == 0 { logCtx.WithFields(logrus.Fields{ "tables": 0, "duration": time.Since(start), @@ -564,13 +583,13 @@ func (m *DatabaseManager) CloneExternalDatabase(ctx context.Context, testID stri var ( cloneWg sync.WaitGroup cloneSem = make(chan struct{}, cloneWorkers) - cloneErrs = make(chan error, len(tables)) + cloneErrs = make(chan error, len(specs)) ) - for _, table := range tables { + for _, spec := range specs { cloneWg.Add(1) - go func(t tableInfo) { + go func(s cloneSpec) { defer cloneWg.Done() // Acquire semaphore @@ -578,10 +597,10 @@ func (m *DatabaseManager) CloneExternalDatabase(ctx context.Context, testID stri defer func() { <-cloneSem }() if cloneErr := m.cloneTableWithUniqueReplicaPath(ctx, m.xatuConn, - config.DefaultDatabase, extDBName, t.name, config.XatuClusterName); cloneErr != nil { - cloneErrs <- fmt.Errorf("cloning table %s: %w", t.name, cloneErr) + s.sourceDB, extDBName, s.sourceTable, s.targetTable, config.XatuClusterName); cloneErr != nil { + cloneErrs <- fmt.Errorf("cloning table %s.%s → %s: %w", s.sourceDB, s.sourceTable, s.targetTable, cloneErr) } - }(table) + }(spec) } cloneWg.Wait() @@ -595,7 +614,7 @@ func (m *DatabaseManager) CloneExternalDatabase(ctx context.Context, testID stri } logCtx.WithFields(logrus.Fields{ - "tables": len(tables), + "tables": len(specs), "duration": time.Since(start), }).Info("external database cloned") @@ -603,41 +622,45 @@ func (m *DatabaseManager) CloneExternalDatabase(ctx context.Context, testID stri } // cloneTableWithUniqueReplicaPath clones a table, modifying ReplicatedMergeTree paths to be unique. +// sourceTable and targetTable may differ for cross-database external models where the source table name +// (e.g., cpu_utilization) differs from the model name used in the test database (e.g., observoor_cpu_utilization). func (m *DatabaseManager) cloneTableWithUniqueReplicaPath( ctx context.Context, conn *sql.DB, - sourceDB, targetDB, tableName, clusterName string, + sourceDB, targetDB, sourceTable, targetTable, clusterName string, ) error { - // Get the CREATE TABLE statement - showSQL := fmt.Sprintf("SHOW CREATE TABLE `%s`.`%s`", sourceDB, tableName) + // Get the CREATE TABLE statement from the source + showSQL := fmt.Sprintf("SHOW CREATE TABLE `%s`.`%s`", sourceDB, sourceTable) queryCtx, cancel := context.WithTimeout(ctx, m.config.QueryTimeout) defer cancel() var createStmt string if err := conn.QueryRowContext(queryCtx, showSQL).Scan(&createStmt); err != nil { - return fmt.Errorf("getting CREATE TABLE statement: %w", err) + return fmt.Errorf("getting CREATE TABLE statement for %s.%s: %w", sourceDB, sourceTable, err) } // Modify the statement: - // 1. Replace database name in the CREATE TABLE line + // 1. Replace database and table name in the CREATE TABLE line // 2. Replace ZooKeeper paths in ReplicatedMergeTree to include target database - modifiedStmt := m.modifyCreateTableForClone(createStmt, sourceDB, targetDB, tableName, clusterName) + // 3. Rename table references when sourceTable != targetTable + modifiedStmt := m.modifyCreateTableForClone(createStmt, sourceDB, targetDB, sourceTable, targetTable, clusterName) execCtx, execCancel := context.WithTimeout(ctx, m.config.QueryTimeout) defer execCancel() if _, err := conn.ExecContext(execCtx, modifiedStmt); err != nil { - return fmt.Errorf("executing modified CREATE TABLE: %w", err) + return fmt.Errorf("executing modified CREATE TABLE for %s: %w", targetTable, err) } return nil } // modifyCreateTableForClone modifies a CREATE TABLE/VIEW statement for cloning to a new database. -// It updates the table name and modifies ReplicatedMergeTree ZooKeeper paths. +// It updates the database/table name and modifies ReplicatedMergeTree ZooKeeper paths. +// When sourceTable != targetTable (cross-database models), it also renames table references. func (m *DatabaseManager) modifyCreateTableForClone( - createStmt, sourceDB, targetDB, tableName, clusterName string, + createStmt, sourceDB, targetDB, sourceTable, targetTable, clusterName string, ) string { result := createStmt @@ -647,33 +670,33 @@ func (m *DatabaseManager) modifyCreateTableForClone( // Materialized Views: CREATE MATERIALIZED VIEW default.mv_name // Replace TABLE references - oldTableRef := fmt.Sprintf("CREATE TABLE %s.%s", sourceDB, tableName) + oldTableRef := fmt.Sprintf("CREATE TABLE %s.%s", sourceDB, sourceTable) newTableRef := fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%s`.`%s` ON CLUSTER %s", - targetDB, tableName, clusterName) + targetDB, targetTable, clusterName) result = strings.Replace(result, oldTableRef, newTableRef, 1) // Also handle backtick-quoted version for TABLE - oldTableRefQuoted := fmt.Sprintf("CREATE TABLE `%s`.`%s`", sourceDB, tableName) + oldTableRefQuoted := fmt.Sprintf("CREATE TABLE `%s`.`%s`", sourceDB, sourceTable) result = strings.Replace(result, oldTableRefQuoted, newTableRef, 1) // Replace MATERIALIZED VIEW references - oldMVRef := fmt.Sprintf("CREATE MATERIALIZED VIEW %s.%s", sourceDB, tableName) + oldMVRef := fmt.Sprintf("CREATE MATERIALIZED VIEW %s.%s", sourceDB, sourceTable) newMVRef := fmt.Sprintf("CREATE MATERIALIZED VIEW IF NOT EXISTS `%s`.`%s` ON CLUSTER %s", - targetDB, tableName, clusterName) + targetDB, targetTable, clusterName) result = strings.Replace(result, oldMVRef, newMVRef, 1) // Backtick-quoted MATERIALIZED VIEW - oldMVRefQuoted := fmt.Sprintf("CREATE MATERIALIZED VIEW `%s`.`%s`", sourceDB, tableName) + oldMVRefQuoted := fmt.Sprintf("CREATE MATERIALIZED VIEW `%s`.`%s`", sourceDB, sourceTable) result = strings.Replace(result, oldMVRefQuoted, newMVRef, 1) // Replace VIEW references (non-materialized) - oldViewRef := fmt.Sprintf("CREATE VIEW %s.%s", sourceDB, tableName) + oldViewRef := fmt.Sprintf("CREATE VIEW %s.%s", sourceDB, sourceTable) newViewRef := fmt.Sprintf("CREATE VIEW IF NOT EXISTS `%s`.`%s` ON CLUSTER %s", - targetDB, tableName, clusterName) + targetDB, targetTable, clusterName) result = strings.Replace(result, oldViewRef, newViewRef, 1) // Backtick-quoted VIEW - oldViewRefQuoted := fmt.Sprintf("CREATE VIEW `%s`.`%s`", sourceDB, tableName) + oldViewRefQuoted := fmt.Sprintf("CREATE VIEW `%s`.`%s`", sourceDB, sourceTable) result = strings.Replace(result, oldViewRefQuoted, newViewRef, 1) // For Materialized Views with TO clause (e.g., CREATE MATERIALIZED VIEW ... TO default.target_table) @@ -712,6 +735,28 @@ func (m *DatabaseManager) modifyCreateTableForClone( newDistRef := fmt.Sprintf("'%s'", targetDB) result = strings.ReplaceAll(result, oldDistRef, newDistRef) + // For cross-database models where source table name differs from target table name, + // rename the Distributed engine's local table reference. + // Example: Distributed('{cluster}', 'ext_123', 'cpu_utilization_local', ...) needs to become + // Distributed('{cluster}', 'ext_123', 'observoor_cpu_utilization_local', ...) + // Only target quoted references in the Distributed engine to avoid unintended global replacements. + if sourceTable != targetTable { + // Quoted reference (most common): 'cpu_utilization_local' → 'observoor_cpu_utilization_local' + oldQuotedLocal := fmt.Sprintf("'%s_local'", sourceTable) + newQuotedLocal := fmt.Sprintf("'%s_local'", targetTable) + result = strings.ReplaceAll(result, oldQuotedLocal, newQuotedLocal) + + // Unquoted reference: cpu_utilization_local, → observoor_cpu_utilization_local, + oldUnquotedLocal := fmt.Sprintf(", %s_local,", sourceTable) + newUnquotedLocal := fmt.Sprintf(", %s_local,", targetTable) + result = strings.ReplaceAll(result, oldUnquotedLocal, newUnquotedLocal) + + // Quoted base table ref: 'cpu_utilization' → 'observoor_cpu_utilization' + oldQuotedBase := fmt.Sprintf("'%s'", sourceTable) + newQuotedBase := fmt.Sprintf("'%s'", targetTable) + result = strings.ReplaceAll(result, oldQuotedBase, newQuotedBase) + } + return result } @@ -780,7 +825,7 @@ func (m *DatabaseManager) CloneCBTDatabase(ctx context.Context, testID string, t defer func() { <-cloneSem }() if cloneErr := m.cloneTableWithUniqueReplicaPath(ctx, m.cbtConn, - config.CBTTemplateDatabase, cbtDBName, t.name, config.CBTClusterName); cloneErr != nil { + config.CBTTemplateDatabase, cbtDBName, t.name, t.name, config.CBTClusterName); cloneErr != nil { cloneErrs <- fmt.Errorf("cloning table %s: %w", t.name, cloneErr) } }(table) diff --git a/internal/testing/models.go b/internal/testing/models.go index 824520ac..666b568e 100644 --- a/internal/testing/models.go +++ b/internal/testing/models.go @@ -37,14 +37,26 @@ type ModelMetadata struct { Name string // Table name (inferred from filename or frontmatter) ExecutionType string // incremental, scheduled, or empty for external models Dependencies []string // List of table dependencies + SourceDB string // Source database for cross-database external models (empty = default) + SourceTable string // Actual table name in source database (empty = same as Name) +} + +// ExternalTableRef describes the source location of an external table in ClickHouse. +// For standard external models, SourceDB and SourceTable are empty (default database, model name as table). +// For cross-database models (e.g., observoor.cpu_utilization), these fields specify the actual source location. +type ExternalTableRef struct { + ModelName string // Model identifier used in the test database + SourceDB string // Source database ("" = default) + SourceTable string // Actual source table name ("" = same as ModelName) } // Dependencies contains resolved dependency information for test execution. type Dependencies struct { - TargetModel *ModelMetadata // The model being tested - TransformationModels []*ModelMetadata // Transformations in execution order (topologically sorted) - ExternalTables []string // Leaf external table names required - ParquetURLs map[string]string // External table name → parquet URL (from testConfig) + TargetModel *ModelMetadata // The model being tested + TransformationModels []*ModelMetadata // Transformations in execution order (topologically sorted) + ExternalTables []string // Leaf external table names required (model identifiers) + ExternalTableRefs []ExternalTableRef // Source references for external tables (includes cross-database info) + ParquetURLs map[string]string // External table name → parquet URL (from testConfig) } // ModelCache caches parsed model metadata and handles dependency resolution. @@ -58,6 +70,7 @@ type ModelCache struct { // Frontmatter represents YAML frontmatter in SQL files. type Frontmatter struct { + Database string `yaml:"database"` // Source database for cross-database external models Table string `yaml:"table"` Type string `yaml:"type"` // incremental or scheduled Dependencies []interface{} `yaml:"dependencies"` // Can be []string or [][]string (OR dependencies) @@ -144,7 +157,12 @@ func (c *ModelCache) ResolveTestDependencies(testConfig *testdef.TestDefinition) TargetModel: externalModel, TransformationModels: []*ModelMetadata{}, ExternalTables: []string{externalModel.Name}, - ParquetURLs: make(map[string]string), + ExternalTableRefs: []ExternalTableRef{{ + ModelName: externalModel.Name, + SourceDB: externalModel.SourceDB, + SourceTable: externalModel.SourceTable, + }}, + ParquetURLs: make(map[string]string), } // Build parquet URL map @@ -193,10 +211,23 @@ func (c *ModelCache) ResolveTestDependencies(testConfig *testdef.TestDefinition) return nil, fmt.Errorf("topological sort: %w", err) } + // Build ExternalTableRefs with cross-database source info + extRefs := make([]ExternalTableRef, 0, len(externalTables)) + for _, tableName := range externalTables { + ref := ExternalTableRef{ModelName: tableName} + if ext, ok := c.externalModels[tableName]; ok { + ref.SourceDB = ext.SourceDB + ref.SourceTable = ext.SourceTable + } + + extRefs = append(extRefs, ref) + } + deps := &Dependencies{ TargetModel: targetModel, TransformationModels: sortedTransformations, ExternalTables: externalTables, + ExternalTableRefs: extRefs, ParquetURLs: parquetURLs, } @@ -226,6 +257,14 @@ func (c *ModelCache) IsExternalModel(name string) bool { return exists } +// GetExternalModel returns the metadata for an external model, or nil if not found. +func (c *ModelCache) GetExternalModel(name string) *ModelMetadata { + c.mu.RLock() + defer c.mu.RUnlock() + + return c.externalModels[name] +} + // IsTransformationModel checks if a model exists in the transformations. func (c *ModelCache) IsTransformationModel(name string) bool { c.mu.RLock() @@ -326,44 +365,40 @@ func (c *ModelCache) parseModel(path string, _ ModelType) (*ModelMetadata, error } } - // Determine table name - tableName := frontmatter.Table - if tableName == "" { - // Infer from filename - filename := filepath.Base(path) - tableName = strings.TrimSuffix(filename, filepath.Ext(filename)) - } + // Derive model name from filename (always available, always consistent). + filename := filepath.Base(path) + modelName := strings.TrimSuffix(filename, filepath.Ext(filename)) - // Normalize dependencies - handle both simple strings and OR dependencies (nested lists) - dependencies := make([]string, 0) - for _, dep := range frontmatter.Dependencies { - switch v := dep.(type) { - case string: - // Simple dependency: "{{external}}.table_name" - normalized := c.normalizeDependency(v) - dependencies = append(dependencies, normalized) - case []interface{}: - // OR dependency: ["{{external}}.table1", "{{external}}.table2"] - // Flatten - include all options since CBT needs to know about all of them - for _, orDep := range v { - if depStr, ok := orDep.(string); ok { - normalized := c.normalizeDependency(depStr) - dependencies = append(dependencies, normalized) - } - } - } + // For non-cross-database models, prefer frontmatter.Table as the model name if set. + // For cross-database models (database field set), the frontmatter.Table is the source table + // name (e.g., "cpu_utilization"), not the model identifier (e.g., "observoor_cpu_utilization"). + if frontmatter.Database == "" && frontmatter.Table != "" { + modelName = frontmatter.Table } + dependencies := c.normalizeDependencies(frontmatter.Dependencies) + // Normalize execution type (incremental, scheduled, or empty) executionType := strings.ToLower(strings.TrimSpace(frontmatter.Type)) if executionType != "incremental" && executionType != "scheduled" { executionType = "" // Default to empty for external models or unknown types } + // Capture cross-database source info for external models. + // When database is set in frontmatter (e.g., "observoor"), the actual source table + // lives in a different database (e.g., observoor.cpu_utilization) than the model name implies. + var sourceDB, sourceTable string + if frontmatter.Database != "" { + sourceDB = frontmatter.Database + sourceTable = frontmatter.Table + } + return &ModelMetadata{ - Name: tableName, + Name: modelName, ExecutionType: executionType, Dependencies: dependencies, + SourceDB: sourceDB, + SourceTable: sourceTable, }, nil } @@ -392,6 +427,28 @@ func (c *ModelCache) extractFrontmatter(content string) (*Frontmatter, string, e return &frontmatter, sql, nil } +// normalizeDependencies converts raw frontmatter dependencies to normalized table names. +// Handles both simple string dependencies and OR dependencies (nested lists). +func (c *ModelCache) normalizeDependencies(raw []interface{}) []string { + deps := make([]string, 0, len(raw)) + + for _, dep := range raw { + switch v := dep.(type) { + case string: + deps = append(deps, c.normalizeDependency(v)) + case []interface{}: + // OR dependency: flatten all options + for _, orDep := range v { + if depStr, ok := orDep.(string); ok { + deps = append(deps, c.normalizeDependency(depStr)) + } + } + } + } + + return deps +} + // normalizeDependency converts dependency references to table names // Handles: {{external}}.table_name → table_name // @@ -448,9 +505,9 @@ func (c *ModelCache) extractLeafExternalTables(transformations []*ModelMetadata) for _, model := range transformations { for _, dep := range model.Dependencies { - // Check if dependency is an external model - if _, isExternal := c.externalModels[dep]; isExternal { - externalSet[dep] = true + // Resolve dependency to canonical model name, handling cross-database references. + if canonicalName, isExternal := c.resolveExternalDependency(dep); isExternal { + externalSet[canonicalName] = true } } } @@ -473,10 +530,11 @@ func (c *ModelCache) extractLeafExternalTablesWithDependents(transformations []* for _, model := range transformations { for _, dep := range model.Dependencies { - // Check if dependency is an external model - if _, isExternal := c.externalModels[dep]; isExternal { - externalSet[dep] = true - dependents[dep] = append(dependents[dep], model.Name) + // Resolve dependency to canonical model name, handling cross-database references + // (e.g., "observoor.cpu_utilization" → "observoor_cpu_utilization"). + if canonicalName, isExternal := c.resolveExternalDependency(dep); isExternal { + externalSet[canonicalName] = true + dependents[canonicalName] = append(dependents[canonicalName], model.Name) } } } @@ -490,6 +548,30 @@ func (c *ModelCache) extractLeafExternalTablesWithDependents(transformations []* return externals, dependents } +// resolveExternalDependency resolves a dependency string to the canonical external model name. +// Supports both direct model name lookups (e.g., "beacon_api_eth_v1_events_block") +// and cross-database references (e.g., "observoor.cpu_utilization" → "observoor_cpu_utilization"). +// Caller must hold c.mu read lock. +func (c *ModelCache) resolveExternalDependency(dep string) (string, bool) { + // Direct lookup by model name. + if _, ok := c.externalModels[dep]; ok { + return dep, true + } + + // Cross-database lookup: "database.table" → find model with matching SourceDB and SourceTable. + if strings.Contains(dep, ".") { + parts := strings.SplitN(dep, ".", 2) + + for name, model := range c.externalModels { + if model.SourceDB == parts[0] && model.SourceTable == parts[1] { + return name, true + } + } + } + + return "", false +} + // warnMissingExternalData logs warnings for any external tables that are required // but not provided in the test config. This is non-fatal - the test will proceed // and assertions will catch any actual problems from missing data. diff --git a/internal/testing/orchestrator.go b/internal/testing/orchestrator.go index 2ea61334..1d480f66 100644 --- a/internal/testing/orchestrator.go +++ b/internal/testing/orchestrator.go @@ -447,30 +447,41 @@ func (o *Orchestrator) precloneAllDatabases( model := cfg.Model deps := testDBs[model].deps - // Merge external tables from model deps + test definition's ExternalData - extTableSet := make(map[string]bool) - for _, t := range deps.ExternalTables { - extTableSet[t] = true + // Merge external table refs from model deps + test definition's ExternalData. + // Build a map keyed by model name to deduplicate and enrich with cross-database info. + refMap := make(map[string]ExternalTableRef, len(deps.ExternalTableRefs)) + for _, ref := range deps.ExternalTableRefs { + refMap[ref.ModelName] = ref } + for tableName := range cfg.ExternalData { - extTableSet[tableName] = true + if _, exists := refMap[tableName]; !exists { + // Table from test config without model metadata — use defaults (standard database) + ref := ExternalTableRef{ModelName: tableName} + if ext := o.modelCache.GetExternalModel(tableName); ext != nil { + ref.SourceDB = ext.SourceDB + ref.SourceTable = ext.SourceTable + } + + refMap[tableName] = ref + } } - extTables := make([]string, 0, len(extTableSet)) - for t := range extTableSet { - extTables = append(extTables, t) + extRefs := make([]ExternalTableRef, 0, len(refMap)) + for _, ref := range refMap { + extRefs = append(extRefs, ref) } // Clone external DB with only needed tables wg.Add(1) - go func(m, id string, tables []string) { + go func(m, id string, refs []ExternalTableRef) { defer wg.Done() cloneSem <- struct{}{} defer func() { <-cloneSem }() - extDB, err := o.dbManager.CloneExternalDatabase(ctx, id, tables) + extDB, err := o.dbManager.CloneExternalDatabase(ctx, id, refs) if err != nil { errChan <- fmt.Errorf("cloning ext DB for %s: %w", m, err) @@ -480,7 +491,7 @@ func (o *Orchestrator) precloneAllDatabases( mu.Lock() testDBs[m].extDB = extDB mu.Unlock() - }(model, testID, extTables) + }(model, testID, extRefs) // Clone CBT DB with only needed tables (transformation model names) wg.Add(1) @@ -586,10 +597,24 @@ func (o *Orchestrator) executeTestWithDBs( result.ParquetURLs = deps.ParquetURLs result.Transformations = extractModelNames(deps.TransformationModels) - // Step 2: Fetch and load parquet data into pre-cloned external database - if loadErr := o.fetchAndLoadParquetData(ctx, extDB, deps.ParquetURLs); loadErr != nil { - result.Error = loadErr - return result + // Step 2: Fetch and load parquet data. + // Standard external models load into the per-test ext database. + // Cross-database external models (e.g., observoor.cpu_utilization) load into the + // source database so the CBT bounds scan and dependency helpers resolve correctly. + standardURLs, crossDBLoads := splitParquetBySourceDB(deps) + + if len(standardURLs) > 0 { + if loadErr := o.fetchAndLoadParquetData(ctx, extDB, standardURLs); loadErr != nil { + result.Error = loadErr + return result + } + } + + for sourceDB, sourceURLs := range crossDBLoads { + if loadErr := o.fetchAndLoadParquetData(ctx, sourceDB, sourceURLs); loadErr != nil { + result.Error = loadErr + return result + } } // Step 3: Run transformations (reads extDB, writes cbtDB) @@ -733,6 +758,37 @@ func (o *Orchestrator) recordTestMetrics(result *TestResult, testConfig *testdef }) } +// splitParquetBySourceDB separates parquet URLs into standard loads (keyed by model name) +// and cross-database loads (keyed by source database → source table name). +// Cross-database external models (where SourceDB is set) need data loaded into their +// source database so the CBT engine's bounds scan and dependency helpers resolve correctly. +func splitParquetBySourceDB(deps *Dependencies) (standard map[string]string, crossDB map[string]map[string]string) { + standard = make(map[string]string, len(deps.ParquetURLs)) + crossDB = make(map[string]map[string]string) + + // Build lookup from model name to ExternalTableRef for cross-database detection. + refMap := make(map[string]ExternalTableRef, len(deps.ExternalTableRefs)) + for _, ref := range deps.ExternalTableRefs { + refMap[ref.ModelName] = ref + } + + for tableName, url := range deps.ParquetURLs { + ref, exists := refMap[tableName] + if exists && ref.SourceDB != "" && ref.SourceTable != "" { + // Cross-database: load into source database with source table name. + if crossDB[ref.SourceDB] == nil { + crossDB[ref.SourceDB] = make(map[string]string, 1) + } + + crossDB[ref.SourceDB][ref.SourceTable] = url + } else { + standard[tableName] = url + } + } + + return standard, crossDB +} + // extractModelNames extracts model names from ModelMetadata structs. func extractModelNames(models []*ModelMetadata) []string { names := make([]string, 0, len(models)) diff --git a/migrations/070_fct_node_cpu_utilization_by_process.down.sql b/migrations/070_fct_node_cpu_utilization_by_process.down.sql new file mode 100644 index 00000000..888d169c --- /dev/null +++ b/migrations/070_fct_node_cpu_utilization_by_process.down.sql @@ -0,0 +1,2 @@ +DROP TABLE IF EXISTS `${NETWORK_NAME}`.fct_node_cpu_utilization_by_process ON CLUSTER '{cluster}'; +DROP TABLE IF EXISTS `${NETWORK_NAME}`.fct_node_cpu_utilization_by_process_local ON CLUSTER '{cluster}'; diff --git a/migrations/070_fct_node_cpu_utilization_by_process.up.sql b/migrations/070_fct_node_cpu_utilization_by_process.up.sql new file mode 100644 index 00000000..43a8f130 --- /dev/null +++ b/migrations/070_fct_node_cpu_utilization_by_process.up.sql @@ -0,0 +1,32 @@ +-- Transformation output table for node CPU utilization with node_class enrichment +CREATE TABLE `${NETWORK_NAME}`.fct_node_cpu_utilization_by_process_local ON CLUSTER '{cluster}' ( + `updated_date_time` DateTime COMMENT 'Timestamp when the record was last updated' CODEC(DoubleDelta, ZSTD(1)), + `window_start` DateTime64(3) COMMENT 'Start of the sub-slot aggregation window' CODEC(DoubleDelta, ZSTD(1)), + `wallclock_slot` UInt32 COMMENT 'The wallclock slot number' CODEC(DoubleDelta, ZSTD(1)), + `wallclock_slot_start_date_time` DateTime64(3) COMMENT 'The wall clock time when the slot started' CODEC(DoubleDelta, ZSTD(1)), + `meta_client_name` LowCardinality(String) COMMENT 'Name of the observoor client that collected the data', + `meta_network_name` LowCardinality(String) COMMENT 'Ethereum network name', + `pid` UInt32 COMMENT 'Process ID of the monitored client' CODEC(ZSTD(1)), + `client_type` LowCardinality(String) COMMENT 'Client type: CL or EL', + `system_cores` UInt16 COMMENT 'Total system CPU cores' CODEC(ZSTD(1)), + `mean_core_pct` Float32 COMMENT 'Mean CPU core utilization percentage (100pct = 1 core)' CODEC(ZSTD(1)), + `min_core_pct` Float32 COMMENT 'Minimum CPU core utilization percentage (100pct = 1 core)' CODEC(ZSTD(1)), + `max_core_pct` Float32 COMMENT 'Maximum CPU core utilization percentage (100pct = 1 core)' CODEC(ZSTD(1)), + `node_class` LowCardinality(String) COMMENT 'Node classification for filtering (e.g. eip7870)' +) ENGINE = ReplicatedReplacingMergeTree( + '/clickhouse/{installation}/{cluster}/tables/{shard}/{database}/{table}', + '{replica}', + `updated_date_time` +) PARTITION BY toStartOfMonth(wallclock_slot_start_date_time) +ORDER BY + (wallclock_slot_start_date_time, meta_client_name, client_type, pid, window_start) +SETTINGS + deduplicate_merge_projection_mode = 'rebuild' +COMMENT 'Node CPU utilization per sub-slot window enriched with node classification'; + +CREATE TABLE `${NETWORK_NAME}`.fct_node_cpu_utilization_by_process ON CLUSTER '{cluster}' AS `${NETWORK_NAME}`.fct_node_cpu_utilization_by_process_local ENGINE = Distributed( + '{cluster}', + '${NETWORK_NAME}', + fct_node_cpu_utilization_by_process_local, + cityHash64(wallclock_slot_start_date_time, meta_client_name) +); diff --git a/models/external/observoor_cpu_utilization.sql b/models/external/observoor_cpu_utilization.sql new file mode 100644 index 00000000..5242418e --- /dev/null +++ b/models/external/observoor_cpu_utilization.sql @@ -0,0 +1,32 @@ +--- +database: observoor +table: cpu_utilization +cache: + incremental_scan_interval: 5s + full_scan_interval: 24h +interval: + type: slot +lag: 12 +--- +SELECT + {{ if .cache.is_incremental_scan }} + '{{ .cache.previous_min }}' as min, + {{ else }} + toUnixTimestamp(min(wallclock_slot_start_date_time)) as min, + {{ end }} + toUnixTimestamp(max(wallclock_slot_start_date_time)) as max +FROM {{ .self.helpers.from }} +WHERE + meta_network_name = '{{ .env.NETWORK }}' + + -- previous_max if incremental scan and is set, otherwise default/env + {{- $ts := default "0" .env.EXTERNAL_MODEL_MIN_TIMESTAMP -}} + {{- if .cache.is_incremental_scan -}} + {{- if .cache.previous_max -}} + {{- $ts = .cache.previous_max -}} + {{- end -}} + {{- end }} + AND wallclock_slot_start_date_time >= fromUnixTimestamp({{ $ts }}) + {{- if .cache.is_incremental_scan }} + AND wallclock_slot_start_date_time <= fromUnixTimestamp({{ $ts }}) + {{ default "100000" .env.EXTERNAL_MODEL_SCAN_SIZE_TIMESTAMP }} + {{- end }} diff --git a/models/transformations/fct_node_cpu_utilization_by_process.sql b/models/transformations/fct_node_cpu_utilization_by_process.sql new file mode 100644 index 00000000..0c5666a5 --- /dev/null +++ b/models/transformations/fct_node_cpu_utilization_by_process.sql @@ -0,0 +1,37 @@ +--- +table: fct_node_cpu_utilization_by_process +type: incremental +interval: + type: slot + max: 50000 +schedules: + forwardfill: "@every 5s" + backfill: "@every 30s" +tags: + - slot + - observoor + - cpu +dependencies: + - "observoor.cpu_utilization" +--- +INSERT INTO + `{{ .self.database }}`.`{{ .self.table }}` +SELECT + fromUnixTimestamp({{ .task.start }}) as updated_date_time, + window_start, + wallclock_slot, + wallclock_slot_start_date_time, + meta_client_name, + meta_network_name, + pid, + client_type, + system_cores, + mean_core_pct, + min_core_pct, + max_core_pct, + CASE + WHEN positionCaseInsensitive(meta_client_name, '7870') > 0 THEN 'eip7870' + ELSE '' + END AS node_class +FROM {{ index .dep "observoor" "cpu_utilization" "helpers" "from" }} FINAL +WHERE wallclock_slot_start_date_time BETWEEN fromUnixTimestamp({{ .bounds.start }}) AND fromUnixTimestamp({{ .bounds.end }}) diff --git a/pkg/proto/clickhouse/fct_node_cpu_utilization_by_process.go b/pkg/proto/clickhouse/fct_node_cpu_utilization_by_process.go new file mode 100644 index 00000000..eaee5728 --- /dev/null +++ b/pkg/proto/clickhouse/fct_node_cpu_utilization_by_process.go @@ -0,0 +1,410 @@ +// Code generated by clickhouse-proto-gen. DO NOT EDIT. +// SQL query builder for fct_node_cpu_utilization_by_process + +package clickhouse + +import ( + "fmt" +) + +// BuildListFctNodeCpuUtilizationByProcessQuery constructs a parameterized SQL query from a ListFctNodeCpuUtilizationByProcessRequest +func BuildListFctNodeCpuUtilizationByProcessQuery(req *ListFctNodeCpuUtilizationByProcessRequest, options ...QueryOption) (SQLQuery, error) { + // Validate that at least one primary key is provided + // Primary keys can come from base table or projections + if req.WallclockSlotStartDateTime == nil { + return SQLQuery{}, fmt.Errorf("primary key field wallclock_slot_start_date_time is required") + } + + // Build query using QueryBuilder + qb := NewQueryBuilder() + + // Add primary key filter + switch filter := req.WallclockSlotStartDateTime.Filter.(type) { + case *Int64Filter_Eq: + qb.AddCondition("wallclock_slot_start_date_time", "=", DateTime64Value{uint64(filter.Eq)}) + case *Int64Filter_Ne: + qb.AddCondition("wallclock_slot_start_date_time", "!=", DateTime64Value{uint64(filter.Ne)}) + case *Int64Filter_Lt: + qb.AddCondition("wallclock_slot_start_date_time", "<", DateTime64Value{uint64(filter.Lt)}) + case *Int64Filter_Lte: + qb.AddCondition("wallclock_slot_start_date_time", "<=", DateTime64Value{uint64(filter.Lte)}) + case *Int64Filter_Gt: + qb.AddCondition("wallclock_slot_start_date_time", ">", DateTime64Value{uint64(filter.Gt)}) + case *Int64Filter_Gte: + qb.AddCondition("wallclock_slot_start_date_time", ">=", DateTime64Value{uint64(filter.Gte)}) + case *Int64Filter_Between: + qb.AddBetweenCondition("wallclock_slot_start_date_time", DateTime64Value{uint64(filter.Between.Min)}, DateTime64Value{uint64(filter.Between.Max.GetValue())}) + case *Int64Filter_In: + if len(filter.In.Values) > 0 { + converted := make([]interface{}, len(filter.In.Values)) + for i, v := range filter.In.Values { + converted[i] = DateTime64Value{uint64(v)} + } + qb.AddInCondition("wallclock_slot_start_date_time", converted) + } + case *Int64Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + converted := make([]interface{}, len(filter.NotIn.Values)) + for i, v := range filter.NotIn.Values { + converted[i] = DateTime64Value{uint64(v)} + } + qb.AddNotInCondition("wallclock_slot_start_date_time", converted) + } + default: + // Unsupported filter type + } + + // Add filter for column: updated_date_time + if req.UpdatedDateTime != nil { + switch filter := req.UpdatedDateTime.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("updated_date_time", "=", DateTimeValue{filter.Eq}) + case *UInt32Filter_Ne: + qb.AddCondition("updated_date_time", "!=", DateTimeValue{filter.Ne}) + case *UInt32Filter_Lt: + qb.AddCondition("updated_date_time", "<", DateTimeValue{filter.Lt}) + case *UInt32Filter_Lte: + qb.AddCondition("updated_date_time", "<=", DateTimeValue{filter.Lte}) + case *UInt32Filter_Gt: + qb.AddCondition("updated_date_time", ">", DateTimeValue{filter.Gt}) + case *UInt32Filter_Gte: + qb.AddCondition("updated_date_time", ">=", DateTimeValue{filter.Gte}) + case *UInt32Filter_Between: + qb.AddBetweenCondition("updated_date_time", DateTimeValue{filter.Between.Min}, DateTimeValue{filter.Between.Max.GetValue()}) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + converted := make([]interface{}, len(filter.In.Values)) + for i, v := range filter.In.Values { + converted[i] = DateTimeValue{v} + } + qb.AddInCondition("updated_date_time", converted) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + converted := make([]interface{}, len(filter.NotIn.Values)) + for i, v := range filter.NotIn.Values { + converted[i] = DateTimeValue{v} + } + qb.AddNotInCondition("updated_date_time", converted) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: window_start + if req.WindowStart != nil { + switch filter := req.WindowStart.Filter.(type) { + case *Int64Filter_Eq: + qb.AddCondition("window_start", "=", DateTime64Value{uint64(filter.Eq)}) + case *Int64Filter_Ne: + qb.AddCondition("window_start", "!=", DateTime64Value{uint64(filter.Ne)}) + case *Int64Filter_Lt: + qb.AddCondition("window_start", "<", DateTime64Value{uint64(filter.Lt)}) + case *Int64Filter_Lte: + qb.AddCondition("window_start", "<=", DateTime64Value{uint64(filter.Lte)}) + case *Int64Filter_Gt: + qb.AddCondition("window_start", ">", DateTime64Value{uint64(filter.Gt)}) + case *Int64Filter_Gte: + qb.AddCondition("window_start", ">=", DateTime64Value{uint64(filter.Gte)}) + case *Int64Filter_Between: + qb.AddBetweenCondition("window_start", DateTime64Value{uint64(filter.Between.Min)}, DateTime64Value{uint64(filter.Between.Max.GetValue())}) + case *Int64Filter_In: + if len(filter.In.Values) > 0 { + converted := make([]interface{}, len(filter.In.Values)) + for i, v := range filter.In.Values { + converted[i] = DateTime64Value{uint64(v)} + } + qb.AddInCondition("window_start", converted) + } + case *Int64Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + converted := make([]interface{}, len(filter.NotIn.Values)) + for i, v := range filter.NotIn.Values { + converted[i] = DateTime64Value{uint64(v)} + } + qb.AddNotInCondition("window_start", converted) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: wallclock_slot + if req.WallclockSlot != nil { + switch filter := req.WallclockSlot.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("wallclock_slot", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("wallclock_slot", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("wallclock_slot", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("wallclock_slot", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("wallclock_slot", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("wallclock_slot", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("wallclock_slot", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("wallclock_slot", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("wallclock_slot", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: meta_client_name + if req.MetaClientName != nil { + switch filter := req.MetaClientName.Filter.(type) { + case *StringFilter_Eq: + qb.AddCondition("meta_client_name", "=", filter.Eq) + case *StringFilter_Ne: + qb.AddCondition("meta_client_name", "!=", filter.Ne) + case *StringFilter_Contains: + qb.AddLikeCondition("meta_client_name", "%" + filter.Contains + "%") + case *StringFilter_StartsWith: + qb.AddLikeCondition("meta_client_name", filter.StartsWith + "%") + case *StringFilter_EndsWith: + qb.AddLikeCondition("meta_client_name", "%" + filter.EndsWith) + case *StringFilter_Like: + qb.AddLikeCondition("meta_client_name", filter.Like) + case *StringFilter_NotLike: + qb.AddNotLikeCondition("meta_client_name", filter.NotLike) + case *StringFilter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("meta_client_name", StringSliceToInterface(filter.In.Values)) + } + case *StringFilter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("meta_client_name", StringSliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: meta_network_name + if req.MetaNetworkName != nil { + switch filter := req.MetaNetworkName.Filter.(type) { + case *StringFilter_Eq: + qb.AddCondition("meta_network_name", "=", filter.Eq) + case *StringFilter_Ne: + qb.AddCondition("meta_network_name", "!=", filter.Ne) + case *StringFilter_Contains: + qb.AddLikeCondition("meta_network_name", "%" + filter.Contains + "%") + case *StringFilter_StartsWith: + qb.AddLikeCondition("meta_network_name", filter.StartsWith + "%") + case *StringFilter_EndsWith: + qb.AddLikeCondition("meta_network_name", "%" + filter.EndsWith) + case *StringFilter_Like: + qb.AddLikeCondition("meta_network_name", filter.Like) + case *StringFilter_NotLike: + qb.AddNotLikeCondition("meta_network_name", filter.NotLike) + case *StringFilter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("meta_network_name", StringSliceToInterface(filter.In.Values)) + } + case *StringFilter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("meta_network_name", StringSliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: pid + if req.Pid != nil { + switch filter := req.Pid.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("pid", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("pid", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("pid", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("pid", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("pid", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("pid", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("pid", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("pid", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("pid", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: client_type + if req.ClientType != nil { + switch filter := req.ClientType.Filter.(type) { + case *StringFilter_Eq: + qb.AddCondition("client_type", "=", filter.Eq) + case *StringFilter_Ne: + qb.AddCondition("client_type", "!=", filter.Ne) + case *StringFilter_Contains: + qb.AddLikeCondition("client_type", "%" + filter.Contains + "%") + case *StringFilter_StartsWith: + qb.AddLikeCondition("client_type", filter.StartsWith + "%") + case *StringFilter_EndsWith: + qb.AddLikeCondition("client_type", "%" + filter.EndsWith) + case *StringFilter_Like: + qb.AddLikeCondition("client_type", filter.Like) + case *StringFilter_NotLike: + qb.AddNotLikeCondition("client_type", filter.NotLike) + case *StringFilter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("client_type", StringSliceToInterface(filter.In.Values)) + } + case *StringFilter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("client_type", StringSliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: system_cores + if req.SystemCores != nil { + switch filter := req.SystemCores.Filter.(type) { + case *UInt32Filter_Eq: + qb.AddCondition("system_cores", "=", filter.Eq) + case *UInt32Filter_Ne: + qb.AddCondition("system_cores", "!=", filter.Ne) + case *UInt32Filter_Lt: + qb.AddCondition("system_cores", "<", filter.Lt) + case *UInt32Filter_Lte: + qb.AddCondition("system_cores", "<=", filter.Lte) + case *UInt32Filter_Gt: + qb.AddCondition("system_cores", ">", filter.Gt) + case *UInt32Filter_Gte: + qb.AddCondition("system_cores", ">=", filter.Gte) + case *UInt32Filter_Between: + qb.AddBetweenCondition("system_cores", filter.Between.Min, filter.Between.Max.GetValue()) + case *UInt32Filter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("system_cores", UInt32SliceToInterface(filter.In.Values)) + } + case *UInt32Filter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("system_cores", UInt32SliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Add filter for column: mean_core_pct + + // Add filter for column: min_core_pct + + // Add filter for column: max_core_pct + + // Add filter for column: node_class + if req.NodeClass != nil { + switch filter := req.NodeClass.Filter.(type) { + case *StringFilter_Eq: + qb.AddCondition("node_class", "=", filter.Eq) + case *StringFilter_Ne: + qb.AddCondition("node_class", "!=", filter.Ne) + case *StringFilter_Contains: + qb.AddLikeCondition("node_class", "%" + filter.Contains + "%") + case *StringFilter_StartsWith: + qb.AddLikeCondition("node_class", filter.StartsWith + "%") + case *StringFilter_EndsWith: + qb.AddLikeCondition("node_class", "%" + filter.EndsWith) + case *StringFilter_Like: + qb.AddLikeCondition("node_class", filter.Like) + case *StringFilter_NotLike: + qb.AddNotLikeCondition("node_class", filter.NotLike) + case *StringFilter_In: + if len(filter.In.Values) > 0 { + qb.AddInCondition("node_class", StringSliceToInterface(filter.In.Values)) + } + case *StringFilter_NotIn: + if len(filter.NotIn.Values) > 0 { + qb.AddNotInCondition("node_class", StringSliceToInterface(filter.NotIn.Values)) + } + default: + // Unsupported filter type + } + } + + // Handle pagination per AIP-132 + // Validate page size + if req.PageSize < 0 { + return SQLQuery{}, fmt.Errorf("page_size must be non-negative, got %d", req.PageSize) + } + if req.PageSize > 10000 { + return SQLQuery{}, fmt.Errorf("page_size must not exceed %d, got %d", 10000, req.PageSize) + } + + var limit, offset uint32 + limit = 100 // Default page size + if req.PageSize > 0 { + limit = uint32(req.PageSize) + } + if req.PageToken != "" { + decodedOffset, err := DecodePageToken(req.PageToken) + if err != nil { + return SQLQuery{}, fmt.Errorf("invalid page_token: %w", err) + } + offset = decodedOffset + } + + // Handle custom ordering if provided + var orderByClause string + if req.OrderBy != "" { + validFields := []string{"updated_date_time", "window_start", "wallclock_slot", "wallclock_slot_start_date_time", "meta_client_name", "meta_network_name", "pid", "client_type", "system_cores", "mean_core_pct", "min_core_pct", "max_core_pct", "node_class"} + orderFields, err := ParseOrderBy(req.OrderBy, validFields) + if err != nil { + return SQLQuery{}, fmt.Errorf("invalid order_by: %w", err) + } + orderByClause = BuildOrderByClause(orderFields) + } else { + // Default sorting by primary key + orderByClause = " ORDER BY wallclock_slot_start_date_time" + ", meta_client_name" + ", client_type" + ", pid" + ", window_start" + } + + // Build column list + columns := []string{"toUnixTimestamp(`updated_date_time`) AS `updated_date_time`", "toUnixTimestamp64Micro(`window_start`) AS `window_start`", "wallclock_slot", "toUnixTimestamp64Micro(`wallclock_slot_start_date_time`) AS `wallclock_slot_start_date_time`", "meta_client_name", "meta_network_name", "pid", "client_type", "toUInt32(`system_cores`) AS `system_cores`", "mean_core_pct", "min_core_pct", "max_core_pct", "node_class"} + + return BuildParameterizedQuery("fct_node_cpu_utilization_by_process", columns, qb, orderByClause, limit, offset, options...) +} + +// BuildGetFctNodeCpuUtilizationByProcessQuery constructs a parameterized SQL query from a GetFctNodeCpuUtilizationByProcessRequest +func BuildGetFctNodeCpuUtilizationByProcessQuery(req *GetFctNodeCpuUtilizationByProcessRequest, options ...QueryOption) (SQLQuery, error) { + // Validate primary key is provided + if req.WallclockSlotStartDateTime == 0 { + return SQLQuery{}, fmt.Errorf("primary key field wallclock_slot_start_date_time is required") + } + + // Build query with primary key condition + qb := NewQueryBuilder() + qb.AddCondition("wallclock_slot_start_date_time", "=", req.WallclockSlotStartDateTime) + + // Build ORDER BY clause + orderByClause := " ORDER BY wallclock_slot_start_date_time, meta_client_name, client_type, pid, window_start" + + // Build column list + columns := []string{"toUnixTimestamp(`updated_date_time`) AS `updated_date_time`", "toUnixTimestamp64Micro(`window_start`) AS `window_start`", "wallclock_slot", "toUnixTimestamp64Micro(`wallclock_slot_start_date_time`) AS `wallclock_slot_start_date_time`", "meta_client_name", "meta_network_name", "pid", "client_type", "toUInt32(`system_cores`) AS `system_cores`", "mean_core_pct", "min_core_pct", "max_core_pct", "node_class"} + + // Return single record + return BuildParameterizedQuery("fct_node_cpu_utilization_by_process", columns, qb, orderByClause, 1, 0, options...) +} diff --git a/pkg/proto/clickhouse/fct_node_cpu_utilization_by_process.pb.go b/pkg/proto/clickhouse/fct_node_cpu_utilization_by_process.pb.go new file mode 100644 index 00000000..1a41cde2 --- /dev/null +++ b/pkg/proto/clickhouse/fct_node_cpu_utilization_by_process.pb.go @@ -0,0 +1,831 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc (unknown) +// source: fct_node_cpu_utilization_by_process.proto + +package clickhouse + +import ( + _ "github.com/ethpandaops/xatu-cbt/pkg/proto/clickhouse/clickhouse" + _ "google.golang.org/genproto/googleapis/api/annotations" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type FctNodeCpuUtilizationByProcess struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Timestamp when the record was last updated + UpdatedDateTime uint32 `protobuf:"varint,11,opt,name=updated_date_time,json=updatedDateTime,proto3" json:"updated_date_time,omitempty"` + // Start of the sub-slot aggregation window + WindowStart int64 `protobuf:"varint,12,opt,name=window_start,json=windowStart,proto3" json:"window_start,omitempty"` + // The wallclock slot number + WallclockSlot uint32 `protobuf:"varint,13,opt,name=wallclock_slot,json=wallclockSlot,proto3" json:"wallclock_slot,omitempty"` + // The wall clock time when the slot started + WallclockSlotStartDateTime int64 `protobuf:"varint,14,opt,name=wallclock_slot_start_date_time,json=wallclockSlotStartDateTime,proto3" json:"wallclock_slot_start_date_time,omitempty"` + // Name of the observoor client that collected the data + MetaClientName string `protobuf:"bytes,15,opt,name=meta_client_name,json=metaClientName,proto3" json:"meta_client_name,omitempty"` + // Ethereum network name + MetaNetworkName string `protobuf:"bytes,16,opt,name=meta_network_name,json=metaNetworkName,proto3" json:"meta_network_name,omitempty"` + // Process ID of the monitored client + Pid uint32 `protobuf:"varint,17,opt,name=pid,proto3" json:"pid,omitempty"` + // Client type: CL or EL + ClientType string `protobuf:"bytes,18,opt,name=client_type,json=clientType,proto3" json:"client_type,omitempty"` + // Total system CPU cores + SystemCores uint32 `protobuf:"varint,19,opt,name=system_cores,json=systemCores,proto3" json:"system_cores,omitempty"` + // Mean CPU core utilization percentage (100pct = 1 core) + MeanCorePct float32 `protobuf:"fixed32,20,opt,name=mean_core_pct,json=meanCorePct,proto3" json:"mean_core_pct,omitempty"` + // Minimum CPU core utilization percentage (100pct = 1 core) + MinCorePct float32 `protobuf:"fixed32,21,opt,name=min_core_pct,json=minCorePct,proto3" json:"min_core_pct,omitempty"` + // Maximum CPU core utilization percentage (100pct = 1 core) + MaxCorePct float32 `protobuf:"fixed32,22,opt,name=max_core_pct,json=maxCorePct,proto3" json:"max_core_pct,omitempty"` + // Node classification for filtering (e.g. eip7870) + NodeClass string `protobuf:"bytes,23,opt,name=node_class,json=nodeClass,proto3" json:"node_class,omitempty"` +} + +func (x *FctNodeCpuUtilizationByProcess) Reset() { + *x = FctNodeCpuUtilizationByProcess{} + if protoimpl.UnsafeEnabled { + mi := &file_fct_node_cpu_utilization_by_process_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *FctNodeCpuUtilizationByProcess) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FctNodeCpuUtilizationByProcess) ProtoMessage() {} + +func (x *FctNodeCpuUtilizationByProcess) ProtoReflect() protoreflect.Message { + mi := &file_fct_node_cpu_utilization_by_process_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FctNodeCpuUtilizationByProcess.ProtoReflect.Descriptor instead. +func (*FctNodeCpuUtilizationByProcess) Descriptor() ([]byte, []int) { + return file_fct_node_cpu_utilization_by_process_proto_rawDescGZIP(), []int{0} +} + +func (x *FctNodeCpuUtilizationByProcess) GetUpdatedDateTime() uint32 { + if x != nil { + return x.UpdatedDateTime + } + return 0 +} + +func (x *FctNodeCpuUtilizationByProcess) GetWindowStart() int64 { + if x != nil { + return x.WindowStart + } + return 0 +} + +func (x *FctNodeCpuUtilizationByProcess) GetWallclockSlot() uint32 { + if x != nil { + return x.WallclockSlot + } + return 0 +} + +func (x *FctNodeCpuUtilizationByProcess) GetWallclockSlotStartDateTime() int64 { + if x != nil { + return x.WallclockSlotStartDateTime + } + return 0 +} + +func (x *FctNodeCpuUtilizationByProcess) GetMetaClientName() string { + if x != nil { + return x.MetaClientName + } + return "" +} + +func (x *FctNodeCpuUtilizationByProcess) GetMetaNetworkName() string { + if x != nil { + return x.MetaNetworkName + } + return "" +} + +func (x *FctNodeCpuUtilizationByProcess) GetPid() uint32 { + if x != nil { + return x.Pid + } + return 0 +} + +func (x *FctNodeCpuUtilizationByProcess) GetClientType() string { + if x != nil { + return x.ClientType + } + return "" +} + +func (x *FctNodeCpuUtilizationByProcess) GetSystemCores() uint32 { + if x != nil { + return x.SystemCores + } + return 0 +} + +func (x *FctNodeCpuUtilizationByProcess) GetMeanCorePct() float32 { + if x != nil { + return x.MeanCorePct + } + return 0 +} + +func (x *FctNodeCpuUtilizationByProcess) GetMinCorePct() float32 { + if x != nil { + return x.MinCorePct + } + return 0 +} + +func (x *FctNodeCpuUtilizationByProcess) GetMaxCorePct() float32 { + if x != nil { + return x.MaxCorePct + } + return 0 +} + +func (x *FctNodeCpuUtilizationByProcess) GetNodeClass() string { + if x != nil { + return x.NodeClass + } + return "" +} + +// Request for listing fct_node_cpu_utilization_by_process records +type ListFctNodeCpuUtilizationByProcessRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Filter by wallclock_slot_start_date_time - The wall clock time when the slot started (PRIMARY KEY - required) + WallclockSlotStartDateTime *Int64Filter `protobuf:"bytes,1,opt,name=wallclock_slot_start_date_time,json=wallclockSlotStartDateTime,proto3" json:"wallclock_slot_start_date_time,omitempty"` + // Filter by meta_client_name - Name of the observoor client that collected the data (ORDER BY column 2 - optional) + MetaClientName *StringFilter `protobuf:"bytes,2,opt,name=meta_client_name,json=metaClientName,proto3" json:"meta_client_name,omitempty"` + // Filter by client_type - Client type: CL or EL (ORDER BY column 3 - optional) + ClientType *StringFilter `protobuf:"bytes,3,opt,name=client_type,json=clientType,proto3" json:"client_type,omitempty"` + // Filter by pid - Process ID of the monitored client (ORDER BY column 4 - optional) + Pid *UInt32Filter `protobuf:"bytes,4,opt,name=pid,proto3" json:"pid,omitempty"` + // Filter by window_start - Start of the sub-slot aggregation window (ORDER BY column 5 - optional) + WindowStart *Int64Filter `protobuf:"bytes,5,opt,name=window_start,json=windowStart,proto3" json:"window_start,omitempty"` + // Filter by updated_date_time - Timestamp when the record was last updated (optional) + UpdatedDateTime *UInt32Filter `protobuf:"bytes,6,opt,name=updated_date_time,json=updatedDateTime,proto3" json:"updated_date_time,omitempty"` + // Filter by wallclock_slot - The wallclock slot number (optional) + WallclockSlot *UInt32Filter `protobuf:"bytes,7,opt,name=wallclock_slot,json=wallclockSlot,proto3" json:"wallclock_slot,omitempty"` + // Filter by meta_network_name - Ethereum network name (optional) + MetaNetworkName *StringFilter `protobuf:"bytes,8,opt,name=meta_network_name,json=metaNetworkName,proto3" json:"meta_network_name,omitempty"` + // Filter by system_cores - Total system CPU cores (optional) + SystemCores *UInt32Filter `protobuf:"bytes,9,opt,name=system_cores,json=systemCores,proto3" json:"system_cores,omitempty"` + // Filter by mean_core_pct - Mean CPU core utilization percentage (100pct = 1 core) (optional) + MeanCorePct *wrapperspb.FloatValue `protobuf:"bytes,10,opt,name=mean_core_pct,json=meanCorePct,proto3" json:"mean_core_pct,omitempty"` + // Filter by min_core_pct - Minimum CPU core utilization percentage (100pct = 1 core) (optional) + MinCorePct *wrapperspb.FloatValue `protobuf:"bytes,11,opt,name=min_core_pct,json=minCorePct,proto3" json:"min_core_pct,omitempty"` + // Filter by max_core_pct - Maximum CPU core utilization percentage (100pct = 1 core) (optional) + MaxCorePct *wrapperspb.FloatValue `protobuf:"bytes,12,opt,name=max_core_pct,json=maxCorePct,proto3" json:"max_core_pct,omitempty"` + // Filter by node_class - Node classification for filtering (e.g. eip7870) (optional) + NodeClass *StringFilter `protobuf:"bytes,13,opt,name=node_class,json=nodeClass,proto3" json:"node_class,omitempty"` + // The maximum number of fct_node_cpu_utilization_by_process to return. + // If unspecified, at most 100 items will be returned. + // The maximum value is 10000; values above 10000 will be coerced to 10000. + PageSize int32 `protobuf:"varint,14,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + // A page token, received from a previous `ListFctNodeCpuUtilizationByProcess` call. + // Provide this to retrieve the subsequent page. + PageToken string `protobuf:"bytes,15,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` + // The order of results. Format: comma-separated list of fields. + // Example: "foo,bar" or "foo desc,bar" for descending order on foo. + // If unspecified, results will be returned in the default order. + OrderBy string `protobuf:"bytes,16,opt,name=order_by,json=orderBy,proto3" json:"order_by,omitempty"` +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) Reset() { + *x = ListFctNodeCpuUtilizationByProcessRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_fct_node_cpu_utilization_by_process_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListFctNodeCpuUtilizationByProcessRequest) ProtoMessage() {} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) ProtoReflect() protoreflect.Message { + mi := &file_fct_node_cpu_utilization_by_process_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListFctNodeCpuUtilizationByProcessRequest.ProtoReflect.Descriptor instead. +func (*ListFctNodeCpuUtilizationByProcessRequest) Descriptor() ([]byte, []int) { + return file_fct_node_cpu_utilization_by_process_proto_rawDescGZIP(), []int{1} +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetWallclockSlotStartDateTime() *Int64Filter { + if x != nil { + return x.WallclockSlotStartDateTime + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetMetaClientName() *StringFilter { + if x != nil { + return x.MetaClientName + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetClientType() *StringFilter { + if x != nil { + return x.ClientType + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetPid() *UInt32Filter { + if x != nil { + return x.Pid + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetWindowStart() *Int64Filter { + if x != nil { + return x.WindowStart + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetUpdatedDateTime() *UInt32Filter { + if x != nil { + return x.UpdatedDateTime + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetWallclockSlot() *UInt32Filter { + if x != nil { + return x.WallclockSlot + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetMetaNetworkName() *StringFilter { + if x != nil { + return x.MetaNetworkName + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetSystemCores() *UInt32Filter { + if x != nil { + return x.SystemCores + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetMeanCorePct() *wrapperspb.FloatValue { + if x != nil { + return x.MeanCorePct + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetMinCorePct() *wrapperspb.FloatValue { + if x != nil { + return x.MinCorePct + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetMaxCorePct() *wrapperspb.FloatValue { + if x != nil { + return x.MaxCorePct + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetNodeClass() *StringFilter { + if x != nil { + return x.NodeClass + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetPageSize() int32 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetPageToken() string { + if x != nil { + return x.PageToken + } + return "" +} + +func (x *ListFctNodeCpuUtilizationByProcessRequest) GetOrderBy() string { + if x != nil { + return x.OrderBy + } + return "" +} + +// Response for listing fct_node_cpu_utilization_by_process records +type ListFctNodeCpuUtilizationByProcessResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The list of fct_node_cpu_utilization_by_process. + FctNodeCpuUtilizationByProcess []*FctNodeCpuUtilizationByProcess `protobuf:"bytes,1,rep,name=fct_node_cpu_utilization_by_process,json=fctNodeCpuUtilizationByProcess,proto3" json:"fct_node_cpu_utilization_by_process,omitempty"` + // A token, which can be sent as `page_token` to retrieve the next page. + // If this field is omitted, there are no subsequent pages. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` +} + +func (x *ListFctNodeCpuUtilizationByProcessResponse) Reset() { + *x = ListFctNodeCpuUtilizationByProcessResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_fct_node_cpu_utilization_by_process_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListFctNodeCpuUtilizationByProcessResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListFctNodeCpuUtilizationByProcessResponse) ProtoMessage() {} + +func (x *ListFctNodeCpuUtilizationByProcessResponse) ProtoReflect() protoreflect.Message { + mi := &file_fct_node_cpu_utilization_by_process_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListFctNodeCpuUtilizationByProcessResponse.ProtoReflect.Descriptor instead. +func (*ListFctNodeCpuUtilizationByProcessResponse) Descriptor() ([]byte, []int) { + return file_fct_node_cpu_utilization_by_process_proto_rawDescGZIP(), []int{2} +} + +func (x *ListFctNodeCpuUtilizationByProcessResponse) GetFctNodeCpuUtilizationByProcess() []*FctNodeCpuUtilizationByProcess { + if x != nil { + return x.FctNodeCpuUtilizationByProcess + } + return nil +} + +func (x *ListFctNodeCpuUtilizationByProcessResponse) GetNextPageToken() string { + if x != nil { + return x.NextPageToken + } + return "" +} + +// Request for getting a single fct_node_cpu_utilization_by_process record by primary key +type GetFctNodeCpuUtilizationByProcessRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The wall clock time when the slot started + WallclockSlotStartDateTime int64 `protobuf:"varint,1,opt,name=wallclock_slot_start_date_time,json=wallclockSlotStartDateTime,proto3" json:"wallclock_slot_start_date_time,omitempty"` // Primary key (required) +} + +func (x *GetFctNodeCpuUtilizationByProcessRequest) Reset() { + *x = GetFctNodeCpuUtilizationByProcessRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_fct_node_cpu_utilization_by_process_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetFctNodeCpuUtilizationByProcessRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFctNodeCpuUtilizationByProcessRequest) ProtoMessage() {} + +func (x *GetFctNodeCpuUtilizationByProcessRequest) ProtoReflect() protoreflect.Message { + mi := &file_fct_node_cpu_utilization_by_process_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFctNodeCpuUtilizationByProcessRequest.ProtoReflect.Descriptor instead. +func (*GetFctNodeCpuUtilizationByProcessRequest) Descriptor() ([]byte, []int) { + return file_fct_node_cpu_utilization_by_process_proto_rawDescGZIP(), []int{3} +} + +func (x *GetFctNodeCpuUtilizationByProcessRequest) GetWallclockSlotStartDateTime() int64 { + if x != nil { + return x.WallclockSlotStartDateTime + } + return 0 +} + +// Response for getting a single fct_node_cpu_utilization_by_process record +type GetFctNodeCpuUtilizationByProcessResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *FctNodeCpuUtilizationByProcess `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *GetFctNodeCpuUtilizationByProcessResponse) Reset() { + *x = GetFctNodeCpuUtilizationByProcessResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_fct_node_cpu_utilization_by_process_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetFctNodeCpuUtilizationByProcessResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetFctNodeCpuUtilizationByProcessResponse) ProtoMessage() {} + +func (x *GetFctNodeCpuUtilizationByProcessResponse) ProtoReflect() protoreflect.Message { + mi := &file_fct_node_cpu_utilization_by_process_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetFctNodeCpuUtilizationByProcessResponse.ProtoReflect.Descriptor instead. +func (*GetFctNodeCpuUtilizationByProcessResponse) Descriptor() ([]byte, []int) { + return file_fct_node_cpu_utilization_by_process_proto_rawDescGZIP(), []int{4} +} + +func (x *GetFctNodeCpuUtilizationByProcessResponse) GetItem() *FctNodeCpuUtilizationByProcess { + if x != nil { + return x.Item + } + return nil +} + +var File_fct_node_cpu_utilization_by_process_proto protoreflect.FileDescriptor + +var file_fct_node_cpu_utilization_by_process_proto_rawDesc = []byte{ + 0x0a, 0x29, 0x66, 0x63, 0x74, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x75, + 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x79, 0x5f, 0x70, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x63, 0x62, 0x74, + 0x1a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, + 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x62, + 0x65, 0x68, 0x61, 0x76, 0x69, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x63, + 0x6c, 0x69, 0x63, 0x6b, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8d, 0x04, 0x0a, 0x1e, + 0x46, 0x63, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x70, 0x75, 0x55, 0x74, 0x69, 0x6c, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x2a, + 0x0a, 0x11, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x69, + 0x6e, 0x64, 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x0b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x25, 0x0a, + 0x0e, 0x77, 0x61, 0x6c, 0x6c, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, + 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x77, 0x61, 0x6c, 0x6c, 0x63, 0x6c, 0x6f, 0x63, 0x6b, + 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x42, 0x0a, 0x1e, 0x77, 0x61, 0x6c, 0x6c, 0x63, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x61, 0x74, + 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x77, 0x61, + 0x6c, 0x6c, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6c, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x65, 0x74, 0x61, + 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0f, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x65, 0x74, 0x61, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x6e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6d, + 0x65, 0x74, 0x61, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x70, 0x69, 0x64, + 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x63, 0x6f, 0x72, 0x65, + 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, + 0x6f, 0x72, 0x65, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x65, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x72, + 0x65, 0x5f, 0x70, 0x63, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0b, 0x6d, 0x65, 0x61, + 0x6e, 0x43, 0x6f, 0x72, 0x65, 0x50, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x0c, 0x6d, 0x69, 0x6e, 0x5f, + 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x70, 0x63, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0a, + 0x6d, 0x69, 0x6e, 0x43, 0x6f, 0x72, 0x65, 0x50, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x0c, 0x6d, 0x61, + 0x78, 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x70, 0x63, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x02, + 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x72, 0x65, 0x50, 0x63, 0x74, 0x12, 0x1d, 0x0a, 0x0a, + 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x22, 0xe1, 0x07, 0x0a, 0x29, + 0x4c, 0x69, 0x73, 0x74, 0x46, 0x63, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x70, 0x75, 0x55, 0x74, + 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x50, 0x72, 0x6f, 0x63, 0x65, + 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x68, 0x0a, 0x1e, 0x77, 0x61, 0x6c, + 0x6c, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x10, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x42, 0x12, 0xe0, 0x41, 0x02, 0x9a, 0xb5, 0x18, 0x0b, 0x70, 0x72, 0x69, 0x6d, + 0x61, 0x72, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x52, 0x1a, 0x77, 0x61, 0x6c, 0x6c, 0x63, 0x6c, 0x6f, + 0x63, 0x6b, 0x53, 0x6c, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, 0x65, 0x54, + 0x69, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x10, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x63, 0x62, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x0e, 0x6d, 0x65, 0x74, 0x61, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, + 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x42, 0x03, 0xe0, + 0x41, 0x01, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x28, + 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, + 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x42, 0x03, + 0xe0, 0x41, 0x01, 0x52, 0x03, 0x70, 0x69, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x77, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, + 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x0b, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x12, 0x42, 0x0a, 0x11, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, + 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x63, 0x62, 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x44, 0x61, + 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x0e, 0x77, 0x61, 0x6c, 0x6c, 0x63, 0x6c, + 0x6f, 0x63, 0x6b, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x0d, 0x77, 0x61, 0x6c, 0x6c, 0x63, 0x6c, 0x6f, 0x63, + 0x6b, 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x42, 0x0a, 0x11, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x6e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x46, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x0f, 0x6d, 0x65, 0x74, 0x61, 0x4e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x0c, 0x73, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x43, + 0x6f, 0x72, 0x65, 0x73, 0x12, 0x44, 0x0a, 0x0d, 0x6d, 0x65, 0x61, 0x6e, 0x5f, 0x63, 0x6f, 0x72, + 0x65, 0x5f, 0x70, 0x63, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x6c, + 0x6f, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x0b, 0x6d, + 0x65, 0x61, 0x6e, 0x43, 0x6f, 0x72, 0x65, 0x50, 0x63, 0x74, 0x12, 0x42, 0x0a, 0x0c, 0x6d, 0x69, + 0x6e, 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x70, 0x63, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x03, 0xe0, + 0x41, 0x01, 0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x43, 0x6f, 0x72, 0x65, 0x50, 0x63, 0x74, 0x12, 0x42, + 0x0a, 0x0c, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x70, 0x63, 0x74, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x72, 0x65, 0x50, + 0x63, 0x74, 0x12, 0x35, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x09, + 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x20, 0x0a, 0x09, 0x70, 0x61, 0x67, + 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x05, 0x42, 0x03, 0xe0, 0x41, + 0x01, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0a, 0x70, + 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x03, 0xe0, 0x41, 0x01, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, + 0x1e, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x22, + 0xc6, 0x01, 0x0a, 0x2a, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x63, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, + 0x70, 0x75, 0x55, 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x70, + 0x0a, 0x23, 0x66, 0x63, 0x74, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x75, + 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x79, 0x5f, 0x70, 0x72, + 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x62, + 0x74, 0x2e, 0x46, 0x63, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x70, 0x75, 0x55, 0x74, 0x69, 0x6c, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x52, 0x1e, 0x66, 0x63, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x70, 0x75, 0x55, 0x74, 0x69, 0x6c, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, + 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, + 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x6e, 0x0a, 0x28, 0x47, 0x65, 0x74, 0x46, + 0x63, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x70, 0x75, 0x55, 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x1e, 0x77, 0x61, 0x6c, 0x6c, 0x63, 0x6c, 0x6f, 0x63, + 0x6b, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x61, 0x74, + 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x1a, 0x77, 0x61, + 0x6c, 0x6c, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x6c, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x64, 0x0a, 0x29, 0x47, 0x65, 0x74, 0x46, + 0x63, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x70, 0x75, 0x55, 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x46, 0x63, 0x74, 0x4e, 0x6f, 0x64, + 0x65, 0x43, 0x70, 0x75, 0x55, 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, + 0x79, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x32, 0x83, + 0x03, 0x0a, 0x25, 0x46, 0x63, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x70, 0x75, 0x55, 0x74, 0x69, + 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x9c, 0x01, 0x0a, 0x04, 0x4c, 0x69, 0x73, + 0x74, 0x12, 0x2e, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x63, 0x74, 0x4e, + 0x6f, 0x64, 0x65, 0x43, 0x70, 0x75, 0x55, 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x42, 0x79, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x46, 0x63, 0x74, 0x4e, + 0x6f, 0x64, 0x65, 0x43, 0x70, 0x75, 0x55, 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x42, 0x79, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x12, 0x2b, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x63, 0x74, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x70, 0x75, + 0x5f, 0x75, 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x79, 0x5f, + 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0xba, 0x01, 0x0a, 0x03, 0x47, 0x65, 0x74, 0x12, + 0x2d, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x63, 0x74, 0x4e, 0x6f, 0x64, 0x65, + 0x43, 0x70, 0x75, 0x55, 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, + 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, + 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x63, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, + 0x70, 0x75, 0x55, 0x74, 0x69, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x54, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4e, 0x12, 0x4c, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, + 0x66, 0x63, 0x74, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x70, 0x75, 0x5f, 0x75, 0x74, 0x69, + 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x63, + 0x65, 0x73, 0x73, 0x2f, 0x7b, 0x77, 0x61, 0x6c, 0x6c, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x73, + 0x6c, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x7d, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x70, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x70, 0x73, 0x2f, 0x78, + 0x61, 0x74, 0x75, 0x2d, 0x63, 0x62, 0x74, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_fct_node_cpu_utilization_by_process_proto_rawDescOnce sync.Once + file_fct_node_cpu_utilization_by_process_proto_rawDescData = file_fct_node_cpu_utilization_by_process_proto_rawDesc +) + +func file_fct_node_cpu_utilization_by_process_proto_rawDescGZIP() []byte { + file_fct_node_cpu_utilization_by_process_proto_rawDescOnce.Do(func() { + file_fct_node_cpu_utilization_by_process_proto_rawDescData = protoimpl.X.CompressGZIP(file_fct_node_cpu_utilization_by_process_proto_rawDescData) + }) + return file_fct_node_cpu_utilization_by_process_proto_rawDescData +} + +var file_fct_node_cpu_utilization_by_process_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_fct_node_cpu_utilization_by_process_proto_goTypes = []any{ + (*FctNodeCpuUtilizationByProcess)(nil), // 0: cbt.FctNodeCpuUtilizationByProcess + (*ListFctNodeCpuUtilizationByProcessRequest)(nil), // 1: cbt.ListFctNodeCpuUtilizationByProcessRequest + (*ListFctNodeCpuUtilizationByProcessResponse)(nil), // 2: cbt.ListFctNodeCpuUtilizationByProcessResponse + (*GetFctNodeCpuUtilizationByProcessRequest)(nil), // 3: cbt.GetFctNodeCpuUtilizationByProcessRequest + (*GetFctNodeCpuUtilizationByProcessResponse)(nil), // 4: cbt.GetFctNodeCpuUtilizationByProcessResponse + (*Int64Filter)(nil), // 5: cbt.Int64Filter + (*StringFilter)(nil), // 6: cbt.StringFilter + (*UInt32Filter)(nil), // 7: cbt.UInt32Filter + (*wrapperspb.FloatValue)(nil), // 8: google.protobuf.FloatValue +} +var file_fct_node_cpu_utilization_by_process_proto_depIdxs = []int32{ + 5, // 0: cbt.ListFctNodeCpuUtilizationByProcessRequest.wallclock_slot_start_date_time:type_name -> cbt.Int64Filter + 6, // 1: cbt.ListFctNodeCpuUtilizationByProcessRequest.meta_client_name:type_name -> cbt.StringFilter + 6, // 2: cbt.ListFctNodeCpuUtilizationByProcessRequest.client_type:type_name -> cbt.StringFilter + 7, // 3: cbt.ListFctNodeCpuUtilizationByProcessRequest.pid:type_name -> cbt.UInt32Filter + 5, // 4: cbt.ListFctNodeCpuUtilizationByProcessRequest.window_start:type_name -> cbt.Int64Filter + 7, // 5: cbt.ListFctNodeCpuUtilizationByProcessRequest.updated_date_time:type_name -> cbt.UInt32Filter + 7, // 6: cbt.ListFctNodeCpuUtilizationByProcessRequest.wallclock_slot:type_name -> cbt.UInt32Filter + 6, // 7: cbt.ListFctNodeCpuUtilizationByProcessRequest.meta_network_name:type_name -> cbt.StringFilter + 7, // 8: cbt.ListFctNodeCpuUtilizationByProcessRequest.system_cores:type_name -> cbt.UInt32Filter + 8, // 9: cbt.ListFctNodeCpuUtilizationByProcessRequest.mean_core_pct:type_name -> google.protobuf.FloatValue + 8, // 10: cbt.ListFctNodeCpuUtilizationByProcessRequest.min_core_pct:type_name -> google.protobuf.FloatValue + 8, // 11: cbt.ListFctNodeCpuUtilizationByProcessRequest.max_core_pct:type_name -> google.protobuf.FloatValue + 6, // 12: cbt.ListFctNodeCpuUtilizationByProcessRequest.node_class:type_name -> cbt.StringFilter + 0, // 13: cbt.ListFctNodeCpuUtilizationByProcessResponse.fct_node_cpu_utilization_by_process:type_name -> cbt.FctNodeCpuUtilizationByProcess + 0, // 14: cbt.GetFctNodeCpuUtilizationByProcessResponse.item:type_name -> cbt.FctNodeCpuUtilizationByProcess + 1, // 15: cbt.FctNodeCpuUtilizationByProcessService.List:input_type -> cbt.ListFctNodeCpuUtilizationByProcessRequest + 3, // 16: cbt.FctNodeCpuUtilizationByProcessService.Get:input_type -> cbt.GetFctNodeCpuUtilizationByProcessRequest + 2, // 17: cbt.FctNodeCpuUtilizationByProcessService.List:output_type -> cbt.ListFctNodeCpuUtilizationByProcessResponse + 4, // 18: cbt.FctNodeCpuUtilizationByProcessService.Get:output_type -> cbt.GetFctNodeCpuUtilizationByProcessResponse + 17, // [17:19] is the sub-list for method output_type + 15, // [15:17] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name +} + +func init() { file_fct_node_cpu_utilization_by_process_proto_init() } +func file_fct_node_cpu_utilization_by_process_proto_init() { + if File_fct_node_cpu_utilization_by_process_proto != nil { + return + } + file_common_proto_init() + if !protoimpl.UnsafeEnabled { + file_fct_node_cpu_utilization_by_process_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*FctNodeCpuUtilizationByProcess); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fct_node_cpu_utilization_by_process_proto_msgTypes[1].Exporter = func(v any, i int) any { + switch v := v.(*ListFctNodeCpuUtilizationByProcessRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fct_node_cpu_utilization_by_process_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*ListFctNodeCpuUtilizationByProcessResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fct_node_cpu_utilization_by_process_proto_msgTypes[3].Exporter = func(v any, i int) any { + switch v := v.(*GetFctNodeCpuUtilizationByProcessRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_fct_node_cpu_utilization_by_process_proto_msgTypes[4].Exporter = func(v any, i int) any { + switch v := v.(*GetFctNodeCpuUtilizationByProcessResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_fct_node_cpu_utilization_by_process_proto_rawDesc, + NumEnums: 0, + NumMessages: 5, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_fct_node_cpu_utilization_by_process_proto_goTypes, + DependencyIndexes: file_fct_node_cpu_utilization_by_process_proto_depIdxs, + MessageInfos: file_fct_node_cpu_utilization_by_process_proto_msgTypes, + }.Build() + File_fct_node_cpu_utilization_by_process_proto = out.File + file_fct_node_cpu_utilization_by_process_proto_rawDesc = nil + file_fct_node_cpu_utilization_by_process_proto_goTypes = nil + file_fct_node_cpu_utilization_by_process_proto_depIdxs = nil +} diff --git a/pkg/proto/clickhouse/fct_node_cpu_utilization_by_process.proto b/pkg/proto/clickhouse/fct_node_cpu_utilization_by_process.proto new file mode 100644 index 00000000..74a72f89 --- /dev/null +++ b/pkg/proto/clickhouse/fct_node_cpu_utilization_by_process.proto @@ -0,0 +1,124 @@ +syntax = "proto3"; + +package cbt; + +import "common.proto"; +import "google/protobuf/wrappers.proto"; +import "google/api/annotations.proto"; +import "google/api/field_behavior.proto"; +import "clickhouse/annotations.proto"; + +option go_package = "github.com/ethpandaops/xatu-cbt/pkg/proto/clickhouse"; +// Node CPU utilization per sub-slot window enriched with node classification + +message FctNodeCpuUtilizationByProcess { + // Timestamp when the record was last updated + uint32 updated_date_time = 11; + // Start of the sub-slot aggregation window + int64 window_start = 12; + // The wallclock slot number + uint32 wallclock_slot = 13; + // The wall clock time when the slot started + int64 wallclock_slot_start_date_time = 14; + // Name of the observoor client that collected the data + string meta_client_name = 15; + // Ethereum network name + string meta_network_name = 16; + // Process ID of the monitored client + uint32 pid = 17; + // Client type: CL or EL + string client_type = 18; + // Total system CPU cores + uint32 system_cores = 19; + // Mean CPU core utilization percentage (100pct = 1 core) + float mean_core_pct = 20; + // Minimum CPU core utilization percentage (100pct = 1 core) + float min_core_pct = 21; + // Maximum CPU core utilization percentage (100pct = 1 core) + float max_core_pct = 22; + // Node classification for filtering (e.g. eip7870) + string node_class = 23; +} + +// Request for listing fct_node_cpu_utilization_by_process records +message ListFctNodeCpuUtilizationByProcessRequest { + // Filter by wallclock_slot_start_date_time - The wall clock time when the slot started (PRIMARY KEY - required) + Int64Filter wallclock_slot_start_date_time = 1 [(google.api.field_behavior) = REQUIRED, (clickhouse.v1.required_group) = "primary_key"]; + + // Filter by meta_client_name - Name of the observoor client that collected the data (ORDER BY column 2 - optional) + StringFilter meta_client_name = 2 [(google.api.field_behavior) = OPTIONAL]; + + // Filter by client_type - Client type: CL or EL (ORDER BY column 3 - optional) + StringFilter client_type = 3 [(google.api.field_behavior) = OPTIONAL]; + + // Filter by pid - Process ID of the monitored client (ORDER BY column 4 - optional) + UInt32Filter pid = 4 [(google.api.field_behavior) = OPTIONAL]; + + // Filter by window_start - Start of the sub-slot aggregation window (ORDER BY column 5 - optional) + Int64Filter window_start = 5 [(google.api.field_behavior) = OPTIONAL]; + + // Filter by updated_date_time - Timestamp when the record was last updated (optional) + UInt32Filter updated_date_time = 6 [(google.api.field_behavior) = OPTIONAL]; + // Filter by wallclock_slot - The wallclock slot number (optional) + UInt32Filter wallclock_slot = 7 [(google.api.field_behavior) = OPTIONAL]; + // Filter by meta_network_name - Ethereum network name (optional) + StringFilter meta_network_name = 8 [(google.api.field_behavior) = OPTIONAL]; + // Filter by system_cores - Total system CPU cores (optional) + UInt32Filter system_cores = 9 [(google.api.field_behavior) = OPTIONAL]; + // Filter by mean_core_pct - Mean CPU core utilization percentage (100pct = 1 core) (optional) + google.protobuf.FloatValue mean_core_pct = 10 [(google.api.field_behavior) = OPTIONAL]; + // Filter by min_core_pct - Minimum CPU core utilization percentage (100pct = 1 core) (optional) + google.protobuf.FloatValue min_core_pct = 11 [(google.api.field_behavior) = OPTIONAL]; + // Filter by max_core_pct - Maximum CPU core utilization percentage (100pct = 1 core) (optional) + google.protobuf.FloatValue max_core_pct = 12 [(google.api.field_behavior) = OPTIONAL]; + // Filter by node_class - Node classification for filtering (e.g. eip7870) (optional) + StringFilter node_class = 13 [(google.api.field_behavior) = OPTIONAL]; + + // The maximum number of fct_node_cpu_utilization_by_process to return. + // If unspecified, at most 100 items will be returned. + // The maximum value is 10000; values above 10000 will be coerced to 10000. + int32 page_size = 14 [(google.api.field_behavior) = OPTIONAL]; + // A page token, received from a previous `ListFctNodeCpuUtilizationByProcess` call. + // Provide this to retrieve the subsequent page. + string page_token = 15 [(google.api.field_behavior) = OPTIONAL]; + // The order of results. Format: comma-separated list of fields. + // Example: "foo,bar" or "foo desc,bar" for descending order on foo. + // If unspecified, results will be returned in the default order. + string order_by = 16 [(google.api.field_behavior) = OPTIONAL]; +} + +// Response for listing fct_node_cpu_utilization_by_process records +message ListFctNodeCpuUtilizationByProcessResponse { + // The list of fct_node_cpu_utilization_by_process. + repeated FctNodeCpuUtilizationByProcess fct_node_cpu_utilization_by_process = 1; + // A token, which can be sent as `page_token` to retrieve the next page. + // If this field is omitted, there are no subsequent pages. + string next_page_token = 2; +} + +// Request for getting a single fct_node_cpu_utilization_by_process record by primary key +message GetFctNodeCpuUtilizationByProcessRequest { + // The wall clock time when the slot started + int64 wallclock_slot_start_date_time = 1; // Primary key (required) +} + +// Response for getting a single fct_node_cpu_utilization_by_process record +message GetFctNodeCpuUtilizationByProcessResponse { + FctNodeCpuUtilizationByProcess item = 1; +} + +// Query fct_node_cpu_utilization_by_process data +service FctNodeCpuUtilizationByProcessService { + // List records | Retrieve paginated results with optional filtering + rpc List(ListFctNodeCpuUtilizationByProcessRequest) returns (ListFctNodeCpuUtilizationByProcessResponse) { + option (google.api.http) = { + get: "/api/v1/fct_node_cpu_utilization_by_process" + }; + } + // Get record | Retrieve a single record by wallclock_slot_start_date_time + rpc Get(GetFctNodeCpuUtilizationByProcessRequest) returns (GetFctNodeCpuUtilizationByProcessResponse) { + option (google.api.http) = { + get: "/api/v1/fct_node_cpu_utilization_by_process/{wallclock_slot_start_date_time}" + }; + } +} diff --git a/pkg/proto/clickhouse/int_engine_new_payload_fastest_execution_by_node_class.go b/pkg/proto/clickhouse/int_engine_new_payload_fastest_execution_by_node_class.go index 3ed40b45..666484ec 100644 --- a/pkg/proto/clickhouse/int_engine_new_payload_fastest_execution_by_node_class.go +++ b/pkg/proto/clickhouse/int_engine_new_payload_fastest_execution_by_node_class.go @@ -198,11 +198,11 @@ func BuildListIntEngineNewPayloadFastestExecutionByNodeClassQuery(req *ListIntEn case *StringFilter_Ne: qb.AddCondition("block_hash", "!=", filter.Ne) case *StringFilter_Contains: - qb.AddLikeCondition("block_hash", "%"+filter.Contains+"%") + qb.AddLikeCondition("block_hash", "%" + filter.Contains + "%") case *StringFilter_StartsWith: - qb.AddLikeCondition("block_hash", filter.StartsWith+"%") + qb.AddLikeCondition("block_hash", filter.StartsWith + "%") case *StringFilter_EndsWith: - qb.AddLikeCondition("block_hash", "%"+filter.EndsWith) + qb.AddLikeCondition("block_hash", "%" + filter.EndsWith) case *StringFilter_Like: qb.AddLikeCondition("block_hash", filter.Like) case *StringFilter_NotLike: @@ -258,11 +258,11 @@ func BuildListIntEngineNewPayloadFastestExecutionByNodeClassQuery(req *ListIntEn case *StringFilter_Ne: qb.AddCondition("node_class", "!=", filter.Ne) case *StringFilter_Contains: - qb.AddLikeCondition("node_class", "%"+filter.Contains+"%") + qb.AddLikeCondition("node_class", "%" + filter.Contains + "%") case *StringFilter_StartsWith: - qb.AddLikeCondition("node_class", filter.StartsWith+"%") + qb.AddLikeCondition("node_class", filter.StartsWith + "%") case *StringFilter_EndsWith: - qb.AddLikeCondition("node_class", "%"+filter.EndsWith) + qb.AddLikeCondition("node_class", "%" + filter.EndsWith) case *StringFilter_Like: qb.AddLikeCondition("node_class", filter.Like) case *StringFilter_NotLike: @@ -288,11 +288,11 @@ func BuildListIntEngineNewPayloadFastestExecutionByNodeClassQuery(req *ListIntEn case *StringFilter_Ne: qb.AddCondition("meta_execution_implementation", "!=", filter.Ne) case *StringFilter_Contains: - qb.AddLikeCondition("meta_execution_implementation", "%"+filter.Contains+"%") + qb.AddLikeCondition("meta_execution_implementation", "%" + filter.Contains + "%") case *StringFilter_StartsWith: - qb.AddLikeCondition("meta_execution_implementation", filter.StartsWith+"%") + qb.AddLikeCondition("meta_execution_implementation", filter.StartsWith + "%") case *StringFilter_EndsWith: - qb.AddLikeCondition("meta_execution_implementation", "%"+filter.EndsWith) + qb.AddLikeCondition("meta_execution_implementation", "%" + filter.EndsWith) case *StringFilter_Like: qb.AddLikeCondition("meta_execution_implementation", filter.Like) case *StringFilter_NotLike: @@ -318,11 +318,11 @@ func BuildListIntEngineNewPayloadFastestExecutionByNodeClassQuery(req *ListIntEn case *StringFilter_Ne: qb.AddCondition("meta_execution_version", "!=", filter.Ne) case *StringFilter_Contains: - qb.AddLikeCondition("meta_execution_version", "%"+filter.Contains+"%") + qb.AddLikeCondition("meta_execution_version", "%" + filter.Contains + "%") case *StringFilter_StartsWith: - qb.AddLikeCondition("meta_execution_version", filter.StartsWith+"%") + qb.AddLikeCondition("meta_execution_version", filter.StartsWith + "%") case *StringFilter_EndsWith: - qb.AddLikeCondition("meta_execution_version", "%"+filter.EndsWith) + qb.AddLikeCondition("meta_execution_version", "%" + filter.EndsWith) case *StringFilter_Like: qb.AddLikeCondition("meta_execution_version", filter.Like) case *StringFilter_NotLike: @@ -348,11 +348,11 @@ func BuildListIntEngineNewPayloadFastestExecutionByNodeClassQuery(req *ListIntEn case *StringFilter_Ne: qb.AddCondition("meta_client_name", "!=", filter.Ne) case *StringFilter_Contains: - qb.AddLikeCondition("meta_client_name", "%"+filter.Contains+"%") + qb.AddLikeCondition("meta_client_name", "%" + filter.Contains + "%") case *StringFilter_StartsWith: - qb.AddLikeCondition("meta_client_name", filter.StartsWith+"%") + qb.AddLikeCondition("meta_client_name", filter.StartsWith + "%") case *StringFilter_EndsWith: - qb.AddLikeCondition("meta_client_name", "%"+filter.EndsWith) + qb.AddLikeCondition("meta_client_name", "%" + filter.EndsWith) case *StringFilter_Like: qb.AddLikeCondition("meta_client_name", filter.Like) case *StringFilter_NotLike: diff --git a/pkg/proto/clickhouse/int_engine_new_payload_fastest_execution_by_node_class.pb.go b/pkg/proto/clickhouse/int_engine_new_payload_fastest_execution_by_node_class.pb.go index a40f1f2b..307ed8ba 100644 --- a/pkg/proto/clickhouse/int_engine_new_payload_fastest_execution_by_node_class.pb.go +++ b/pkg/proto/clickhouse/int_engine_new_payload_fastest_execution_by_node_class.pb.go @@ -2,7 +2,7 @@ // versions: // protoc-gen-go v1.34.2 // protoc (unknown) -// source: int_engine_new_payload_fastest.proto +// source: int_engine_new_payload_fastest_execution_by_node_class.proto package clickhouse @@ -52,7 +52,7 @@ type IntEngineNewPayloadFastestExecutionByNodeClass struct { func (x *IntEngineNewPayloadFastestExecutionByNodeClass) Reset() { *x = IntEngineNewPayloadFastestExecutionByNodeClass{} if protoimpl.UnsafeEnabled { - mi := &file_int_engine_new_payload_fastest_proto_msgTypes[0] + mi := &file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -65,7 +65,7 @@ func (x *IntEngineNewPayloadFastestExecutionByNodeClass) String() string { func (*IntEngineNewPayloadFastestExecutionByNodeClass) ProtoMessage() {} func (x *IntEngineNewPayloadFastestExecutionByNodeClass) ProtoReflect() protoreflect.Message { - mi := &file_int_engine_new_payload_fastest_proto_msgTypes[0] + mi := &file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -78,7 +78,7 @@ func (x *IntEngineNewPayloadFastestExecutionByNodeClass) ProtoReflect() protoref // Deprecated: Use IntEngineNewPayloadFastestExecutionByNodeClass.ProtoReflect.Descriptor instead. func (*IntEngineNewPayloadFastestExecutionByNodeClass) Descriptor() ([]byte, []int) { - return file_int_engine_new_payload_fastest_proto_rawDescGZIP(), []int{0} + return file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDescGZIP(), []int{0} } func (x *IntEngineNewPayloadFastestExecutionByNodeClass) GetUpdatedDateTime() uint32 { @@ -158,7 +158,7 @@ func (x *IntEngineNewPayloadFastestExecutionByNodeClass) GetMetaClientName() str return "" } -// Request for listing int_engine_new_payload_fastest records +// Request for listing int_engine_new_payload_fastest_execution_by_node_class records type ListIntEngineNewPayloadFastestExecutionByNodeClassRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -186,7 +186,7 @@ type ListIntEngineNewPayloadFastestExecutionByNodeClassRequest struct { MetaExecutionVersion *StringFilter `protobuf:"bytes,10,opt,name=meta_execution_version,json=metaExecutionVersion,proto3" json:"meta_execution_version,omitempty"` // Filter by meta_client_name - Name of the client that generated the event (optional) MetaClientName *StringFilter `protobuf:"bytes,11,opt,name=meta_client_name,json=metaClientName,proto3" json:"meta_client_name,omitempty"` - // The maximum number of int_engine_new_payload_fastest to return. + // The maximum number of int_engine_new_payload_fastest_execution_by_node_class to return. // If unspecified, at most 100 items will be returned. // The maximum value is 10000; values above 10000 will be coerced to 10000. PageSize int32 `protobuf:"varint,12,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` @@ -202,7 +202,7 @@ type ListIntEngineNewPayloadFastestExecutionByNodeClassRequest struct { func (x *ListIntEngineNewPayloadFastestExecutionByNodeClassRequest) Reset() { *x = ListIntEngineNewPayloadFastestExecutionByNodeClassRequest{} if protoimpl.UnsafeEnabled { - mi := &file_int_engine_new_payload_fastest_proto_msgTypes[1] + mi := &file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -215,7 +215,7 @@ func (x *ListIntEngineNewPayloadFastestExecutionByNodeClassRequest) String() str func (*ListIntEngineNewPayloadFastestExecutionByNodeClassRequest) ProtoMessage() {} func (x *ListIntEngineNewPayloadFastestExecutionByNodeClassRequest) ProtoReflect() protoreflect.Message { - mi := &file_int_engine_new_payload_fastest_proto_msgTypes[1] + mi := &file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -228,7 +228,7 @@ func (x *ListIntEngineNewPayloadFastestExecutionByNodeClassRequest) ProtoReflect // Deprecated: Use ListIntEngineNewPayloadFastestExecutionByNodeClassRequest.ProtoReflect.Descriptor instead. func (*ListIntEngineNewPayloadFastestExecutionByNodeClassRequest) Descriptor() ([]byte, []int) { - return file_int_engine_new_payload_fastest_proto_rawDescGZIP(), []int{1} + return file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDescGZIP(), []int{1} } func (x *ListIntEngineNewPayloadFastestExecutionByNodeClassRequest) GetSlotStartDateTime() *UInt32Filter { @@ -329,14 +329,14 @@ func (x *ListIntEngineNewPayloadFastestExecutionByNodeClassRequest) GetOrderBy() return "" } -// Response for listing int_engine_new_payload_fastest records +// Response for listing int_engine_new_payload_fastest_execution_by_node_class records type ListIntEngineNewPayloadFastestExecutionByNodeClassResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // The list of int_engine_new_payload_fastest. - IntEngineNewPayloadFastestExecutionByNodeClass []*IntEngineNewPayloadFastestExecutionByNodeClass `protobuf:"bytes,1,rep,name=int_engine_new_payload_fastest,json=intEngineNewPayloadFastest,proto3" json:"int_engine_new_payload_fastest,omitempty"` + // The list of int_engine_new_payload_fastest_execution_by_node_class. + IntEngineNewPayloadFastestExecutionByNodeClass []*IntEngineNewPayloadFastestExecutionByNodeClass `protobuf:"bytes,1,rep,name=int_engine_new_payload_fastest_execution_by_node_class,json=intEngineNewPayloadFastestExecutionByNodeClass,proto3" json:"int_engine_new_payload_fastest_execution_by_node_class,omitempty"` // A token, which can be sent as `page_token` to retrieve the next page. // If this field is omitted, there are no subsequent pages. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` @@ -345,7 +345,7 @@ type ListIntEngineNewPayloadFastestExecutionByNodeClassResponse struct { func (x *ListIntEngineNewPayloadFastestExecutionByNodeClassResponse) Reset() { *x = ListIntEngineNewPayloadFastestExecutionByNodeClassResponse{} if protoimpl.UnsafeEnabled { - mi := &file_int_engine_new_payload_fastest_proto_msgTypes[2] + mi := &file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -358,7 +358,7 @@ func (x *ListIntEngineNewPayloadFastestExecutionByNodeClassResponse) String() st func (*ListIntEngineNewPayloadFastestExecutionByNodeClassResponse) ProtoMessage() {} func (x *ListIntEngineNewPayloadFastestExecutionByNodeClassResponse) ProtoReflect() protoreflect.Message { - mi := &file_int_engine_new_payload_fastest_proto_msgTypes[2] + mi := &file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -371,7 +371,7 @@ func (x *ListIntEngineNewPayloadFastestExecutionByNodeClassResponse) ProtoReflec // Deprecated: Use ListIntEngineNewPayloadFastestExecutionByNodeClassResponse.ProtoReflect.Descriptor instead. func (*ListIntEngineNewPayloadFastestExecutionByNodeClassResponse) Descriptor() ([]byte, []int) { - return file_int_engine_new_payload_fastest_proto_rawDescGZIP(), []int{2} + return file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDescGZIP(), []int{2} } func (x *ListIntEngineNewPayloadFastestExecutionByNodeClassResponse) GetIntEngineNewPayloadFastestExecutionByNodeClass() []*IntEngineNewPayloadFastestExecutionByNodeClass { @@ -388,7 +388,7 @@ func (x *ListIntEngineNewPayloadFastestExecutionByNodeClassResponse) GetNextPage return "" } -// Request for getting a single int_engine_new_payload_fastest record by primary key +// Request for getting a single int_engine_new_payload_fastest_execution_by_node_class record by primary key type GetIntEngineNewPayloadFastestExecutionByNodeClassRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -401,7 +401,7 @@ type GetIntEngineNewPayloadFastestExecutionByNodeClassRequest struct { func (x *GetIntEngineNewPayloadFastestExecutionByNodeClassRequest) Reset() { *x = GetIntEngineNewPayloadFastestExecutionByNodeClassRequest{} if protoimpl.UnsafeEnabled { - mi := &file_int_engine_new_payload_fastest_proto_msgTypes[3] + mi := &file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -414,7 +414,7 @@ func (x *GetIntEngineNewPayloadFastestExecutionByNodeClassRequest) String() stri func (*GetIntEngineNewPayloadFastestExecutionByNodeClassRequest) ProtoMessage() {} func (x *GetIntEngineNewPayloadFastestExecutionByNodeClassRequest) ProtoReflect() protoreflect.Message { - mi := &file_int_engine_new_payload_fastest_proto_msgTypes[3] + mi := &file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -427,7 +427,7 @@ func (x *GetIntEngineNewPayloadFastestExecutionByNodeClassRequest) ProtoReflect( // Deprecated: Use GetIntEngineNewPayloadFastestExecutionByNodeClassRequest.ProtoReflect.Descriptor instead. func (*GetIntEngineNewPayloadFastestExecutionByNodeClassRequest) Descriptor() ([]byte, []int) { - return file_int_engine_new_payload_fastest_proto_rawDescGZIP(), []int{3} + return file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDescGZIP(), []int{3} } func (x *GetIntEngineNewPayloadFastestExecutionByNodeClassRequest) GetSlotStartDateTime() uint32 { @@ -437,7 +437,7 @@ func (x *GetIntEngineNewPayloadFastestExecutionByNodeClassRequest) GetSlotStartD return 0 } -// Response for getting a single int_engine_new_payload_fastest record +// Response for getting a single int_engine_new_payload_fastest_execution_by_node_class record type GetIntEngineNewPayloadFastestExecutionByNodeClassResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -449,7 +449,7 @@ type GetIntEngineNewPayloadFastestExecutionByNodeClassResponse struct { func (x *GetIntEngineNewPayloadFastestExecutionByNodeClassResponse) Reset() { *x = GetIntEngineNewPayloadFastestExecutionByNodeClassResponse{} if protoimpl.UnsafeEnabled { - mi := &file_int_engine_new_payload_fastest_proto_msgTypes[4] + mi := &file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -462,7 +462,7 @@ func (x *GetIntEngineNewPayloadFastestExecutionByNodeClassResponse) String() str func (*GetIntEngineNewPayloadFastestExecutionByNodeClassResponse) ProtoMessage() {} func (x *GetIntEngineNewPayloadFastestExecutionByNodeClassResponse) ProtoReflect() protoreflect.Message { - mi := &file_int_engine_new_payload_fastest_proto_msgTypes[4] + mi := &file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -475,7 +475,7 @@ func (x *GetIntEngineNewPayloadFastestExecutionByNodeClassResponse) ProtoReflect // Deprecated: Use GetIntEngineNewPayloadFastestExecutionByNodeClassResponse.ProtoReflect.Descriptor instead. func (*GetIntEngineNewPayloadFastestExecutionByNodeClassResponse) Descriptor() ([]byte, []int) { - return file_int_engine_new_payload_fastest_proto_rawDescGZIP(), []int{4} + return file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDescGZIP(), []int{4} } func (x *GetIntEngineNewPayloadFastestExecutionByNodeClassResponse) GetItem() *IntEngineNewPayloadFastestExecutionByNodeClass { @@ -485,45 +485,49 @@ func (x *GetIntEngineNewPayloadFastestExecutionByNodeClassResponse) GetItem() *I return nil } -var File_int_engine_new_payload_fastest_proto protoreflect.FileDescriptor +var File_int_engine_new_payload_fastest_execution_by_node_class_proto protoreflect.FileDescriptor -var file_int_engine_new_payload_fastest_proto_rawDesc = []byte{ - 0x0a, 0x24, 0x69, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x6e, 0x65, 0x77, +var file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDesc = []byte{ + 0x0a, 0x3c, 0x69, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x66, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x63, 0x62, 0x74, 0x1a, 0x0c, 0x63, 0x6f, 0x6d, - 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd9, 0x03, 0x0a, 0x1a, 0x49, 0x6e, - 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x11, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0b, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, - 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x6c, 0x6f, 0x74, - 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x73, 0x6c, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x72, - 0x74, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, - 0x63, 0x68, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, - 0x31, 0x0a, 0x15, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, - 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, - 0x65, 0x70, 0x6f, 0x63, 0x68, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, - 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, - 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, - 0x18, 0x11, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x4d, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, - 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, - 0x73, 0x12, 0x42, 0x0a, 0x1d, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x6d, 0x65, 0x74, 0x61, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x16, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x6d, 0x65, 0x74, 0x61, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x6d, - 0x65, 0x74, 0x61, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6d, 0x65, 0x74, 0x61, 0x43, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x8c, 0x06, 0x0a, 0x25, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, - 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x79, 0x5f, 0x6e, 0x6f, + 0x64, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, + 0x63, 0x62, 0x74, 0x1a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0xed, 0x03, 0x0a, 0x2e, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, + 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x43, + 0x6c, 0x61, 0x73, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, + 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0d, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x11, 0x73, 0x6c, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, + 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x0e, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x12, 0x31, 0x0a, 0x15, 0x65, + 0x70, 0x6f, 0x63, 0x68, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x65, 0x70, 0x6f, 0x63, + 0x68, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1d, + 0x0a, 0x0a, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x10, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1f, 0x0a, + 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x73, 0x18, 0x11, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0a, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x73, 0x12, 0x1d, + 0x0a, 0x0a, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x12, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x42, 0x0a, + 0x1d, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x13, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x6d, 0x65, 0x74, 0x61, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x34, 0x0a, 0x16, 0x6d, 0x65, 0x74, 0x61, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x14, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x14, 0x6d, 0x65, 0x74, 0x61, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x65, 0x74, 0x61, 0x5f, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0e, 0x6d, 0x65, 0x74, 0x61, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x22, 0xa0, 0x06, 0x0a, 0x39, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, + 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, + 0x74, 0x65, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x4e, + 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x42, 0x0a, 0x14, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, @@ -570,64 +574,79 @@ var file_int_engine_new_payload_fastest_proto_rawDesc = []byte{ 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, - 0x65, 0x72, 0x42, 0x79, 0x22, 0xb5, 0x01, 0x0a, 0x26, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x42, 0x79, 0x22, 0x8a, 0x02, 0x0a, 0x3a, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, - 0x46, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x63, 0x0a, 0x1e, 0x69, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5f, 0x6e, 0x65, - 0x77, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x66, 0x61, 0x73, 0x74, 0x65, 0x73, - 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x49, 0x6e, - 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, - 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x52, 0x1a, 0x69, 0x6e, 0x74, 0x45, 0x6e, 0x67, - 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, - 0x74, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, - 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, - 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x57, 0x0a, 0x24, - 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x14, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x11, 0x73, 0x6c, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, - 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x5c, 0x0a, 0x25, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x45, - 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, - 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, - 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, - 0x62, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x52, 0x04, 0x69, - 0x74, 0x65, 0x6d, 0x32, 0xe2, 0x01, 0x0a, 0x21, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, - 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, - 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x04, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x2a, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x45, - 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, - 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, - 0x63, 0x62, 0x74, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, - 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x03, 0x47, 0x65, - 0x74, 0x12, 0x29, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x45, 0x6e, + 0x46, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x42, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0xa3, 0x01, 0x0a, 0x36, 0x69, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x67, 0x69, + 0x6e, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x66, + 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x62, 0x79, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x45, 0x6e, + 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, + 0x73, 0x74, 0x65, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, + 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x52, 0x2e, 0x69, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, - 0x73, 0x74, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x63, - 0x62, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, + 0x73, 0x74, 0x65, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, + 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, + 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x22, 0x6b, 0x0a, 0x38, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, + 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, + 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x4e, 0x6f, 0x64, + 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, + 0x14, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x11, 0x73, 0x6c, 0x6f, + 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x84, + 0x01, 0x0a, 0x39, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x74, 0x68, 0x70, 0x61, 0x6e, 0x64, 0x61, 0x6f, - 0x70, 0x73, 0x2f, 0x78, 0x61, 0x74, 0x75, 0x2d, 0x63, 0x62, 0x74, 0x2f, 0x70, 0x6b, 0x67, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x68, 0x6f, 0x75, 0x73, 0x65, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x43, + 0x6c, 0x61, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x04, + 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x63, 0x62, 0x74, + 0x2e, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, + 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x52, + 0x04, 0x69, 0x74, 0x65, 0x6d, 0x32, 0xc8, 0x02, 0x0a, 0x35, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, + 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, + 0x74, 0x65, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x4e, + 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x87, 0x01, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x3e, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3f, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, + 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, 0x74, 0x65, 0x73, 0x74, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x84, 0x01, 0x0a, 0x03, 0x47, 0x65, + 0x74, 0x12, 0x3d, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x45, 0x6e, + 0x67, 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, + 0x73, 0x74, 0x65, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, + 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x3e, 0x2e, 0x63, 0x62, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x74, 0x45, 0x6e, 0x67, + 0x69, 0x6e, 0x65, 0x4e, 0x65, 0x77, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x46, 0x61, 0x73, + 0x74, 0x65, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x4e, + 0x6f, 0x64, 0x65, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, + 0x74, 0x68, 0x70, 0x61, 0x6e, 0x64, 0x61, 0x6f, 0x70, 0x73, 0x2f, 0x78, 0x61, 0x74, 0x75, 0x2d, + 0x63, 0x62, 0x74, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x63, 0x6c, + 0x69, 0x63, 0x6b, 0x68, 0x6f, 0x75, 0x73, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( - file_int_engine_new_payload_fastest_proto_rawDescOnce sync.Once - file_int_engine_new_payload_fastest_proto_rawDescData = file_int_engine_new_payload_fastest_proto_rawDesc + file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDescOnce sync.Once + file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDescData = file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDesc ) -func file_int_engine_new_payload_fastest_proto_rawDescGZIP() []byte { - file_int_engine_new_payload_fastest_proto_rawDescOnce.Do(func() { - file_int_engine_new_payload_fastest_proto_rawDescData = protoimpl.X.CompressGZIP(file_int_engine_new_payload_fastest_proto_rawDescData) +func file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDescGZIP() []byte { + file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDescOnce.Do(func() { + file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDescData = protoimpl.X.CompressGZIP(file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDescData) }) - return file_int_engine_new_payload_fastest_proto_rawDescData + return file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDescData } -var file_int_engine_new_payload_fastest_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_int_engine_new_payload_fastest_proto_goTypes = []any{ +var file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_int_engine_new_payload_fastest_execution_by_node_class_proto_goTypes = []any{ (*IntEngineNewPayloadFastestExecutionByNodeClass)(nil), // 0: cbt.IntEngineNewPayloadFastestExecutionByNodeClass (*ListIntEngineNewPayloadFastestExecutionByNodeClassRequest)(nil), // 1: cbt.ListIntEngineNewPayloadFastestExecutionByNodeClassRequest (*ListIntEngineNewPayloadFastestExecutionByNodeClassResponse)(nil), // 2: cbt.ListIntEngineNewPayloadFastestExecutionByNodeClassResponse @@ -637,7 +656,7 @@ var file_int_engine_new_payload_fastest_proto_goTypes = []any{ (*StringFilter)(nil), // 6: cbt.StringFilter (*UInt64Filter)(nil), // 7: cbt.UInt64Filter } -var file_int_engine_new_payload_fastest_proto_depIdxs = []int32{ +var file_int_engine_new_payload_fastest_execution_by_node_class_proto_depIdxs = []int32{ 5, // 0: cbt.ListIntEngineNewPayloadFastestExecutionByNodeClassRequest.slot_start_date_time:type_name -> cbt.UInt32Filter 5, // 1: cbt.ListIntEngineNewPayloadFastestExecutionByNodeClassRequest.slot:type_name -> cbt.UInt32Filter 6, // 2: cbt.ListIntEngineNewPayloadFastestExecutionByNodeClassRequest.node_class:type_name -> cbt.StringFilter @@ -649,7 +668,7 @@ var file_int_engine_new_payload_fastest_proto_depIdxs = []int32{ 6, // 8: cbt.ListIntEngineNewPayloadFastestExecutionByNodeClassRequest.meta_execution_implementation:type_name -> cbt.StringFilter 6, // 9: cbt.ListIntEngineNewPayloadFastestExecutionByNodeClassRequest.meta_execution_version:type_name -> cbt.StringFilter 6, // 10: cbt.ListIntEngineNewPayloadFastestExecutionByNodeClassRequest.meta_client_name:type_name -> cbt.StringFilter - 0, // 11: cbt.ListIntEngineNewPayloadFastestExecutionByNodeClassResponse.int_engine_new_payload_fastest:type_name -> cbt.IntEngineNewPayloadFastestExecutionByNodeClass + 0, // 11: cbt.ListIntEngineNewPayloadFastestExecutionByNodeClassResponse.int_engine_new_payload_fastest_execution_by_node_class:type_name -> cbt.IntEngineNewPayloadFastestExecutionByNodeClass 0, // 12: cbt.GetIntEngineNewPayloadFastestExecutionByNodeClassResponse.item:type_name -> cbt.IntEngineNewPayloadFastestExecutionByNodeClass 1, // 13: cbt.IntEngineNewPayloadFastestExecutionByNodeClassService.List:input_type -> cbt.ListIntEngineNewPayloadFastestExecutionByNodeClassRequest 3, // 14: cbt.IntEngineNewPayloadFastestExecutionByNodeClassService.Get:input_type -> cbt.GetIntEngineNewPayloadFastestExecutionByNodeClassRequest @@ -662,14 +681,14 @@ var file_int_engine_new_payload_fastest_proto_depIdxs = []int32{ 0, // [0:13] is the sub-list for field type_name } -func init() { file_int_engine_new_payload_fastest_proto_init() } -func file_int_engine_new_payload_fastest_proto_init() { - if File_int_engine_new_payload_fastest_proto != nil { +func init() { file_int_engine_new_payload_fastest_execution_by_node_class_proto_init() } +func file_int_engine_new_payload_fastest_execution_by_node_class_proto_init() { + if File_int_engine_new_payload_fastest_execution_by_node_class_proto != nil { return } file_common_proto_init() if !protoimpl.UnsafeEnabled { - file_int_engine_new_payload_fastest_proto_msgTypes[0].Exporter = func(v any, i int) any { + file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*IntEngineNewPayloadFastestExecutionByNodeClass); i { case 0: return &v.state @@ -681,7 +700,7 @@ func file_int_engine_new_payload_fastest_proto_init() { return nil } } - file_int_engine_new_payload_fastest_proto_msgTypes[1].Exporter = func(v any, i int) any { + file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*ListIntEngineNewPayloadFastestExecutionByNodeClassRequest); i { case 0: return &v.state @@ -693,7 +712,7 @@ func file_int_engine_new_payload_fastest_proto_init() { return nil } } - file_int_engine_new_payload_fastest_proto_msgTypes[2].Exporter = func(v any, i int) any { + file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*ListIntEngineNewPayloadFastestExecutionByNodeClassResponse); i { case 0: return &v.state @@ -705,7 +724,7 @@ func file_int_engine_new_payload_fastest_proto_init() { return nil } } - file_int_engine_new_payload_fastest_proto_msgTypes[3].Exporter = func(v any, i int) any { + file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*GetIntEngineNewPayloadFastestExecutionByNodeClassRequest); i { case 0: return &v.state @@ -717,7 +736,7 @@ func file_int_engine_new_payload_fastest_proto_init() { return nil } } - file_int_engine_new_payload_fastest_proto_msgTypes[4].Exporter = func(v any, i int) any { + file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes[4].Exporter = func(v any, i int) any { switch v := v.(*GetIntEngineNewPayloadFastestExecutionByNodeClassResponse); i { case 0: return &v.state @@ -734,18 +753,18 @@ func file_int_engine_new_payload_fastest_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_int_engine_new_payload_fastest_proto_rawDesc, + RawDescriptor: file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDesc, NumEnums: 0, NumMessages: 5, NumExtensions: 0, NumServices: 1, }, - GoTypes: file_int_engine_new_payload_fastest_proto_goTypes, - DependencyIndexes: file_int_engine_new_payload_fastest_proto_depIdxs, - MessageInfos: file_int_engine_new_payload_fastest_proto_msgTypes, + GoTypes: file_int_engine_new_payload_fastest_execution_by_node_class_proto_goTypes, + DependencyIndexes: file_int_engine_new_payload_fastest_execution_by_node_class_proto_depIdxs, + MessageInfos: file_int_engine_new_payload_fastest_execution_by_node_class_proto_msgTypes, }.Build() - File_int_engine_new_payload_fastest_proto = out.File - file_int_engine_new_payload_fastest_proto_rawDesc = nil - file_int_engine_new_payload_fastest_proto_goTypes = nil - file_int_engine_new_payload_fastest_proto_depIdxs = nil + File_int_engine_new_payload_fastest_execution_by_node_class_proto = out.File + file_int_engine_new_payload_fastest_execution_by_node_class_proto_rawDesc = nil + file_int_engine_new_payload_fastest_execution_by_node_class_proto_goTypes = nil + file_int_engine_new_payload_fastest_execution_by_node_class_proto_depIdxs = nil } diff --git a/pkg/proto/clickhouse/int_engine_new_payload_fastest_execution_by_node_class.proto b/pkg/proto/clickhouse/int_engine_new_payload_fastest_execution_by_node_class.proto index 2f204214..b34e4dbe 100644 --- a/pkg/proto/clickhouse/int_engine_new_payload_fastest_execution_by_node_class.proto +++ b/pkg/proto/clickhouse/int_engine_new_payload_fastest_execution_by_node_class.proto @@ -32,7 +32,7 @@ message IntEngineNewPayloadFastestExecutionByNodeClass { string meta_client_name = 21; } -// Request for listing int_engine_new_payload_fastest records +// Request for listing int_engine_new_payload_fastest_execution_by_node_class records message ListIntEngineNewPayloadFastestExecutionByNodeClassRequest { // Filter by slot_start_date_time - The wall clock time when the slot started (PRIMARY KEY - required) UInt32Filter slot_start_date_time = 1; @@ -60,7 +60,7 @@ message ListIntEngineNewPayloadFastestExecutionByNodeClassRequest { // Filter by meta_client_name - Name of the client that generated the event (optional) StringFilter meta_client_name = 11; - // The maximum number of int_engine_new_payload_fastest to return. + // The maximum number of int_engine_new_payload_fastest_execution_by_node_class to return. // If unspecified, at most 100 items will be returned. // The maximum value is 10000; values above 10000 will be coerced to 10000. int32 page_size = 12; @@ -73,27 +73,27 @@ message ListIntEngineNewPayloadFastestExecutionByNodeClassRequest { string order_by = 14; } -// Response for listing int_engine_new_payload_fastest records +// Response for listing int_engine_new_payload_fastest_execution_by_node_class records message ListIntEngineNewPayloadFastestExecutionByNodeClassResponse { - // The list of int_engine_new_payload_fastest. - repeated IntEngineNewPayloadFastestExecutionByNodeClass int_engine_new_payload_fastest = 1; + // The list of int_engine_new_payload_fastest_execution_by_node_class. + repeated IntEngineNewPayloadFastestExecutionByNodeClass int_engine_new_payload_fastest_execution_by_node_class = 1; // A token, which can be sent as `page_token` to retrieve the next page. // If this field is omitted, there are no subsequent pages. string next_page_token = 2; } -// Request for getting a single int_engine_new_payload_fastest record by primary key +// Request for getting a single int_engine_new_payload_fastest_execution_by_node_class record by primary key message GetIntEngineNewPayloadFastestExecutionByNodeClassRequest { // The wall clock time when the slot started uint32 slot_start_date_time = 1; // Primary key (required) } -// Response for getting a single int_engine_new_payload_fastest record +// Response for getting a single int_engine_new_payload_fastest_execution_by_node_class record message GetIntEngineNewPayloadFastestExecutionByNodeClassResponse { IntEngineNewPayloadFastestExecutionByNodeClass item = 1; } -// Query int_engine_new_payload_fastest data +// Query int_engine_new_payload_fastest_execution_by_node_class data service IntEngineNewPayloadFastestExecutionByNodeClassService { // List records | Retrieve paginated results with optional filtering rpc List(ListIntEngineNewPayloadFastestExecutionByNodeClassRequest) returns (ListIntEngineNewPayloadFastestExecutionByNodeClassResponse); diff --git a/tests/mainnet/fusaka/models/fct_node_cpu_utilization_by_process.yaml b/tests/mainnet/fusaka/models/fct_node_cpu_utilization_by_process.yaml new file mode 100644 index 00000000..4fc28b50 --- /dev/null +++ b/tests/mainnet/fusaka/models/fct_node_cpu_utilization_by_process.yaml @@ -0,0 +1,78 @@ +model: fct_node_cpu_utilization_by_process +network: mainnet +spec: fusaka +external_data: + observoor_cpu_utilization: + url: https://data.ethpandaops.io/xatu-cbt/mainnet/fusaka/fct_node_cpu_utilization_by_process_observoor_cpu_utilization.parquet + network_column: meta_network_name +assertions: + - name: Row count should be greater than zero + sql: | + SELECT COUNT(*) AS count FROM fct_node_cpu_utilization_by_process FINAL + assertions: + - type: greater_than + column: count + value: 0 + - name: No null wallclock_slot values + sql: | + SELECT COUNT(*) AS count FROM fct_node_cpu_utilization_by_process FINAL WHERE wallclock_slot IS NULL + assertions: + - type: equals + column: count + value: 0 + - name: Wallclock slot should be non-negative + sql: | + SELECT MIN(wallclock_slot) AS min_slot FROM fct_node_cpu_utilization_by_process FINAL + assertions: + - type: greater_than_or_equal + column: min_slot + value: 0 + - name: System cores should be positive + sql: | + SELECT COUNT(*) AS count FROM fct_node_cpu_utilization_by_process FINAL WHERE system_cores <= 0 + assertions: + - type: equals + column: count + value: 0 + - name: Min core pct should not exceed mean core pct + sql: | + SELECT COUNT(*) AS count FROM fct_node_cpu_utilization_by_process FINAL WHERE min_core_pct > mean_core_pct + assertions: + - type: equals + column: count + value: 0 + - name: Mean core pct should not exceed max core pct + sql: | + SELECT COUNT(*) AS count FROM fct_node_cpu_utilization_by_process FINAL WHERE mean_core_pct > max_core_pct + assertions: + - type: equals + column: count + value: 0 + - name: CPU percentages should be non-negative + sql: | + SELECT COUNT(*) AS count FROM fct_node_cpu_utilization_by_process FINAL WHERE min_core_pct < 0 OR mean_core_pct < 0 OR max_core_pct < 0 + assertions: + - type: equals + column: count + value: 0 + - name: Node class should only contain valid values + sql: | + SELECT COUNT(*) AS count FROM fct_node_cpu_utilization_by_process FINAL WHERE node_class NOT IN ('eip7870', '') + assertions: + - type: equals + column: count + value: 0 + - name: No null meta_client_name values + sql: | + SELECT COUNT(*) AS count FROM fct_node_cpu_utilization_by_process FINAL WHERE meta_client_name IS NULL OR meta_client_name = '' + assertions: + - type: equals + column: count + value: 0 + - name: Node class eip7870 matches meta_client_name containing 7870 + sql: | + SELECT COUNT(*) AS count FROM fct_node_cpu_utilization_by_process FINAL WHERE node_class = 'eip7870' AND positionCaseInsensitive(meta_client_name, '7870') = 0 + assertions: + - type: equals + column: count + value: 0 diff --git a/tests/mainnet/pectra/models/fct_block_blob_count_head.yaml b/tests/mainnet/pectra/models/fct_block_blob_count_head.yaml index f1a0b352..f74b9164 100644 --- a/tests/mainnet/pectra/models/fct_block_blob_count_head.yaml +++ b/tests/mainnet/pectra/models/fct_block_blob_count_head.yaml @@ -78,7 +78,7 @@ assertions: value: 0 - name: Blob count should not exceed max blobs per block sql: | - SELECT COUNT(*) AS count FROM fct_block_blob_count_head FINAL WHERE blob_count > 6 + SELECT COUNT(*) AS count FROM fct_block_blob_count_head FINAL WHERE blob_count > 9 assertions: - type: equals column: count diff --git a/tests/mainnet/pectra/models/fct_node_cpu_utilization_by_process.yaml b/tests/mainnet/pectra/models/fct_node_cpu_utilization_by_process.yaml new file mode 100644 index 00000000..17371e22 --- /dev/null +++ b/tests/mainnet/pectra/models/fct_node_cpu_utilization_by_process.yaml @@ -0,0 +1,78 @@ +model: fct_node_cpu_utilization_by_process +network: mainnet +spec: pectra +external_data: + observoor_cpu_utilization: + url: https://data.ethpandaops.io/xatu-cbt/mainnet/pectra/fct_node_cpu_utilization_by_process_observoor_cpu_utilization.parquet + network_column: meta_network_name +assertions: + - name: Row count should be greater than zero + sql: | + SELECT COUNT(*) AS count FROM fct_node_cpu_utilization_by_process FINAL + assertions: + - type: greater_than + column: count + value: 0 + - name: No null wallclock_slot values + sql: | + SELECT COUNT(*) AS null_count FROM fct_node_cpu_utilization_by_process FINAL WHERE wallclock_slot IS NULL + assertions: + - type: equals + column: null_count + value: 0 + - name: No null meta_client_name values + sql: | + SELECT COUNT(*) AS null_count FROM fct_node_cpu_utilization_by_process FINAL WHERE meta_client_name IS NULL OR meta_client_name = '' + assertions: + - type: equals + column: null_count + value: 0 + - name: system_cores should be positive + sql: | + SELECT COUNT(*) AS invalid_count FROM fct_node_cpu_utilization_by_process FINAL WHERE system_cores <= 0 + assertions: + - type: equals + column: invalid_count + value: 0 + - name: mean_core_pct should be between min and max + sql: | + SELECT COUNT(*) AS invalid_count FROM fct_node_cpu_utilization_by_process FINAL WHERE mean_core_pct < min_core_pct OR mean_core_pct > max_core_pct + assertions: + - type: equals + column: invalid_count + value: 0 + - name: min_core_pct should not exceed max_core_pct + sql: | + SELECT COUNT(*) AS invalid_count FROM fct_node_cpu_utilization_by_process FINAL WHERE min_core_pct > max_core_pct + assertions: + - type: equals + column: invalid_count + value: 0 + - name: CPU percentages should be non-negative + sql: | + SELECT COUNT(*) AS invalid_count FROM fct_node_cpu_utilization_by_process FINAL WHERE min_core_pct < 0 OR mean_core_pct < 0 OR max_core_pct < 0 + assertions: + - type: equals + column: invalid_count + value: 0 + - name: node_class should only contain valid values + sql: | + SELECT COUNT(*) AS invalid_count FROM fct_node_cpu_utilization_by_process FINAL WHERE node_class NOT IN ('eip7870', '') + assertions: + - type: equals + column: invalid_count + value: 0 + - name: node_class eip7870 matches meta_client_name containing 7870 + sql: | + SELECT COUNT(*) AS mismatch_count FROM fct_node_cpu_utilization_by_process FINAL WHERE node_class = 'eip7870' AND positionCaseInsensitive(meta_client_name, '7870') = 0 + assertions: + - type: equals + column: mismatch_count + value: 0 + - name: wallclock_slot_start_date_time should not be in the future + sql: | + SELECT COUNT(*) AS future_count FROM fct_node_cpu_utilization_by_process FINAL WHERE wallclock_slot_start_date_time > now() + INTERVAL 1 HOUR + assertions: + - type: equals + column: future_count + value: 0