위의 쿼리문에서 다른것은 수정할 것 없이 `LOCATION` 뒤의 s3 버킷 주소만 자신의 버킷에 맞게 수정해주면 됩니다.
이렇게 테이블 정의를 하고 나면 필요에 따라 쿼리를 날려 CF로그를 분석 할 수 있습니다. CF Cache Statistics 등에서도 통계를 제공해주기 때문에 통계에 관한 쿼리가 별로 필요하지 않을 수도 있지만, 따로 대시보드를 구성해 시각화 툴과 연계한다던가 할때는 필요할만한 것들을 모아봤습니다. Troubleshooting이 필요할 때는 그때그때 상황에 맞게 쿼리를 해야해서 예시를 들기가 어렵네요. 아래 예시 쿼리들은 참고만 하시고 필요에 맞게 변경해서 사용하시기 바랍니다.
SELECT response_result_type, count(*) as cnt FROM "sample_db"."cloudfront_logs" GROUPBY response_result_type ORDERBY cnt DESC;
에러의 응답 코드 별 조회
1 2 3 4 5 6 7 8 9 10
SELECT status, count(*) as cnt FROM "sample_db"."cloudfront_logs" WHERE result_type ='Error' GROUPBY status ORDERBY cnt DESC;
상위 20개 에러(4XX,5XX) uri
1 2 3 4 5 6 7 8 9 10 11
SELECT uri, count(*) as cnt FROM "sample_db"."cloudfront_logs" WHERE result_type ='Error' GROUPBY uri ORDERBY cnt DESC limit 20;
상위 20개 요청ip count
1 2 3 4 5 6 7 8
SELECT request_ip, COUNT(*) AS cnt FROM cloudfront_logs GROUPBY request_ip ORDERBY cnt DESC;
상위 20 Referrer Count
1 2 3 4 5 6 7 8 9
SELECT referrer, count(*) as cnt FROM "sample_db"."cloudfront_logs" GROUPBY referrer ORDERBY cnt DESC LIMIT 20;
시계열 분석 예시
시계열 분석을 위해서는 기본 테이블에 저장된 date, time의 데이터를 concat(), from_iso8601_timestamp(), date_trunc() 등을 이용해 변환해주어야 합니다. Athena는 Select 절에서 Alias가 잘 만들어지지 않아서 cte를 쓰는 편이 편합니다.
CTE 예시
1 2 3 4
WITH cte AS ( SELECT from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time)) AS ts FROM "sample_db"."cloudfront_logs" )
5월 29일(UTC 기준) 시간별 요청수, 오름차순
1 2 3 4 5 6 7 8 9 10 11 12 13
WITH cte AS ( SELECT from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time)) AS ts FROM "sample_db"."cloudfront_logs" )SELECT date_trunc('hour',ts) asTIME, count(*) as CNT FROM cte WHERE ts >= from_iso8601_timestamp('2019-05-29T00:00:00') AND ts < from_iso8601_timestamp('2019-05-30T00:00:00') GROUPBY date_trunc('hour',ts) ORDERBY date_trunc('hour',ts);
5월 29일(UTC 기준) 시간별 전송량(Gb)
WITH cte AS (
SELECT from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time)), bytesAS ts
FROM"sample_db"."cloudfront_logs"
)SELECT
date_trunc('hour',ts) asTIME, sum(bytes)/1024/1024/1024as Gb
FROM cte
WHERE
ts >= from_iso8601_timestamp('2019-05-29T00:00:00')AND
ts < from_iso8601_timestamp('2019-05-30T00:00:00')
GROUPBY
date_trunc('hour',ts)
ORDERBY
date_trunc('hour',ts);
5월 29일(UTC 기준) 시간별 에러수
WITH cte AS (
SELECT from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time)) AS ts
FROM"sample_db"."cloudfront_logs"
)SELECT
date_trunc('hour',ts) asTIME, count(*) as CNT
FROM
cte
WHERE
ts >= from_iso8601_timestamp('2019-05-29T00:00:00') AND
ts < from_iso8601_timestamp('2019-05-30T00:00:00') AND
result_type = 'Error'GROUPBY
date_trunc('hour',ts)
ORDERBY
date_trunc('hour',ts);
시간별 평균 전송시간
WITH cte AS (
SELECT from_iso8601_timestamp(concat(concat(date_format(date, '%Y-%m-%d'), 'T'), time)) AS ts, time_taken
FROM"sample_db"."cloudfront_logs"
)SELECT
date_trunc('hour',ts) asTIME, avg(time_taken) as avg_time
FROM cte
WHERE
ts >= from_iso8601_timestamp('2018-05-29T00:00:00') AND
ts < from_iso8601_timestamp('2019-05-30T00:00:00')
GROUPBY
date_trunc('hour',ts)
ORDERBY
date_trunc('hour',ts);
주의할 점
Athena는 스캔한 데이터의 양에 비례해서 과금이 됩니다. 그런데 Cloudfront Log는 보통 양이 상당히 많은데도 데이터가 파티셔닝되지 않고 하나의 버킷에 통째로 저장이 되죠. 결국 Cloudfront의 Log 양이 상당해지면 Athena가 스캔하는 데이터의 양도 늘어나고 그러면 성능도 느려지겠죠.
따라서 데이터의 양이 많아지는 경우, 파티셔닝을 고려해봐야 합니다. 여기 AWS 블로그에서 Cloudfront로그를 파티셔닝하고, 파싱해서 더 많은 정보를 부여 (예를들어, bot인지 아닌지 여부를 판단해서 isBot이라는 column을 추가)하는 예제를 만들어 놓았네요. 따라해보진 않았지만 꽤 유용할것 같습니다. 글이 포스팅된지 꽤 된것 같은데 한국어로 번역된글도 없는걸 보니 한번 따라해보면서 번역글을 작성해도 괜찮겠네요.