Ruby AWS CloudFront log 分析及 Zlib 使用问题?

eva · 2013年12月09日 · 最后由 eva 回复于 2013年12月10日 · 3731 次阅读

我目前使用的下载服务是 aws 的 s3 和 cloudfront(英文网站针对国外用户),但 aws 没有提供下载次数的统计。于是我的想法是写个脚本每天去下载前一天的 cloudfront 的 log(使用 gem aws-sdk),再处理分析得到下载次数。使用 ruby 1.8.7,代码如下:

require 'rubygems'
require 'aws'
require 'active_support/all'
require 'zlib'

AWS.config({
  :access_key_id => 'XXXXX',
  :secret_access_key => 'XXXXX',
  :region => "XXX"
})

date = Date.today - 1.days
date_fmt = date.strftime("%Y-%m-%d")

s3 = AWS::S3.new
bucket = s3.buckets['XXXX-download']
@objs = bucket.objects.with_prefix('cflog').select { |o| o.key =~ Regexp.new(date_fmt)}

logs_file = "logs/#{date_fmt}.gz"

File.open(logs_file, "wb") do |file|
    @objs.each do |obj|
        obj.read do |chunk|
            file.write(chunk)
        end
    end
end

result = {}
Zlib::GzipReader.open(logs_file) do |gz|
    gz.each_line do |line|
        if match = /\tGET\t\S+\t\/(\S+)\t200\t\S+\t\S+\t\S+\t\S+\tHit\t/i.match(line)
            result[match[1]] = result[match[1]] ? result[match[1]] + 1 : 1
        end     
    end
end

p result

cloudfront 的 log 是.gz 格式的,每天大概有好几万条 log,且每条 log 都只有几百个字节,因此我是先将前一天的所有 Log 下载下来合并成一个.gz 文件,再用 Zlib::GzipReader 去分析,如果 log 里是 Get /XXXX.zip 200 .... Hit 这种格式,我会当成是一次下载请求。

好了,现在的问题是: 1 合并后的.gz log 文件也正常生成了(如 2013-12-08.gz),但最后用 Zlib::GzipReader.open(logs_file) 去处理的时候,发现只读取了部分内容(只有第一个 log 的内容,用 gz.read 看也只有部份内容)。如果直接解压 2013-12-08.gz 文件后可以看到内容是完整的。为什么呢? 2 我这么判断下载次数合理么?因为没有发现 cloudfront 的 log 有关于下载完成的标志。

唉,尼玛,又一次自问自答,难道是我的问题没问清楚么?有什么不清楚的也请指出来呀? 问题解决了,先贴代码:

logs_file = "logs/#{date_fmt}"

File.open(logs_file, "wb") do |file|
    @objs.each do |obj|
        file.write Zlib::GzipReader.new(StringIO.new(obj.read)).read 
    end
end

result = {}
File.open(logs_file) do |file|
    file.each_line do |line|
        if match = /\tGET\t\S+\t\/(\S+)\t200\t\S+\t\S+\t\S+\t\S+\tHit\t/i.match(line)
            result[match[1]] = result[match[1]] ? result[match[1]] + 1 : 1
        end     
    end
end

p result

应该是像我这样合并.gz 文件的做法并不标准,Zlib 库不能正常识别,虽然命令行里可以。所以改为先通过 Zlib::GzipReader 读取出解压缩后内容再写入文件即可~

MS 一般是写个 rake file,这样就可以很方便的写数据库了

需要 登录 后方可回复, 如果你还没有账号请 注册新账号