Skip to content

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.

Terminal window
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.

The defaults use database rainlytics, table cloudfront_logs and workgroup rainlytics.

Terminal window
rainlytics query "SELECT count(*) FROM cloudfront_logs" \
--region us-east-1 \
--database rainlytics \
--workgroup rainlytics

Credentials 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.

Athena charges by bytes scanned. For an hourly table, restrict distributionid, year, month, day and hour where possible.

SELECT count(*)
FROM cloudfront_logs
WHERE 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.

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 path
FROM cloudfront_logs
WHERE year = '2026' AND month = '09' AND day = '01'

See Log table for field-name mapping.

After each query, standard error reports the query ID, workgroup, region, bytes scanned, duration and estimated cost. Result rows go to standard output.

Terminal window
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.

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);