作者:v神
导语:云原生日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志数据解决平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
CDN是非常重要的互联网基础设施,用户可以通过CDN,快速的访问网络中各种图片,视频等资源。在访问过程中,CDN会产生大量的日志数据,通过对CDN访问日志的分析,可以挖掘出大量有用的信息用于CDN质量和性能的分析,错误诊断,客户端分布, 用户行为分析。
前提条件: CDN日志采集至CLS侧,详见操作详情。
什么是CDN?
CDN内容分发网络(Content Delivery Network,CDN)是在现有Internet中增加的一层新的网络架构,由遍布全球的高性能加速节点构成。这些高性能的服务节点都会按照一定的缓存策略存储业务内容,当用户向某业务内容发起请求时,请求会被调度至最接近用户的服务节点,直接由服务节点快速响应,有效降低用户访问延迟,提升可用性。
当前, 各CDN服务提供厂商, 通常会实时提供基础的监控指标, 比如请求次数,宽带等信息。 但是,在许多特定的分析场景下, 这些默认的实时指标可能并不能满足用户定制化的分析需求。 因此,通常用户会进一步将CDN的原始日志下载下来, 进行离线的深入分析与挖掘。
在实时问题定位、快速验证等交互式分析强烈的场景下,用户自行搭建离线分析集群,不仅需要大量的运维开发成本和人力成本,且数据产生实时性无法保证,延时半小时以上不足为奇;若在CDN日志的告警,排障等分析场景下,灵活性欠佳,无法快速响应实时交互查询需求。
腾讯云CDN与CLS日志服务实现打通, 用户可以将CDN的数据实时投递至CLS日志服务, 并进一步使用CLS日志服务的检索和SQL分析能力, 来满足不同场景下用户个性化的实时日志分析需求:
CDN日志字段说明
字段名 | 原始日志类型 | 日志服务类型 | 说明 |
---|---|---|---|
app_id | Integer | long | 腾讯云账号 APPID |
client_ip | String | text | 客户端 IP |
file_size | Integer | long | 文件大小 |
hit | String | text | 缓存 HIT / MISS,在 CDN 边缘节点命中、父节点命中均标记为 HIT |
host | String | text | 域名 |
http_code | Integer | long | HTTP 状态码 |
isp | String | text | 运营商 |
method | String | text | HTTP Method |
param | String | text | URL 携带的参数 |
proto | String | text | HTTP 协议标识 |
prov | String | text | 运营商省份 |
referer | String | text | Referer 信息,HTTP 来源地址 |
request_range | String | text | Range 参数,请求范围 |
request_time | Integer | long | 响应时间(毫秒),指节点从收到请求后响应所有回包再到客户端所花费的时间 |
request_port | String | long | 客户端与 CDN 节点建立连接的端口,若无则为 - |
rsp_size | Integer | long | 返回字节数 |
time | Integer | long | 请求时间,UNIX 时间戳,单位为:秒。 |
ua | String | text | User-Agent 信息 |
url | String | text | 请求路径 |
uuid | String | text | 请求的唯一标识 |
version | Integer | long | CDN 实时日志版本 |
使用数学统计中的百分数(例如99%最大延迟)来作为告警触发条件较为准确, 使用平均值, 个体值触发告警会造成一些个体请求延时被平均, 无法反映真实情况。 例如使用如下查询分析语句计算一天窗口(1440分钟)内各分钟的平均延时大小,50%分位的延时大小,和90%分位的延时大小。
* | select avg(request_time) as l, approx_percentile(request_time, 0.5) as p50, approx_percentile(request_time, 0.99) as p99, time_series(__TIMESTAMP__, '5m', '%Y-%m-%d %H:%i:%s', '0') as time group by time order by time desc limit 1440
针对99%的延时大于100ms进行告警, 并且在告警信息中之间展示受影响域名、url、client_ip, 以便快速判断错误情况。告警设置如下语句:
* | select approx_percentile(request_time, 0.99) as p99
通过配置多维度分析,在告警信息中展示受影响的域名,客户端ip,url,帮助开发人员快速定位问题。
一旦告警触发后,通过微信,企业微信,短信第一时间获取关键信息。
当页面访问错误的数量出现激增时, 往往可能说明CDN后端服务器出现故障,或者请求过载。 我们可以通过设置告警来对一定时间范围内(eg.一分钟)请求错误数量的同比增数进行监控, 当同比增数超过一定阈值时, 告警通知用户。
最近一分钟内的错误数量
* | select * from (select * from (select * from (select date_trunc('minute', __TIMESTAMP__) as time,count(*) as errct where http_code>=400 group by time order by time desc limit 2)) order by time desc limit 1)
上一分钟内的错误数量
* | select * from (select * from (select * from (select date_trunc('minute', __TIMESTAMP__) as time,count(*) as errct where http_code>=400 group by time order by time desc limit 2)) order by time asc limit 1
告警策略配置触发条件为【最近一分钟内的错误数量】-【上一分钟内的错误数量】 > 指定阈值
$2.errct-$1.errct >100
CDN提供日志中,包含了丰富的内容,我们可以从多个维度对CDN的整体质量和性能进行全方位的统计和分析:
统计http_code小于500的请求占所有请求的百分比。
* | select round(sum(case when http_code<500 then 1.00 else 0.00 end) / cast(count(*) as double) * 100,1) as "健康度"
统计return_code小于400的请求中, hit 为 “hit”的请求百分比。
http_code<400 | select round(sum(case when hit='hit' then 1.00 else 0.00 end) / cast(count(*) as double) * 100,1) as "缓存命中率"
统计一段时间内,总体下载量除以整体耗时获得平均下载速度。
* | select sum(rsp_size/1024.0) / sum(request_time/1000.0) as "平均下载速度(kb/s)"
原理同上,使用ip_to_provider函数,将client_ip转化成对应的运营商。
* | select ip_to_provider(client_ip) as isp , sum(rsp_size)* 1.0 /(sum(request_time)+1) as "下载速度(KB/s)" , sum(rsp_size/1024.0/1024.0) as "下载总量(MB)", count(*) as c group by isp order by c desc limit 10
将访问延时按照各窗口进行统计,可根据应用实际的情况来划分合适的延时时间窗口。
* | select case when request_time < 5000 then '~5s' when request_time < 6000 then '5s~6s' when request_time < 7000 then '6s~7s' when request_time < 8000 then '7~8s' when request_time < 10000 then '8~10s' when request_time < 15000 then '10~15s' else '15s~' end as latency , count(*) as count group by latency
访问错误一直是影响服务体验的重要一环,当出现错误的时候,需要快速定位当前错误QPS和比例是多少,哪些域名和URI影响最大,是否和地域、运营商有关,是不是发布的新版本导致。
查看4xx,5xx错误码分布
* | select http_code , count(*) as c where http_code >= 400 group by http_code order by c desc
从下面的错误分布图来看,主要的错误都是发生了404错误,说明被被访问文件或内容不存在,这个时候就需要检查是不是资源已经被删除或者销毁。
对于http_code > 400的请求,我们对其进行多维度分析,如按照域名和uri的维度进行top 排序;省份,运营商角度查看错误次数;查看客户端分布。
域名
* | select host , count(*) as count where http_code > 400 group by host order by count desc limit 10
url
* | select url , count(*) as count where http_code > 400 group by url order by count desc limit 10
省份,运营商分析
* | select client_ip, ip_to_province(client_ip) as "province", ip_to_provider(client_ip) as "运营商" , count(*) as "错误次数" where http_code >= 400 group by client_ip order by "错误次数" DESC limit 100
客户端分布
* | select ua as "客户端版本", count(*) as "错误次数" where http_code > 400 group by ua order by "错误次数" desc limit 10sql
由图可看出,错误集中Safari客户端,定位问题后发现,是新版本bug导致在Safari浏览器窗口下,访问资源频繁失败。
访问来源分析
* | select ip_to_province(client_ip) as province , count(*) as c group by province order by c desc limit 50
访问TopUrl
http_code < 400 | select url ,count(*) as "访问次数", round(sum(rsp_size)/1024.0/1024.0/1024.0, 2) as "下载总量(GB)" group by url order by "访问次数" desc limit 100
下载流量Top域名,按照各个域名下载数据量大小进行Top排序
* | select host, sum(rsp_size/1024) as "下载总量" group by host order by "下载总量" desc limit 100
下载量Top用户统计
* | SELECT CASE WHEN ip_to_country(client_ip)='香港' THEN concat(client_ip, ' ( Hong Kong )') WHEN ip_to_province(client_ip)='' THEN concat(client_ip, ' ( Unknown IP )') WHEN ip_to_provider(client_ip)='内网IP' THEN concat(client_ip, ' (Private IP )') ELSE concat(client_ip, ' ( ', ip_to_country(client_ip), '/', ip_to_province(client_ip), '/', if(ip_to_city(client_ip)='-1', 'Unknown city', ip_to_city(client_ip)), ' ',ip_to_provider(client_ip), ' )') END AS client, pv as "总访问数", error_count as "错误访问数" , throughput as "下载总量(GB)" from (select client_ip , count(*) as pv, round(sum(rsp_size)/1024.0/1024/1024.0, 1) AS throughput , sum(if(http_code > 400, 1, 0)) AS error_count from log group by client_ip order by throughput desc limit 100)
有效访问Top用户统计
* | SELECT CASE WHEN ip_to_country(client_ip)='香港' THEN concat(client_ip, ' ( Hong Kong )') WHEN ip_to_province(client_ip)='' THEN concat(client_ip, ' ( Unknown IP )') WHEN ip_to_provider(client_ip)='内网IP' THEN concat(client_ip, ' (Private IP )') ELSE concat(client_ip, ' ( ', ip_to_country(client_ip), '/', ip_to_province(client_ip), '/', if(ip_to_city(client_ip)='-1', 'Unknown city', ip_to_city(client_ip)), ' ',ip_to_provider(client_ip), ' )') END AS client, pv as "总访问数", (pv - success_count) as "错误访问数" , throughput as "下载总量(GB)" from (select client_ip , count(*) as pv, round(sum(rsp_size)/1024.0/1024/1024.0, 1) AS throughput , sum(if(http_code < 400, 1, 0)) AS success_count from log group by client_ip order by success_count desc limit 100)
访问PV、UV统计,统计某一时间段内的访问次数和独立的client ip的变化趋势
* | select date_trunc('minute', __TIMESTAMP__) as time, count(*) as pv,count( distinct client_ip) as uv group by time order by time limit 1000
以上就是关于CDN访问日志的玩法分享,如果您有更多有意思的日志实践,欢迎投稿分享!
往期文章:
【腾讯云日志服务CLS】serverless应用中的CLS服务详解
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。