AWS Infra

[ AWS ] Python boto3를 이용하여 s3 log 압축파일(gz) DataFrame 만들기 - CloudFront Logs

Pydole 2023. 3. 16. 12:36

 

AWS CloudFront, WAF 등 S3에 저장된 log들은 최종 gz 압축 형태로 보관 된다. 

주기적이고, 빠르게 모니터링하고 분석하기 위해서 Python SDK를 이용하여 자동화 할 수 있는 방법을 알아본다.

 


 

S3 버킷에 저장된 object 다운로드

 

 Python boto3를 이용하여 S3에서 파일을 다운로드 한다. 일반적으로 날짜 Prefix가 들어가기 때문에 datetime 모듈을 이용하여 일괄 다운로드 받을 수 있으며, 아래에서는 단일 파일만 대상으로 테스트 해본다.

 

CloudFront 로그가 S3에 저장되어 있고, xxxx.2023-03-15-01.xxxx.gz 라는 압축파일을 다운로드

 

import boto3

client = boto3.client('s3')

saveFile = 'xxxx.2023-03-15-01.xxxx.gz'
bucket = 'bucket-name'
key = 'xxxx.2023-03-15-01.xxxx.gz'


# key : Local File
# saveFile : S3 object,  object는 파일이다.

client.download_file(bucket, key, saveFile)

 

 

 만약 날짜 Prefix 로 모두 다운로드 받으려면 list_objects 메소드를 이용하여 파일을 목록을 리스트 하면 된다.

 

prefix = 'xxxxxx.2023-03-'
bucket = 'bucket-name'

res = client.list_objects(Bucket=bucket, Prefix=prefix)

filelist = []

for i in [ filename['Key'] for filename in res['Contents']]:
        filelist.append(i)
        
        
 # filename['Key']는 다운로드 파일명

 


 

 

gzip 모듈을 이용하여 압축파일에 내용 읽기

 

 

import gzip
import pandas as pd

with gzip.open(saveFile,'rb') as f:
    data = f.readlines()
    
data = [ x.decode() for x in data ]  # Byte형이기 때문에 decode()
col = data[1].split()[1:]    # 컬럼 리스트
data = [ x.split('\t') for x in data[1:]]  # 데이터 리스트

 

 

 

CloudFront 컬럼 (col) 리스트를 보면 총 33개의 필드로 구성되어 있다.

컬럼명과 데이터의 길이 (len) 가 서로 맞아야 DataFrame에온전히 넣을 수 있겠다.

 

 


 

DataFrame으로 변환

 

pandas 모듈을 이용하여  DataFrame으로 변환한다.

 

df = pd.DataFrame(data[1:],columns=col)
df

 

 

정상적으로 만들어 졌다면 아래와 같이 만들어 졌을 것이다.

 

 

 


 

모니터링 활용

 

 

 

Pandas 이용한 시계열 scbytes 통계보기 ( resample을 이용하여 시간대별 Download 양 보기 )

 

# 컬럼에 -는 _로 대체하였다.

df.columns = df.columns.str.replace('-','_')


# sc_bytes는 집계를 해야하기 때문에 int로 형변환

df['sc_bytes'] = df['sc_bytes'].astype(int)


# logtime 이라는 컬럼을 만들고, 한국시간 UTC +9000으로 조정하여, Index 지정
df['logtime'] = pd.DatetimeIndex(df['date'] + ' ' + df['time']) + timedelta(hours=9)
df = df.set_index('logtime')


# resample 메소드를 이용하여 1시간당 집계. (용량 : G)

df_resamped = df.resample('1H', closed='left', label='left', base=0).sum() / 1000000000
df_resamped

 

 

 

 

 

 

Kibana의 heatmap을 이용한 시계열 콘텐츠별 Download 시각화

 

cloudfront scbytes heatmap