Build analytics¶
Beta
This feature is currently in beta. Contact EngFlow if you'd like to use it.
EngFlow captures build performance data for every remotely executed invocation. While this data is surfaced in the Build and Test UI as the EngFlow Profile, build analytics makes this data available as a queryable data store for you to extract powerful build performance insights. You can query the data directly using tools like DuckDB, or stream it to Snowflake via Snowpipe Streaming.
Queryable build data deepens your visibility into:
- Build health information
- Action-level metrics
- Build trends over a period of time that's significant to your organization.
Data schema¶
EngFlow build analytics records data from the Remote Execution API v2 (REAPI) as rows in an Apache Iceberg table. If your EngFlow RE cluster is deployed on AWS, this data is stored in AWS’s S3 Tables. If your cluster is deployed on GCP, this data is stored in a GCS bucket, leveraging the invocation index database as the Iceberg catalog. This data can also be streamed to your Snowflake account via Snowpipe Streaming.
See Iceberg table schema for the full schema.
Enabling build analytics for your cluster¶
Contact EngFlow to enable build analytics for your cluster.
Please note that enabling build analytics will result in a small increase in your cloud costs. We recommend monitoring the associated cost during the first 30 days of usage.
Querying build analytics data¶
This section describes how to query your cluster's build analytics data, including the access and tooling you need to get started. Note that these instructions use DuckDB to query the database. You may use a similar tool of your choice. If your organization uses Snowflake, see Streaming to Snowflake.
Step 1: Install prerequisite tooling and verify access¶
-
Make sure you have the following core tools installed:
- Python 3.14 or above
- A Python package manager like
uvorpip.
-
Install required dependencies. The
requirements.txtfile below lists the required packages. Create a copy of this file in the directory where you'll be running your queries: -
Run
uv syncto install the dependencies. -
Install the AWS CLI.
-
Make sure you can access S3 tables.
Step 2: Create a Jupyter Notebook¶
Using Jupyter Notebook in an IDE
You can do this step in an IDE like Visual Studio Code. If using an IDE, select the Python interpreter from the virtual environment created by uv as your notebook kernel. This ensures the notebook has access to all installed dependencies.
Start Jupyter Notebook and create a notebook named engflow_analytics.ipynb. Then, create the following cells in your notebook:
# Install and load the Iceberg extension for DuckDB
# This enables DuckDB to read Apache Iceberg table format
duckdb.sql("INSTALL iceberg; LOAD ICEBERG")
# Export temporary AWS credentials for the specified cluster profile
# Update cluster name and region
credentials = !aws configure export-credentials --profile <your-cluster-name> --region us-east-1 --format process
credentials = json.loads(''.join(credentials))
print(f'These credentials will expire on {credentials["Expiration"]} and need to be refreshed.')
# Find the S3 Tables bucket ARN that contains observability data
aws_arn = !aws --profile <your-cluster-name> s3tables list-table-buckets
table_bucket_result = json.loads(''.join(aws_arn))['tableBuckets']
table_bucket = [x['arn'] for x in table_bucket_result if '-observability' in x['name']][0]
table_bucket
# Create a local DuckDB table from the remote executions table
# This is optional but can improve query performance for repeated queries
# It can take a long time to cold start if scanning over large data sets
# We recommend filtering this data to applicable data ranges
duckdb.sql("""
CREATE OR REPLACE TABLE executions AS
SELECT * FROM s3_tables.observability.executions;
""")
Step 3: Run a test query¶
To verify your setup, run a query to get the number of test executions that ran yesterday:
# Update the database name, schema, and table name
a = duckdb.sql("""
SELECT COUNT(*) as test_that_run_yesterday
FROM <database>.<schema>.<table>
WHERE start_timestamp_day = CURRENT_DATE() - INTERVAL 1 DAY
AND action_mnemonic = 'TestRunner'
""").to_df()
If you see a result showing the number of test executions, your setup is working as expected.
Step 1: Install prerequisite tooling and verify access¶
-
Make sure you have the following core tools installed:
- Python 3.14 or above
- A Python package manager like
uvorpip.
-
Install required dependencies. The
requirements.txtfile below lists the required packages. Create a copy of this file in the directory where you'll be running your queries:requirements.txt -
Run
uv syncto install the dependencies. -
Install the Google Cloud CLI.
-
Make sure you can access BigQuery datasets.
Step 2: Create a Jupyter Notebook¶
Using Jupyter Notebook in an IDE
You can do this step in an IDE like Visual Studio Code. If using an IDE, select the Python interpreter from the virtual environment created by uv as your notebook kernel. This ensures the notebook has access to all installed dependencies.
Start Jupyter Notebook and create a notebook named engflow_analytics.ipynb. Then, create the following cells in your notebook:
# Import required libraries
import duckdb
import pandas as pd
import plotly.express as px
import pyarrow
# Authenticate with Google Cloud using application default credentials
! gcloud auth application-default login
# Initialize BigQuery client to query the analytics dataset
from google.cloud import bigquery
bq = bigquery.Client()
# Update your project ID
client = bigquery.Client(project='my-project-id-123abc456')
Step 3: Run a test query¶
To verify your setup, run a query to get the number of test executions that ran yesterday:
# Query BigQuery to count test executions from yesterday
# Update the project ID, dataset name, and table name
jb = client.query_and_wait("""
SELECT COUNT(*) as test_that_run_yesterday
FROM `<projectId>.<datasetName>.<tableName>`
WHERE start_timestamp_day = CURRENT_DATE() - INTERVAL 1 DAY
AND action_mnemonic = 'TestRunner'
""")
# Convert query results to a pandas DataFrame for analysis
jb.to_dataframe()
If you see a result showing the number of test executions, your setup is working as expected.
Streaming to Snowflake¶
If your organization uses Snowflake, you can stream EngFlow build analytics data directly to your Snowflake account via Snowpipe Streaming. This lets you query execution data using Snowflake SQL and integrate it with your existing Snowflake workflows.
Schema differences¶
The build analytics data streamed to Snowflake uses the same underlying schema as the Iceberg table, but the fields are structured differently. Instead of top-level fields, there is a single top-level column called execution that contains a semi-structured object. This execution object holds all of the remaining fields, including nested objects.
For example, to query target_id in Iceberg you'd run:
In Snowflake SQL, it becomes:
Set up Snowflake streaming¶
Step 1: Set up Snowflake objects¶
Existing Snowflake account required
The following instructions assume that you have an existing Snowflake account with billing enabled.
Create the following objects in your Snowflake account. Names shown in the code sample are suggestions and you can customize them, except for the table's column, which must be called execution.
Step 2: Create secrets in your cloud provider¶
Create two secrets in the cloud provider console where you administer your EngFlow cluster:
These secrets can have any name.
Create Snowflake config secret¶
The Snowflake config secret is a JSON object. All fields are required. In this example, the secret is named snowflake-observability-config.
Note
- The
clientandchannelvalues are arbitrary names used to identify the connection. They don't need to be pre-configured in Snowflake. - The
database,schema, andexecutions_pipevalues should match the objects created in Step 1. - The table name does not appear in this config, since writes happen via the pipe.
- The
accountvalue must match the account identifier in theuri(e.g.,AAA-BBB123inhttps://AAA-BBB123.snowflakecomputing.com:443).
Create a private key secret¶
Store the full private key as the second secret. The key must be unencrypted (no passphrase). See Snowflake's key pair auth docs for how to generate one. In this example, the secret is named snowflake-observability-auth-private-key.
Step 3: Share secret names with EngFlow¶
Once you've created the secrets, contact EngFlow and share the names of the Snowflake config and private key secrets so that we can configure your cluster to stream execution data to Snowflake. In this example, you'd share the following secret names: snowflake-observability-config and snowflake-observability-auth-private-key.
Next steps¶
Now that you've verified your setup, you can:
- Explore the full Iceberg table schema.
- Create custom queries to analyze your build performance.
- Set up automated reports using the queried data.
- Stream data to Snowflake if your organization uses Snowflake for analytics.