我目前使用的下载服务是 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 有关于下载完成的标志。