微创(且更准确)的分析:GoAccess和Athena / SQL

2021-02-17 18:17:45

多年来,就像大多数其他互联网一样,我一直在使用Google Analytics(分析)来衡量对此网站的访问量,而无需考虑太多。对我来说,这不过是一个光荣的历史记录而已,随着这些年来产品变得越来越复杂,我经常会因其扩展的界面而感到困惑。

最近,出于对Google追踪我们到互联网各个角落的欲望的满足,我开始寻找更隐私保护的替代方案。我登陆了Goatcounter,该公司故意不设置cookie,也没有尝试跟踪用户,并且符合GDPR的规定,恕不另行通知。与Google拥挤的面板相比,它还有一个出色而简单的界面,是UI设计的杰作。一切都集中在一个地方,漂亮的图表,只有我关心的信息。

但是安装后我很快注意到,尽管Goatcounter是一款独立的分析产品,具有良好的意图(尽可能少地进行跟踪),但这并不能确保其不会被列入uBlock Origin的阻止列表中。确实,我自己的adblocker阻止了我网站的分析:

这让我开始思考:该站点主要是技术材料,技术人员倾向于使用adblocker。如果我的读者群中有很大一部分正在使用adblocker,我的分析结果是否准确?如果没有,他们要走多远?经过一番调查后,答案是:它们绝对不准确,而且偏差很大。事实证明,如果有人安装了广告拦截器,那么您的亲爱的读者就是您。

上周,我从该站点发布了一篇帖子,在Hacker News上排名短暂上升至第一,并查看了我的分析显示的流量与实际收到的流量之间的差异。

我的估计是,我获得的非机器人唯一身份访问者数量是分析报告的2.5倍左右(分别为38k和13k),这意味着大约60%的用户正在使用adblocker。阅读最后,看看我如何得到这些数字。

如果分析产品在该级别被阻止,则有一个很强的论点,那就是根本不值得使用它们-您实际上只是获得了流量示例,而不是半完整的视图。那你该怎么办呢?好吧,如何通过读取日志文件来像1999年那样进行分析。这比听起来容易,因为不管您相信与否,都有一些令人惊叹的工具来支持它。

GoAccess是一个写得很好的日志解析和可视化实用程序,具有基于curses的终端界面以及将生成图形HTML的Web服务器。

它支持所有常见的Web日志记录格式,包括来自Apache,Nginx,ELB和CloudFront的格式。该站点托管在S3上,并通过CloudFront提供服务,因此我正在使用后者。在分发的主设置面板下,可以轻松配置从CloudFront进行日志记录:

提示:也可以考虑使用日志前缀,以便您可以从多个站点登录到同一存储桶,并避免自己一遍又一遍地配置同一件事。

一个不错的扩充是使用到期策略配置目标S3存储桶。这可以让您说,日志会在30天后自动修剪,从而通过减少保留量来进一步保护访问者的隐私,并防止日志永久累积并吞噬您的存储成本。

(在存储桶的“管理”部分下创建新的“生命周期规则”。所有设置都很简单。)

我有一个Git存储库,可以用作日志的分析测试平台。我没有提交任何实际的日志,但是其中包含各种脚本,这些脚本为常用任务提供了简便的快捷方式。

这是另一个启动GoAccess的地方,它使用了我的标准日志位置,压缩后的日志流式传输到其中,并通过我不想看到的排除路径列表进行过滤:

#!/ bin / bashif [" $#" -ne 1];然后回显"用法:$ 0< site>" exit 1fiNUM_DAYS = 30files =(logs-brandur / $ 1 / *)#可以防止目录中退化的大量文件last_files = $ {files [@]:-3000} gunzip -c $ last_files | grep --line-buffered -v -E -f exclude_list.txt | goaccess--p conf / goaccess.conf --keep-last $ NUM_DAYS

GoAccess很棒,但是在本地同步日志并启动它会有点慢。尽管它提供了我们关心的所有基本信息,但我们仍然牢牢抓住了它的轨道。我们可以使用AWS Athena扩展对日志分析的使用,这使我们能够以相对较低的成本使用任意SQL分析日志数据。

雅典娜基于Presto构建,Presto是一个SQL引擎,专门处理大型分布式数据。与传统的数据仓库不同,Presto不需要将数据集中存储的在线组件–非常乐意将自身临时升级并根据需要从S3上存储的文件集合中读取数据,例如CloudFront-生成访问日志。

(顺便说一句,在命名事物时不要尝试使用连字符,否则您会遇到一些有史以来最真实的错误消息。)

然后,在其中创建一个表,该表的结构与Cloudfront日志记录格式相同。请注意,末尾的LOCATION语句指定表的源是S3路径。

