Class: GitlabQuality::TestTooling::CodeCoverage::ClickHouse::PerTestCoverageTable
- Inherits:
-
Table
- Object
- Table
- GitlabQuality::TestTooling::CodeCoverage::ClickHouse::PerTestCoverageTable
- Defined in:
- lib/gitlab_quality/test_tooling/code_coverage/click_house/per_test_coverage_table.rb
Overview
Inserts per-test, per-source-file line-set coverage rows into ‘code_coverage.test_coverage_per_file`. The `covered_lines` column is `AggregateFunction(groupBitmap, UInt32)` so JSONEachRow can’t carry it; rows go in via raw ‘INSERT … VALUES` statements wrapping `bitmapBuild(CAST([line, …] AS Array(UInt32)))` per row.
Dedup across runs is handled by the table’s ‘SharedReplacingMergeTree(version)` engine on `(ci_project_path, test_file, source_file)` ORDER BY. Within a single run, callers must pre-aggregate at the (test_file, source_file) grain before pushing: multiple examples within the same test_file should be unioned into one row by the loader, not handed in as duplicates.
Constant Summary collapse
- TABLE_NAME =
"test_coverage_per_file"- BATCH_SIZE =
500- MAX_LINE_NUMBER =
Intentionally generous ceiling on line numbers. Real source files are thousands of lines; generated artifacts (large GraphQL schemas, bundled JS, JSON manifests) can run past 100k. The cap is set to flag clearly bogus values (negative, garbage casts, anything past ~1M) without rejecting realistic generated files. ClickHouse’s UInt32 ceiling is ~4.3B, so we still have orders of magnitude of headroom above this. Tighten only with evidence.
1_000_000
Instance Method Summary collapse
Methods inherited from Table
Constructor Details
This class inherits a constructor from GitlabQuality::TestTooling::CodeCoverage::ClickHouse::Table
Instance Method Details
#push(data) ⇒ void
This method returns an undefined value.
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/gitlab_quality/test_tooling/code_coverage/click_house/per_test_coverage_table.rb', line 40 def push(data) # rubocop:disable Metrics/AbcSize return logger.warn("#{LOG_PREFIX} No data found, skipping ClickHouse export!") if data.empty? logger.debug("#{LOG_PREFIX} Starting per-test coverage export to ClickHouse") sanitized_data = sanitize(data) return logger.warn("#{LOG_PREFIX} No valid data found after sanitization, skipping ClickHouse export!") if sanitized_data.empty? total_batches = (sanitized_data.size.to_f / BATCH_SIZE).ceil sanitized_data.each_slice(BATCH_SIZE).with_index do |batch, index| logger.debug("#{LOG_PREFIX} Pushing batch #{index + 1} of #{total_batches} (#{batch.size} rows)") client.query(build_insert_sql(batch), format: "TabSeparated") end logger.info("#{LOG_PREFIX} Successfully pushed #{sanitized_data.size} records to #{full_table_name}") rescue StandardError => e logger.error("#{LOG_PREFIX} Error occurred while pushing data to #{full_table_name}: #{e.}") raise end |