'use strict'; /** * 微信小程序接口请求日志。 * * 仅记录定位请求所需的元数据,不记录 authorization、platform-code、 * cookie、请求体或完整响应,避免敏感信息进入日志。 */ module.exports = options => { const slowThreshold = Number(options.slowThreshold) || 3000; return async function weappRequestLogger(ctx, next) { const startTime = Date.now(); const requestId = ctx.logId || ctx.app.uuid.v1(); let requestError = null; ctx.logId = requestId; ctx.set('X-Request-Id', requestId); try { await next(); } catch (error) { requestError = error; throw error; } finally { const duration = Date.now() - startTime; const user = ctx.session && ctx.session.sessionUser; const project = ctx.session && ctx.session.sessionProject; const tender = ctx.tender; const responseBody = ctx.body; const businessCode = responseBody && typeof responseBody === 'object' ? responseBody.code : undefined; const logData = { requestId, requestTime: new Date(startTime).toISOString(), method: ctx.method, path: ctx.path, status: ctx.status, code: businessCode, duration, slow: duration >= slowThreshold, uid: user && (user.accountId || user.id), projectId: project && project.id, projectCode: project && project.code, tenderId: tender && tender.id, ip: ctx.ip, }; const accessLogger = ctx.getLogger('weappAccess'); if (duration >= slowThreshold) { accessLogger.warn(JSON.stringify(logData)); } else { accessLogger.info(JSON.stringify(logData)); } if (requestError || ctx.status >= 500 || (typeof businessCode === 'number' && businessCode < 0)) { const errorData = Object.assign({}, logData, { error: requestError ? (requestError.stack || requestError.message || requestError.toString()) : responseBody && responseBody.msg, }); ctx.getLogger('weappError').error(JSON.stringify(errorData)); } } }; };