Query
Use rainlytics query for an ad-hoc SQL query over the raw access logs. It runs through the
Rainlytics Athena workgroup and prints every result row.
rainlytics query "SELECT cs_uri_stem, count(*) AS views FROM cloudfront_logs WHERE year = '2026' AND month = '09' AND day = '01' GROUP BY 1 ORDER BY 2 DESC LIMIT 5"Quote the SQL as one shell argument.
Select the deployed resources
Section titled “Select the deployed resources”The defaults use database rainlytics, table cloudfront_logs and workgroup rainlytics.
rainlytics query "SELECT count(*) FROM cloudfront_logs" \ --region us-east-1 \ --database rainlytics \ --workgroup rainlyticsCredentials and default region come from the AWS SDK credential chain. The selected region must contain the workgroup and Glue table. Keep the table in the log bucket’s region to avoid cross-region S3 transfer on every query.
Always restrict partitions
Section titled “Always restrict partitions”Athena charges by bytes scanned. For an hourly table, restrict distributionid, year, month,
day and hour where possible.
SELECT count(*)FROM cloudfront_logsWHERE distributionid = 'E1EXAMPLE1234' AND year = '2026' AND month = '09' AND day = '01' AND hour IN ('13', '14')A partition condition tells Athena which S3 paths to read. Conditions on timestamp_ms, path or
status only filter rows within those paths. Use timestamp bounds for an exact time range as well
as partition conditions to limit the scan.
The workgroup stops a query that passes its byte limit. Athena charges for bytes read before a
cancelled query stops. Narrow the partitions or raise bytesScannedCutoff when a legitimate report
needs more data.
Read CloudFront values
Section titled “Read CloudFront values”Every column is stored as text. Cast numbers and timestamps in SQL. CloudFront uses - for missing
values and percent-encodes logged fields.
SELECT from_unixtime(cast(timestamp_ms AS bigint) / 1000) AS requested_at, cast(sc_status AS integer) AS status, nullif(cs_referer, '-') AS referrer, url_decode(cs_uri_stem) AS pathFROM cloudfront_logsWHERE year = '2026' AND month = '09' AND day = '01'See Log table for field-name mapping.
Cost and output
Section titled “Cost and output”After each query, standard error reports the query ID, workgroup, region, bytes scanned, duration and estimated cost. Result rows go to standard output.
rainlytics query "SELECT c_country, count(*) AS views FROM cloudfront_logs WHERE year = '2026' AND month = '09' GROUP BY 1" | jq '.[0]'Use --output json, csv or table. Rainlytics fetches all pages of Athena results. Add a SQL
LIMIT to restrict the output. Keep partition conditions to restrict the scan cost.
Permissions
Section titled “Permissions”The caller needs Athena access to the workgroup, Glue reads for the catalog and table, S3 reads on the log bucket, and S3 reads and writes on the results bucket.
Grant these permissions from CDK:
workgroup.grantQuerying(role, table);