用 Apps Script 给外包单做了个日志面板,结果卡在 6 分钟
上周接了个小单,客户要一个能看订单状态的后台,部署在 Cloud Run 上,日志全丢在 Cloud Logging 里。客户不会用控制台,非要一个表格,说「你就让我在 Sheets 里看」。我心想行吧,Apps Script 写完拉倒,结果差点被自己的聪明坑死。
环境是 Apps Script V8,日志源是 Cloud Logging,数据量不大,一天两三百条,但要求每十分钟刷一次。我的做法是用 UrlFetchApp 打 Logging API 的 entries.list,先把服务账号的 token 拿下来:
function getToken() {
const sa = JSON.parse(PropertiesService.getScriptProperties().getProperty('SA_KEY'));
const now = Math.floor(Date.now() / 1000);
const claim = {
iss: sa.client_email,
scope: 'https://www.googleapis.com/auth/logging.read',
aud: 'https://oauth2.googleapis.com/token',
exp: now + 3600,
iat: now
};
const header = { alg: 'RS256', typ: 'JWT' };
const b64 = o => Utilities.base64EncodeWebSafe(JSON.stringify(o)).replace(/=+$/, '');
const unsigned = b64(header) + '.' + b64(claim);
const sig = Utilities.computeRsaSha256Signature(unsigned, sa.private_key);
const jwt = unsigned + '.' + Utilities.base64EncodeWebSafe(sig).replace(/=+$/, '');
return UrlFetchApp.fetch('https://oauth2.googleapis.com/token', {
method: 'post',
payload: { grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer', assertion: jwt }
}).getContentText();
}
拿到 token 后拼 filter,按 resource.type 加时间窗口卡十分钟,把结果写回 Sheet。这一步本身没问题,加了个 CacheService 把 token 缓存 50 分钟,省得每次都签 JWT。
问题出在触发器和执行时间上。Apps Script 的单次执行上限是 6 分钟,我一开始为了「刷得及时」把触发器设成每 5 分钟一次,结果碰到日志量翻倍的下午,一次拉取加写表要跑 4 分半,两次执行叠在一起,Sheet 开始报「同时有太多请求」。更阴的是 UrlFetchApp 对同一个域名有调用配额,我循环里一条一条补数据,跑到一半直接抛异常,前面写进去的行全白费。
为什么这样做:用 Sheets 当展示层是因为客户只认这个,写 Cloud Run 前端成本更高;用 JWT 自签而不是 OAuth 授权流程,是因为外包单不想维护刷新令牌。代价就是 token 得自己缓存,过期时间得自己盯,签名错一个字符就是 401,报错信息还不告诉你哪错了。
哪里会失效:日志超过几千条别想用 entries.list 全拉,得换 BigQuery 导出;触发器频率别贴着执行时间设,留一倍余量;写 Sheet 用 setValues 一次性写,别在循环里 appendRow,我一开始就是循环 append,500 行写了一分多钟。另外 Apps Script 的时区默认跟脚本设置走,filter 里的时间戳必须显式带 Z,不然窗口会错八小时——这个坑我调了半小时。
现在我把触发器改成 15 分钟一次,拉取改成先写临时数组再整块落表,勉强稳住了。但客户又提了个新需求:想看历史趋势图。你们遇到这种「客户只要一个表格」的单子,是硬着头皮在 Sheets 里画图,还是直接劝他上 Looker Studio?
0 条评论
还没有评论,写下第一条。