feat(consumoor): add table route implementations, tests, and local dev infra #1524
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Sentry Smoke Test | |
| on: | |
| pull_request: | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| sentry-smoke-test: | |
| timeout-minutes: 10 | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| - name: Install dependencies | |
| run: | | |
| # Install clickhouse client | |
| sudo apt-get install -y apt-transport-https ca-certificates curl gnupg | |
| curl -fsSL 'https://packages.clickhouse.com/rpm/lts/repodata/repomd.xml.key' | sudo gpg --dearmor -o /usr/share/keyrings/clickhouse-keyring.gpg | |
| echo "deb [signed-by=/usr/share/keyrings/clickhouse-keyring.gpg] https://packages.clickhouse.com/deb stable main" | sudo tee \ | |
| /etc/apt/sources.list.d/clickhouse.list | |
| sudo apt-get update | |
| sudo apt-get install -y clickhouse-client | |
| clickhouse-client --version | |
| # Install yq for YAML parsing | |
| sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 | |
| sudo chmod +x /usr/local/bin/yq | |
| yq --version | |
| - name: Canary health check on beacon node | |
| id: canary | |
| run: | | |
| BEACON_NODE="https://mainnet-lb-bn.utility.production.platform.ethpandaops.io" | |
| echo "Checking beacon node health at $BEACON_NODE..." | |
| HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 \ | |
| -H "Authorization: ${{ secrets.PLATFORM_UTILITY_NODE_AUTHORIZATION_2 }}" \ | |
| "$BEACON_NODE/eth/v1/node/health" || echo "000") | |
| if [ "$HTTP_CODE" -lt 200 ] || [ "$HTTP_CODE" -ge 400 ]; then | |
| echo "::warning::Beacon node unreachable (HTTP $HTTP_CODE). Skipping sentry smoke test." | |
| echo "skip=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "Beacon node is healthy (HTTP $HTTP_CODE)." | |
| echo "skip=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Pull docker compose images in the background | |
| if: steps.canary.outputs.skip != 'true' | |
| run: | | |
| docker compose pull & | |
| - name: Build xatu image | |
| if: steps.canary.outputs.skip != 'true' | |
| run: | | |
| docker build -t ethpandaops/xatu:local . | |
| echo "Xatu image is built." | |
| - name: Build sentry-logs image | |
| if: steps.canary.outputs.skip != 'true' | |
| run: | | |
| docker build -t ethpandaops/xatu-sentry-logs:local ./sentry-logs | |
| echo "Sentry-logs image is built." | |
| - name: Create sentry-logs directory and log file | |
| if: steps.canary.outputs.skip != 'true' | |
| run: | | |
| mkdir -p deploy/local/docker-compose/sentry-logs/logs | |
| chmod 777 deploy/local/docker-compose/sentry-logs/logs | |
| touch deploy/local/docker-compose/sentry-logs/logs/geth.log | |
| chmod 666 deploy/local/docker-compose/sentry-logs/logs/geth.log | |
| - name: Run Xatu stack | |
| if: steps.canary.outputs.skip != 'true' | |
| timeout-minutes: 5 | |
| run: | | |
| docker compose up --build --detach --quiet-pull | |
| - name: Inject sentry-logs test data | |
| if: steps.canary.outputs.skip != 'true' | |
| run: | | |
| echo "Injecting fake log entries early so they process in background..." | |
| # Format 1: Raw JSON (geth format from PR #33655) | |
| for i in {1..5}; do | |
| echo '{"level":"warn","msg":"Slow block","block":{"number":'${i}',"hash":"0x'$(printf '%064d' ${i})'","gas_used":15000000,"tx_count":150},"timing":{"execution_ms":45.2,"state_read_ms":12.1,"state_hash_ms":8.3,"commit_ms":5.4,"total_ms":71.0},"throughput":{"mgas_per_sec":211.27},"state_reads":{"accounts":1234,"storage_slots":5678,"code":89,"code_bytes":45000},"state_writes":{"accounts":234,"accounts_deleted":5,"storage_slots":890,"storage_slots_deleted":12,"code":3,"code_bytes":15000},"cache":{"account":{"hits":1000,"misses":234,"hit_rate":81.0},"storage":{"hits":5000,"misses":678,"hit_rate":88.0},"code":{"hits":80,"misses":9,"hit_rate":89.9,"hit_bytes":40000,"miss_bytes":5000}}}' >> deploy/local/docker-compose/sentry-logs/logs/geth.log | |
| done | |
| # Format 2: Terminal format (--log.format terminal, geth default) | |
| for i in {6..10}; do | |
| echo 'WARN [01-28|12:58:41.123] {"level":"warn","msg":"Slow block","block":{"number":'${i}',"hash":"0x'$(printf '%064d' ${i})'","gas_used":15000000,"tx_count":150},"timing":{"execution_ms":45.2,"state_read_ms":12.1,"state_hash_ms":8.3,"commit_ms":5.4,"total_ms":71.0},"throughput":{"mgas_per_sec":211.27},"state_reads":{"accounts":1234,"storage_slots":5678,"code":89,"code_bytes":45000},"state_writes":{"accounts":234,"accounts_deleted":5,"storage_slots":890,"storage_slots_deleted":12,"code":3,"code_bytes":15000},"cache":{"account":{"hits":1000,"misses":234,"hit_rate":81.0},"storage":{"hits":5000,"misses":678,"hit_rate":88.0},"code":{"hits":80,"misses":9,"hit_rate":89.9,"hit_bytes":40000,"miss_bytes":5000}}}' >> deploy/local/docker-compose/sentry-logs/logs/geth.log | |
| done | |
| # Format 3: Logfmt format (--log.format logfmt) | |
| for i in {11..15}; do | |
| echo 't=2026-01-28T12:58:41+0000 lvl=warn msg="{\"level\":\"warn\",\"msg\":\"Slow block\",\"block\":{\"number\":'${i}',\"hash\":\"0x'$(printf '%064d' ${i})'\",\"gas_used\":15000000,\"tx_count\":150},\"timing\":{\"execution_ms\":45.2,\"state_read_ms\":12.1,\"state_hash_ms\":8.3,\"commit_ms\":5.4,\"total_ms\":71.0},\"throughput\":{\"mgas_per_sec\":211.27},\"state_reads\":{\"accounts\":1234,\"storage_slots\":5678,\"code\":89,\"code_bytes\":45000},\"state_writes\":{\"accounts\":234,\"accounts_deleted\":5,\"storage_slots\":890,\"storage_slots_deleted\":12,\"code\":3,\"code_bytes\":15000},\"cache\":{\"account\":{\"hits\":1000,\"misses\":234,\"hit_rate\":81.0},\"storage\":{\"hits\":5000,\"misses\":678,\"hit_rate\":88.0},\"code\":{\"hits\":80,\"misses\":9,\"hit_rate\":89.9,\"hit_bytes\":40000,\"miss_bytes\":5000}}}"' >> deploy/local/docker-compose/sentry-logs/logs/geth.log | |
| done | |
| echo "Injected 15 test log entries (5 raw JSON, 5 terminal, 5 logfmt)" | |
| - name: Create sentry config | |
| if: steps.canary.outputs.skip != 'true' | |
| run: | | |
| NETWORK_NAME=$(yq '.network.name' .github/sentry/seeding.yaml) | |
| cat <<EOF > /tmp/sentry_config.yaml | |
| logging: debug | |
| name: sentry-smoke-test | |
| labels: | |
| ethpandaops: rocks | |
| ntpServer: time.google.com | |
| ethereum: | |
| beaconNodeAddress: "https://mainnet-lb-bn.utility.production.platform.ethpandaops.io" | |
| beaconNodeHeaders: | |
| Authorization: "AUTH_HEADER" | |
| overrideNetworkName: "$NETWORK_NAME" | |
| beaconSubscriptions: | |
| - head | |
| - block | |
| - attestation | |
| - contribution_and_proof | |
| - finalized_checkpoint | |
| beaconCommittees: | |
| enabled: false | |
| proposerDuty: | |
| enabled: false | |
| forkChoice: | |
| enabled: false | |
| attestationData: | |
| enabled: false | |
| outputs: | |
| - name: xatu | |
| type: xatu | |
| config: | |
| address: xatu-server:8080 | |
| tls: false | |
| maxQueueSize: 51200 | |
| batchTimeout: 1s | |
| exportTimeout: 30s | |
| maxExportBatchSize: 512 | |
| EOF | |
| - name: Set authorization header | |
| if: steps.canary.outputs.skip != 'true' | |
| run: | | |
| sed -i 's/AUTH_HEADER/${{ secrets.PLATFORM_UTILITY_NODE_AUTHORIZATION_2 }}/' /tmp/sentry_config.yaml | |
| - name: Start sentry | |
| if: steps.canary.outputs.skip != 'true' | |
| run: | | |
| docker run -d --network xatu_xatu-net --name xatu-sentry -v /tmp/sentry_config.yaml:/etc/xatu/config.yaml ethpandaops/xatu:local sentry --config /etc/xatu/config.yaml | |
| - name: Wait for sentry to start | |
| if: steps.canary.outputs.skip != 'true' | |
| run: | | |
| sleep 5 | |
| docker logs xatu-sentry | |
| - name: Verify ClickHouse has sentry data | |
| if: steps.canary.outputs.skip != 'true' | |
| timeout-minutes: 7 | |
| env: | |
| SENTRY_NAME: sentry-smoke-test | |
| run: | | |
| .github/sentry/assert_clickhouse.sh .github/sentry/seeding.yaml | |
| - name: Verify sentry-logs (execution_block_metrics) pipeline | |
| if: steps.canary.outputs.skip != 'true' | |
| timeout-minutes: 3 | |
| run: | | |
| echo "Testing sentry-logs execution_block_metrics pipeline" | |
| echo "Log data was injected earlier and should have been processing in background." | |
| # Debug: show sentry-logs container logs | |
| echo "=== sentry-logs container logs ===" | |
| docker logs xatu-sentry-logs 2>&1 | tail -30 || echo "Container not found or no logs" | |
| # Wait for data to reach ClickHouse | |
| max_retries=30 | |
| retry_count=0 | |
| while true; do | |
| data_count=$(docker exec xatu-clickhouse-01 clickhouse-client --query "SELECT COUNT(*) FROM default.execution_block_metrics" 2>/dev/null || echo "0") | |
| if [[ "$data_count" -ge 15 ]]; then | |
| echo "SUCCESS: execution_block_metrics has $data_count entries" | |
| break | |
| fi | |
| echo "Waiting for execution_block_metrics data... (current: $data_count, attempt: $((retry_count + 1))/$max_retries)" | |
| retry_count=$((retry_count + 1)) | |
| if [[ $retry_count -ge $max_retries ]]; then | |
| echo "FAILED: Timeout waiting for execution_block_metrics data" | |
| echo "=== Final sentry-logs logs ===" | |
| docker logs xatu-sentry-logs 2>&1 | tail -100 || echo "Container not found" | |
| echo "=== Final xatu-server logs ===" | |
| docker logs xatu-server 2>&1 | tail -50 || echo "Container not found" | |
| echo "=== Kafka topics ===" | |
| docker exec xatu-kafka kafka-topics --list --bootstrap-server localhost:9092 2>/dev/null | grep execution || echo "No execution topics" | |
| exit 1 | |
| fi | |
| sleep 5 | |
| done | |
| # Verify data content | |
| echo "Sample execution_block_metrics data:" | |
| docker exec xatu-clickhouse-01 clickhouse-client --query "SELECT block_number, total_ms, mgas_per_sec, meta_client_name FROM default.execution_block_metrics LIMIT 5" | |
| - name: Collect docker logs on failure | |
| if: failure() | |
| uses: jwalton/gh-docker-logs@2741064ab9d7af54b0b1ffb6076cf64c16f0220e # v2.2.2 | |
| with: | |
| dest: './logs' | |
| - name: Tar logs | |
| if: failure() | |
| run: tar cvzf ./logs.tgz ./logs | |
| - name: Upload logs to GitHub | |
| if: failure() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: logs.tgz | |
| path: ./logs.tgz |