日志告警指南
云开发控制台自带的告警是 监控指标告警,基于调用量、耗时、错误率等聚合指标,无法按具体状态码细分。需要“statusCode 为 502 就告警”这类日志级监控时,使用本文的方式:把环境日志投递到腾讯云日志服务(CLS),再用 CLS 的告警能力监控日志内容。
本文以云开发网关错误为例,分别介绍 控制台配置 和 CLI / API 配置 两种方式,选择其一即可。
实现路径
| 步骤 | 内容 |
|---|---|
| 一 | 将环境日志投递到 CLS,获取日志主题 |
| 二 | 确认日志主题的索引,保证告警字段可检索 |
| 三 | 用检索语句验证能查到目标日志 |
| 四 | 创建通知渠道组 |
| 五 | 创建告警策略 |
| 六 | 验证告警能真正触发(两种方式通用,见 验证告警触发) |
前置条件
| 项目 | 要求 |
|---|---|
| 账号权限 | 主账号,或已被授予 CLS 读写权限的子账号 |
| 费用 | 日志写入 CLS 后由 CLS 独立计费(写入量、索引、存储、告警策略),建议设置合理的日志保留周期 |
| CLS 控制台 | 腾讯云/日志服务 |
控制台配置
步骤一:日志投递到 CLS
按 投递到 CLS 日志服务 将环境日志投递到 CLS。
投递完成后,先产生一些真实访问请求,再到 CLS 验证,否则容易误判为投递失败。
步骤二:确认索引
告警依赖字段检索,未配置索引会导致告警查不到数据。
在 CLS 控制台选择与云开发环境相同的地域,在检索分析页执行下面的语句,能查到记录说明日志主题选对了:
logType:"accesslog"
然后进入该日志主题的 索引配置,确认:
- 全文索引:开启。
- 键值索引:至少包含
statusCode、logType、host、path、method、module、resourceName、timeCost、requestId。字段含义见 日志字段说明。
⚠️ 索引只对修改后新写入的日志生效。建议投递到 CLS 后先配索引,再验证检索,最后建告警。
步骤三:验证检索语句
不要直接建告警,先在 CLS 控制台的 检索分析 页面依次执行下面三条语句,确认都能查到结果:
-- ① 统计网关 502 的条数
logType:"accesslog" AND statusCode:"502"
| select count(*) as bad_gateway_cnt
-- ② 按域名和路径查看 502 分布
logType:"accesslog" AND statusCode:"502"
| select host, path, count(*) as cnt
group by host, path
order by cnt desc
limit 20
-- ③ 取样本,拿到具体请求 ID 用于排查
logType:"accesslog" AND statusCode:"502"
| select requestId, host, path, method, timeCost, sourceIp
order by timeCost desc
limit 20
如果 ① 返回 0,说明当前没有 502 记录,属正常现象。可先把 502 换成 200 验证语句能跑通。
步骤四:创建通知渠道组
创建通知渠道组:CLS 控制台,监控告警 > 通知渠道组 > 新建,添加需要的渠道:企业微信、邮件、短信、电话、自定义 Webhook(回调到自己的系统)。
建议按告警级别分流:
| 级别 | 通知方式 |
|---|---|
| 提醒 | 企业微信群 |
| 警告 | 企业微信群、邮件 |
| 紧急 | 企业微信群、短信或电话 |
自定义通知内容(可选):CLS 控制台,监控告警 > 通知内容模板 > 新建。企业微信、钉钉、飞书支持 Markdown,创建后在通知渠道组里选用该模板:
## 云开发网关 502 告警
- **域名**:{{index .ConditionGroup "$1.host"}}
- **路径**:{{index .ConditionGroup "$1.path"}}
- **5 分钟内 502 次数**:{{index .QueryResult[0] "cnt"}}
- **触发条件**:{{.Condition}}
- **触发时间**:{{.StartTime}}
- **已持续**:{{.Duration}} 分钟
步骤五:创建告警策略
CLS 控制台,监控告警 > 告警策略 > 新建。下面三种方案选一种,推荐方案 B。执行语句和触发条件中可使用的更多日志字段,见 日志字段说明。
方案 A:基础版,按次数告警
| 配置项 | 填写内容 |
|---|---|
| 告警名称 | 云开发网关 502 告警 |
| 监控对象 | 步骤一投递的日志主题 |
| 执行语句 1 | logType:"accesslog" AND statusCode:"502" | select count(*) as bad_gateway_cnt |
| 查询时间范围 | 最近 5 分钟 |
| 执行周期 | 每 1 分钟 |
| 触发条件 | $1.bad_gateway_cnt >= 5 |
| 告警级别 | 警告,生产核心环境建议选“紧急” |
| 持续周期 | 1 个周期更敏感,2 个周期更抗抖动 |
方案 B:分组版,直接定位到域名和接口
| 配置项 | 填写内容 |
|---|---|
| 执行语句 1 | logType:"accesslog" AND statusCode:"502" | select host, path, count(*) as cnt group by host, path order by cnt desc limit 20 |
| 查询时间范围 | 最近 5 分钟 |
| 执行周期 | 每 1 分钟 |
| 触发条件 | $1.cnt >= 5 |
| 分组触发 | 开启,分组字段填 host,path |
| 告警分类 | {{index .ConditionGroup "$1.host"}}、{{index .ConditionGroup "$1.path"}} |
| 多维分析 | 自定义检索分析:logType:"accesslog" AND statusCode:"502" AND host:"{{index .ConditionGroup "$1.host"}}" AND path:"{{index .ConditionGroup "$1.path"}}" |
开启分组触发后,每个“域名 + 路径”组合单独判定、单独发送告警,能直接看到是哪个接口出问题,而不是只收到一条总数通知。
方案 C:错误率版,适用于流量波动大的业务
低流量站点用绝对次数容易漏报,高流量站点容易误报,用占比更稳定。
| 配置项 | 填写内容 |
|---|---|
| 执行语句 1 | logType:"accesslog" AND statusCode:"502" | select count(*) as err_cnt |
| 执行语句 2 | logType:"accesslog" | select count(*) as total_cnt |
| 查询时间范围 | 最近 5 分钟,两条语句保持一致 |
| 触发条件 | $2.total_cnt > 100 AND $1.err_cnt >= 10 AND $1.err_cnt * 1.0 / $2.total_cnt > 0.01 |
通用设置,三种方案都需要配置:
| 配置 | 建议值 |
|---|---|
| 通知渠道组 | 选择步骤四创建的渠道组 |
| 告警间隔 | 15 分钟,持续故障建议 30 分钟,避免重复打扰 |
| 恢复通知 | 开启,故障恢复时收到确认通知 |
| 未恢复告警合并 | 开启 |
CLI / API 配置
准备凭证
CLI / API 方式需要两类凭证:
| 凭证 | 获取 | 能做什么 |
|---|---|---|
| CloudBase 环境 API Key | 云开发平台,环境下的 API Key 管理 | 使用 tcb CLI,包括日志检索 tcb logs search |
| 腾讯云账号密钥(SecretId、SecretKey) | 访问管理(CAM)控制台,子账号下的密钥 | 调用 CLS 全部接口:日志主题、索引、检索、告警策略 |
⚠️ 只用 API Key 无法完成告警配置。日志主题、索引、检索和告警策略属于 CLS 产品接口,不接受 CloudBase API Key 鉴权,需要额外准备具备
QcloudCLSFullAccess权限的子账号密钥。多租户场景可将权限限定到指定的topic/<TopicId>。
配置凭证与公共变量:
# CloudBase 环境 API Key
tcb login --cloudbase-api-key <CLOUDBASE_API_KEY> -e <ENV_ID>
tcb env use <ENV_ID>
# 腾讯云账号密钥,CLS 接口必需
tccli configure
export TENCENTCLOUD_SECRET_ID=<SecretId>
export TENCENTCLOUD_SECRET_KEY=<SecretKey>
# 公共变量,地域与云开发环境地域一致
export REGION=ap-shanghai
export ENV_ID=<环境 ID>
步骤一:获取日志主题
开通环境日志服务(异步执行,已开通可跳过):
tccli tcb CreateEnvResource --region $REGION --EnvId $ENV_ID --Resources '["log"]'
获取环境默认日志主题与账号 UIN:
tcb env detail --env-id $ENV_ID --json
从返回结果中取出日志集、日志主题与 UIN:
{
"LogServices": [
{ "LogsetId": "<LogsetId>", "TopicId": "<TopicId>" }
],
"UserInfo": { "Uin": 100000000000 }
}
export LOGSET_ID=<LogsetId>
export TOPIC_ID=<TopicId>
export UIN=<UserInfo.Uin>
如果 tcb env detail 没有返回 UIN,执行下面的命令,返回的 AccountId 即 UIN:
tccli sts GetCallerIdentity --version 2018-08-13
日志服务开通后,网关访问日志、云函数、云托管、数据库等日志会一并写入这个默认主题。后续索引与告警直接建在默认主题上:
export ALARM_LOGSET_ID=$LOGSET_ID
export ALARM_TOPIC_ID=$TOPIC_ID
可选:投递到自定义日志主题
需要独立的存储周期或业务隔离时,可以把默认主题整体投递到自定义主题。环境日志由平台写入默认主题,公开 API 没有改绑自定义主题的入口,需要通过数据加工全量复制实现。
-
创建自定义日志集与日志主题:
tccli cls CreateLogset --region $REGION --LogsetName "tcb-gateway-logset"export CUSTOM_LOGSET_ID=<LogsetId>cat > topic.json <<'EOF'{"LogsetId": "<CUSTOM_LOGSET_ID>","TopicName": "tcb-accesslog-custom","PartitionCount": 1,"AutoSplit": true,"MaxSplitPartitions": 10,"StorageType": "hot","Period": 30,"Describes": "云开发环境日志(数据加工整体投递)","BizType": 0,"BillingMode": 0}EOFtccli cls CreateTopic --region $REGION --cli-input-json file://topic.jsonexport CUSTOM_TOPIC_ID=<TopicId>Period为保存天数,3640表示永久保存。StorageType可选hot(标准存储)或cold(低频存储,保存期不少于 7 天)。 -
创建数据加工任务,整体投递:
cat > transform.json <<'EOF'{"Name": "tcb-accesslog-to-custom-topic","FuncType": 1,"TaskType": 3,"SrcTopicId": "<TOPIC_ID>","DstResources": [{ "TopicId": "<CUSTOM_TOPIC_ID>", "Alias": "tcb-env-accesslog" }],"EtlContent": "log_keep(true)","EnableFlag": 1,"DataTransformType": 0,"KeepFailureLog": 2}EOFtccli cls CreateDataTransform --region $REGION --cli-input-json file://transform.json参数 说明 FuncType1为指定目标主题,2为动态创建(此时EtlContent必须用log_auto_output)TaskType1、2为预览,3为创建真实任务SrcTopicId环境默认日志主题 DstResources[].TopicId自定义日志主题 EtlContent加工语句。整体投递用 log_keep(true),需要过滤时改为log_keep(regex_match(...))EnableFlag1开启,2关闭ProcessFromTimestamp、ProcessToTimestamp可选,处理的起止时间(秒级时间戳),不填 ProcessToTimestamp表示持续执行 -
后续索引与告警改建在自定义主题上:
export ALARM_LOGSET_ID=$CUSTOM_LOGSET_IDexport ALARM_TOPIC_ID=$CUSTOM_TOPIC_ID
⚠️ 数据加工只对任务创建后(或
ProcessFromTimestamp之后)写入的日志生效,不会回溯历史数据,目标主题会另外计一份存储。
步骤二:配置索引
告警依赖字段检索,未配置索引会导致告警查不到数据。字段含义见 日志字段说明。
先查看现有索引:
tccli cls DescribeIndex --region $REGION --TopicId $ALARM_TOPIC_ID
缺少告警字段时补齐。resourceName 标识请求实际访问的资源,用于定位报错归属;并非所有请求都带该字段,鉴权类接口为空。
cat > index.json <<'EOF'
{
"TopicId": "<ALARM_TOPIC_ID>",
"Status": true,
"Rule": {
"FullText": { "CaseSensitive": false, "Tokenizer": "-=/?;,.\"", "ContainZH": true },
"KeyValue": {
"CaseSensitive": false,
"KeyValues": [
{ "Key": "logType", "Value": { "Type": "text", "Tokenizer": "@&?|#()='\",;:<>[]{}/ \n\t\r\\", "SqlFlag": true, "ContainZH": true } },
{ "Key": "statusCode", "Value": { "Type": "long", "Tokenizer": "", "SqlFlag": true, "ContainZH": false } },
{ "Key": "path", "Value": { "Type": "text", "Tokenizer": "@&?|#()='\",;:<>[]{}/ \n\t\r\\", "SqlFlag": true, "ContainZH": true } },
{ "Key": "method", "Value": { "Type": "text", "Tokenizer": "@&?|#()='\",;:<>[]{}/ \n\t\r\\", "SqlFlag": true, "ContainZH": true } },
{ "Key": "resourceName", "Value": { "Type": "text", "Tokenizer": "@&?|#()='\",;:<>[]{}/ \n\t\r\\", "SqlFlag": true, "ContainZH": true } },
{ "Key": "module", "Value": { "Type": "text", "Tokenizer": "@&?|#()='\",;:<>[]{}/ \n\t\r\\", "SqlFlag": true, "ContainZH": true } },
{ "Key": "requestId", "Value": { "Type": "text", "Tokenizer": "@&?|#()='\",;:<>[]{}/ \n\t\r\\", "SqlFlag": true, "ContainZH": true } },
{ "Key": "timeCost", "Value": { "Type": "long", "Tokenizer": "", "SqlFlag": true, "ContainZH": false } }
]
}
},
"IncludeInternalFields": true,
"MetadataFlag": 1
}
EOF
tccli cls ModifyIndex --region $REGION --cli-input-json file://index.json
⚠️ 索引只对修改后新写入的日志生效。同一个日志主题同一时间只允许 1 个索引修改操作,批量操作需要串行执行。
步骤三:验证检索语句
不要直接建告警,先用检索命令确认能查到目标日志。
使用 tcb CLI(API Key 凭证即可,推荐):
# 错误率总览:5xx 数量与总量
tcb logs search --env-id $ENV_ID \
--query 'logType:"accesslog" | select sum(case when cast(statusCode as bigint) >= 500 then 1 else 0 end) as err_cnt, count(*) as total_cnt, round(sum(case when cast(statusCode as bigint) >= 500 then 1 else 0 end) * 100.0 / count(*), 2) as err_rate' \
--timeRange 1h --json
# 按资源和接口拆分错误数,定位报错来自哪个资源
tcb logs search --env-id $ENV_ID \
--query 'logType:"accesslog" | select resourceName, path, count(*) as err_cnt where cast(statusCode as bigint) >= 500 group by resourceName, path order by err_cnt desc limit 20' \
--timeRange 1h --json
| 参数 | 说明 |
|---|---|
--query | CLS 查询语句,支持 | select 聚合 |
--timeRange | 30m、1h、6h、1d,或绝对区间 "2026-10-26 19:00:00,2026-10-26 20:00:00" |
--limit | 返回条数,最大 100 |
--sort | desc 最新优先,asc 最早优先 |
--service | tcb 为云函数、数据库、网关等(默认),tcbr 为云托管 |
使用 CLS 接口 SearchLog(需腾讯云密钥,时间为毫秒时间戳):
FROM=$(( $(date -v-1H +%s) * 1000 )); TO=$(( $(date +%s) * 1000 )) # macOS
tccli cls SearchLog --region $REGION --TopicId $ALARM_TOPIC_ID --From $FROM --To $TO \
--QueryString 'logType:"accesslog" | select resourceName, path, count(*) as err_cnt where cast(statusCode as bigint) >= 500 group by resourceName, path order by err_cnt desc limit 20' \
--QuerySyntax 1 --UseNewAnalysis true
聚合结果在返回的 AnalysisRecords 中。statusCode 在日志中是字符串,SQL 比较需要 cast(statusCode as bigint)。
步骤四:创建通知渠道组
通知接收人的 UIN 取自步骤一的 UserInfo.Uin,下面的示例通过邮件通知:
cat > notice.json <<'EOF'
{
"Name": "云开发网关错误告警通知组",
"Type": "All",
"NoticeReceivers": [
{
"ReceiverType": "Uin",
"ReceiverIds": [<UIN>],
"ReceiverChannels": ["Email"],
"StartTime": "00:00:00",
"EndTime": "23:59:59",
"NoticeContentId": "Default-zh",
"Index": 1
}
]
}
EOF
tccli cls CreateAlarmNotice --region $REGION --cli-input-json file://notice.json
export NOTICE_ID=<AlarmNoticeId>
| 字段 | 说明 |
|---|---|
Type | Trigger 仅触发时通知,Recovery 仅恢复时通知,All 两者都通知 |
ReceiverType | Uin 按用户(填 UIN),Group 按用户组(填用户组 ID) |
ReceiverIds | 接收人 ID 数组,整数,可填多个 |
ReceiverChannels | Email 邮件、Sms 短信、Phone 电话、WeChat 微信 |
StartTime、EndTime | 允许接收通知的时段 |
NoticeContentId | 通知内容模板,Default-zh 为默认中文模板 |
邮件发送到该账号在腾讯云消息中心绑定的邮箱。需要发送到群时,改用 WebCallbacks,其中 CallbackType 可选 WeCom、DingTalk、Lark,并填写机器人 Webhook 的 Url。
步骤五:创建告警策略
下面的示例对应“错误率 + 分组”:5 分钟窗口内,单个 resourceName + path 组合请求量大于 100 且 5xx 占比超过 5% 时告警,每 1 分钟检查一次,重复通知间隔 30 分钟。执行语句和触发条件中可使用的更多日志字段,见 日志字段说明。
cat > alarm.json <<'EOF'
{
"Name": "云开发网关错误率告警",
"MonitorObjectType": 0,
"AlarmTargets": [
{
"TopicId": "<ALARM_TOPIC_ID>",
"LogsetId": "<ALARM_LOGSET_ID>",
"Number": 1,
"Query": "logType:\"accesslog\" | select resourceName, path, count(*) as err_cnt where cast(statusCode as bigint) >= 500 group by resourceName, path",
"StartTimeOffset": -5,
"EndTimeOffset": 0,
"SyntaxRule": 1
},
{
"TopicId": "<ALARM_TOPIC_ID>",
"LogsetId": "<ALARM_LOGSET_ID>",
"Number": 2,
"Query": "logType:\"accesslog\" | select resourceName, path, count(*) as total_cnt group by resourceName, path",
"StartTimeOffset": -5,
"EndTimeOffset": 0,
"SyntaxRule": 1
}
],
"MonitorTime": { "Type": "Period", "Time": 1 },
"TriggerCount": 2,
"AlarmPeriod": 30,
"Condition": "$2.total_cnt > 100 AND $1.err_cnt * 1.0 / $2.total_cnt > 0.05",
"AlarmLevel": 1,
"Status": true,
"GroupTriggerStatus": true,
"GroupTriggerCondition": ["$1.resourceName", "$1.path"],
"AlarmNoticeIds": ["<NOTICE_ID>"],
"Analysis": [
{
"Name": "5xx 原始日志",
"Type": "query",
"Content": "logType:\"accesslog\" | select requestId, resourceName, path, method, statusCode, timeCost, sourceIp where cast(statusCode as bigint) >= 500 limit 20",
"ConfigInfo": [{ "Key": "SyntaxRule", "Value": "1" }]
}
],
"MessageTemplate": "云开发网关错误率告警:{{.Topic}},触发条件 {{.Condition}},时间 {{.StartTime}}"
}
EOF
tccli cls CreateAlarm --region $REGION --cli-input-json file://alarm.json
export ALARM_ID=<AlarmId>
参数说明
| 参数 | 说明 |
|---|---|
AlarmTargets[].Query | 执行语句,必须包含 | select 分析语句,只写检索条件不会触发 |
AlarmTargets[].Number | 语句序号,从 1 开始,条件中用 $1.、$2. 引用 |
StartTimeOffset、EndTimeOffset | 相对执行时刻的分钟偏移,非正数且 StartTimeOffset 不大于 EndTimeOffset。-5 到 0 表示最近 5 分钟 |
SyntaxRule | 1 为 CQL(推荐),0 为 Lucene |
MonitorTime | { "Type": "Period", "Time": 1 } 表示每 1 分钟执行一次 |
TriggerCount | 连续满足几个周期才告警,2 可抗单次抖动 |
AlarmPeriod | 重复通知间隔,单位为分钟 |
AlarmLevel | 0 警告,1 提醒,2 紧急 |
Condition | 触发条件,引用格式为 $N.字段名,字段名与 select 别名一致 |
GroupTriggerStatus | 开启分组触发。开启后 Query 必须含 group by,GroupTriggerCondition 填分组字段 |
Analysis | 多维分析,通知中附带跳转链接,直达原始日志 |
MessageTemplate | 可用 {{.Topic}}、{{.Condition}}、{{.StartTime}}、{{.Duration}} |
常见变体
| 场景 | 修改方法 |
|---|---|
| 只看 5xx 绝对量 | 使用单条语句 ... where cast(statusCode as bigint) >= 500 | select count(*) as err_cnt,条件为 $1.err_cnt >= 10 |
| 包含 4xx | 把 >= 500 改为 >= 400 |
| 不分组,看全局错误率 | GroupTriggerStatus 设为 false,两条语句去掉 group by,条件为 $1.err_cnt * 1.0 / $2.total_cnt > 0.05 |
| 关注慢请求 | 条件改用 timeCost,例如 $1.max_cost > 3000 |
管理告警策略
# 查看策略
tccli cls DescribeAlarms --region $REGION --Filters '[{"Key":"alarmId","Values":["<ALARM_ID>"]}]'
# 调整重复通知间隔
tccli cls ModifyAlarm --region $REGION --AlarmId $ALARM_ID --AlarmPeriod 30
# 临时静默,保留策略,只停通知
tccli cls ModifyAlarm --region $REGION --AlarmId $ALARM_ID --Status false
# 删除策略,不可恢复
tccli cls DeleteAlarm --region $REGION --AlarmId $ALARM_ID
发布期临时静默可使用 CreateAlarmShield。Enable 设为 false 会将策略归档。
接口速查
| 动作 | CLI | 接口 Action |
|---|---|---|
| 开通环境日志资源 | tccli tcb CreateEnvResource | tcb CreateEnvResource |
| 查询环境、日志主题、UIN | tcb env detail --json | tcb DescribeEnvs |
| 检索日志 | tcb logs search | cls SearchLog |
| 创建日志集、日志主题 | tccli cls CreateLogset、CreateTopic | cls CreateLogset、cls CreateTopic |
| 整体投递到自定义主题 | tccli cls CreateDataTransform | cls CreateDataTransform |
| 查询、修改索引 | tccli cls DescribeIndex、ModifyIndex | cls DescribeIndex、cls ModifyIndex |
| 通知渠道组 | tccli cls CreateAlarmNotice | cls CreateAlarmNotice、cls DescribeAlarmNotices |
| 告警策略 | tccli cls CreateAlarm、ModifyAlarm、DeleteAlarm | cls CreateAlarm、cls ModifyAlarm、cls DeleteAlarm、cls DescribeAlarms |
| 告警屏蔽 | 无 | cls CreateAlarmShield |
| 获取当前账号 UIN | tccli sts GetCallerIdentity --version 2018-08-13 | sts GetCallerIdentity |
使用 SDK 调用云 API
CLS 接口使用 TC3-HMAC-SHA256 签名,手写签名成本较高,建议使用 SDK。以 Python 为例,请求参数与步骤五的 alarm.json 一致:
pip install tencentcloud-sdk-python-cls
import os
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.cls.v20201016 import cls_client, models
cred = credential.Credential(
os.environ["TENCENTCLOUD_SECRET_ID"], os.environ["TENCENTCLOUD_SECRET_KEY"])
hp = HttpProfile(endpoint="cls.tencentcloudapi.com")
client = cls_client.ClsClient(cred, "ap-shanghai", ClientProfile(httpProfile=hp))
req = models.CreateAlarmRequest()
with open("alarm.json", encoding="utf-8") as f:
req.from_json_string(f.read())
print(client.CreateAlarm(req).to_json_string())
CreateLogset、CreateTopic、CreateDataTransform、ModifyIndex、CreateAlarmNotice 的调用方式相同,换成对应的 models.XxxRequest() 即可。
验证告警触发
控制台和 CLI / API 两种方式配置完成后,都需要做一次端到端验证,不要等到故障发生才发现告警没有生效:
- 临时把执行语句改成一定会命中的语句,例如把
statusCode:"502"换成statusCode:"200"。 - 把触发条件临时改成
>= 1,执行周期设为 1 分钟。 - 等待 1 分钟至 3 分钟,确认收到通知,并点开通知里的链接,确认能跳转到 CLS 检索页并看到原始日志。
- 把语句和阈值改回目标配置并保存。
收到告警后排查
-
点击告警通知中的多维分析链接,直达 CLS 检索页。
-
执行下面的语句,拿到出错请求的
requestId:logType:"accesslog" AND statusCode:"502"| select requestId, host, path, method, timeCost, sourceIporder by timeCost desclimit 20 -
用
requestId反查该请求在云函数、云托管中的日志,判断问题在网关还是后端:requestId:"9be5592e-11ea-4f45-9c83-e44ff20e7ed4" -
502 的常见原因:后端实例冷启动超时、容器重启或缩容到 0、上游连接被重置、响应体超限。
-
结合
timeCost判断:耗时接近网关超时阈值,通常是超时型 502;耗时很短,一般是上游不可用。
语句速查
| 场景 | 语句 |
|---|---|
| 502 计数 | logType:"accesslog" AND statusCode:"502" | select count(*) as cnt |
| 502 按接口分组 | logType:"accesslog" AND statusCode:"502" | select host, path, count(*) as cnt group by host, path order by cnt desc limit 20 |
| 所有 5xx | logType:"accesslog" | select count(*) as cnt where cast(statusCode as bigint) >= 500 |
| 慢请求(超过 3000 ms) | logType:"accesslog" | select count(*) as cnt where cast(timeCost as bigint) > 3000 |
| 按模块查看错误分布 | logType:"accesslog" AND statusCode:"502" | select module, count(*) as cnt group by module order by cnt desc |
| 单请求追踪 | requestId:"<requestId>" |
常见问题
投递后 CLS 里查不到日志?
依次确认:投递时间点之后是否有新的访问请求;CLS 控制台地域是否与环境地域一致;检索时间范围是否覆盖请求发生的时间;字段是否已配置索引。
只有 CloudBase API Key,能配告警吗?
不能。CLS 的主题、索引、检索、告警接口只接受腾讯云 SecretId、SecretKey 签名。需要额外准备具备 QcloudCLSFullAccess,或限定到指定主题的子账号密钥。API Key 可用于 tcb logs search 检索日志。
tcb env detail 返回的 LogServices 为空?
环境未开通日志服务。执行 tccli tcb CreateEnvResource --Resources '["log"]',再轮询 tcb env detail,开通为异步操作,最长约 5 分钟。
语句在检索页能查到,但告警不触发?
逐项核对:
- 执行语句必须包含
| select分析语句,只写检索条件无法告警。 - 触发条件用
$1.字段名引用,且与select别名一致。 - 开启分组触发时,执行语句必须有
group by。 StartTimeOffset为非正数,且不大于EndTimeOffset。- 索引对新写入的数据已生效。
窗口设为 1 分钟却漏报?
网关日志从产生到写入 CLS 有秒级至 1 分钟级的延迟,窗口过窄容易整轮落空。建议把查询时间范围放宽到 5 分钟,同时调大告警间隔避免重复通知。
告警太频繁,或分组触发后通知量暴涨?
通知量按分组数放大。可以调大阈值、延长执行周期、将持续周期设为 2、把告警间隔调到 30 分钟,必要时关闭分组触发。
statusCode 数值比较失败?
statusCode 在日志中是字符串,SQL 中需要写成 cast(statusCode as bigint) >= 500。
只想监控某个域名或接口?
在检索条件里追加过滤,例如:
logType:"accesslog" AND statusCode:"502" AND host:"xxx.api.tcloudbasegateway.com"
| select count(*) as cnt
多个环境怎么区分?
每个环境投递到各自的日志主题,为每个主题单独建告警策略,或在通知内容中加入主题名变量 {{.Topic}}。
怎么控制费用?
在 CLS 控制台设置日志保留周期(如 7 天或 30 天),并只对必要字段开启键值索引。
并发操作报错?
CreateAlarm 限频 20 次/秒;同一个日志主题同一时间只允许 1 个 ModifyIndex 操作,需串行执行。