如果不存在,则创建外部表logs_brandur.brandur_org(日期,时间STRING,位置STRING,字节BIGINT,request_ip STRING,方法STRING,主机STRING,uri STRING,状态INT,引荐来源STRING,用户代理STRING,query_string STRING,cookie STRING ,result_type STRING,request_id STRING,host_header STRING,request_protocol STRING,request_bytes BIGINT,time_taken FLOAT,xforwarded_for STRING,ssl_protocol STRING,ssl_cipher STRING,response_result_type STRING,http_version STRING,fle_status_result_int, STRING,sc_content_len BIGINT,sc_range_start BIGINT,sc_range_end BIGINT)行格式分隔的字段,由' \ t' LOCATION' s3://logs-brandur/brandur.org/' TBLPROPERTIES( #39; skip.header.line.count' =' 2');

(此查询来自官方的Cloudfront-with-Athena文档。如果该版本过时,请去那里获取规范的版本。)

缺点之一是,即使按亚马逊的低标准,Athena界面也很粗糙,但是其他人将运行Presto集群,而不必这样做,这真是天赐的礼物。我们可以解决UI问题。

AWS的最佳功能之一是,它为每个服务都具有完整的API,并将其反映在awscli中的命令中,使其非常易于访问和使用。我不太想接触Athena的网络用户界面,所以我写了另一个小脚本来创建Athena查询,轮询API直到完成,然后以简单的表格形式显示结果。该脚本将一个* .sql文件作为输入,因此我可以在Vim中以突出的语法突出显示和完成语法来编写SQL,并在Git中对其进行版本控制-如果使用香草Athena产品,则无法使用这两个重要功能。

这是一个查询,它映射到我的Cloudfront日志上,从而为我提供了上个月的每天唯一身份访问者:

SELECT date_trunc(' day&#39 ;, date)AS day,count(distinct(request_ip))AS unique_visitorsFROM brandur_logs.brandur_orgWHERE status = 200 AND date> now()-间隔' 30'天-过滤掉静态文件并且不喜欢uri'%。%' -过滤已知的漫游器(从Goaccess复制的列表,为了简洁起见被删节)和user_agent不喜欢'%AdsBot-Google%' AND user_agent不喜欢'%Googlebot%' AND user_agent不喜欢'%bingbot%'按1组乘以1;

对于像我的“微小”数据集(大约100 MB到GB),Athena会在几秒钟内回复:

$ bin / query querys / brandur.org / unique_last_month.sqlquery执行ID:65df1113-b206-4fc0-b1d2-8ac8017cbc35 + ---------- + ------------- -+ |天unique_visitors | + ---------- + --------------- + | 2021-01-17 | 624 | | 2021-01-18 | 801 | | 2021-01-19 | 820 | | 2021-01-20 | 806 | | 2021-01-21 | 824 | | 2021-01-22 | 866 | | 2021-01-23 | 743 | | 2021-01-24 | 692 | | 2021-01-25 | 947 | | 2021-01-26 | 808 | | 2021-01-27 | 894 | | 2021-01-28 | 860 | | 2021-01-29 | 781 | | 2021-01-30 | 599 | | 2021-01-31 | 627 | | 2021-02-01 | 817 | | 2021-02-02 | 879 | | 2021-02-03 | 835 | | 2021-02-04 | 886 | | 2021-02-05 | 1232 | | 2021-02-06 | 540 | | 2021-02-07 | 530 | | 2021-02-08 | 19599 | | 2021-02-09 | 14626 | | 2021-02-10 | 1934年| | 2021-02-11 | 1341 | | 2021-02-12 | 1148 | | 2021-02-13 | 809 | | 2021-02-14 | 888 | | 2021-02-15 | 901 | + ---------- + --------------- +

选择uri,count(distinct(request_ip))AS unique_visitorsFROM brandur_logs.brandur_orgWHERE状态= 200 AND日期> now()-间隔' 30'天-过滤掉静态文件并且不喜欢uri'%。%' -过滤已知的漫游器(从Goaccess复制的列表,为了简洁起见被删节)和user_agent不喜欢'%AdsBot-Google%' AND user_agent不喜欢'%Googlebot%' AND user_agent不喜欢'%bingbot%'按1组乘以2 DESCLIMIT 20;

$ bin / queryquery / brandur.org / top_articles_last_month.sqlquery执行ID:1830fea4-725d-4e73-ab53-0ffcff3a189f + ------------------------ ------------ + --------------- + | uri | unique_visitors | + ------------------------------------ + ------------ --- + | / fragments / graceful-degradation-time | 32802 | | / | 4854 | | /文章| 2090 | | / logfmt | 2016 | | /大型数据库伤亡| 1726 | | /片段| 1448 | | / postgres-connections | 1393 | | / about | 1227 | | /照片| 942 | | / fragments / rss-abandon | 821 | | /新闻通讯| 811 | | /幂等键| 797 | | / go-worker-pool | 724 | | / twitter | 690 | | / fragments / homebrew-m1 | 645 | | /现在| 633 | | / fragments / test-kafka | 611 | | / fragments / ffmpeg-h265 | 598 | | / elegant-apis | 575 | | / postgres-atomicity | 412 | + ------------------------------------ + ------------ -+

目前,Athena的价格为每TB扫描数据5美元。对于像我的这样的网站来说,这相当便宜,该网站每月产生100 MB的日志,但是值得考虑的是,如果您要运行更大的日志。定价的副作用是,这还意味着如果您保留数据较短的时间,则价格会更低,从而在较少的数据上运行分析(并使您的网站对隐私更加友好)。

通过比较我的在线分析工具的结果和这些基于日志记录的解决方案的结果,我可以大致了解到我的访问者中有多少人正在使用adblocker,因此对于分析来说是不可见的。

我将上周的HN高峰用作衡量时间的好时机。请注意,这种分析并不是完全科学的,当然也有一些误差线,但是我已经尽力过滤掉了机械手,静态文件和重复的访问,因此幅度应该大致正确。

Google Analytics(分析)和Goatcounter都同意,在过去的两天中,我吸引了约1.3万名独立访客。 GoAccess和我自己的自定义雅典娜查询都同意,它更像是约3.3万名唯一身份访问者,这使我的访问者比率比分析报告的结果高出约2.5倍,这意味着大约60%的读者正在使用adblocker。

因此,尽管分析工具仍可用于衡量样本中的访问者,但它们并不能为您提供完整的故事,这本身就是您可能要考虑将其删除的一个很好的理由,但隐私问题除外。

就个人而言,我认为使用Goatcounter这样的致力于隐私保护的工具还是不错的,并且它们肯定会比通过日志记录的分析(例如为您提供纯JavaScript的信息,例如在网站上花费的时间和屏幕尺寸)产生更多的收益,同时方便查看。