feat(logs): 활동 로그 다이얼로그 상세 정보 표시 + 에러 정보 보강
- logs API: longtext로 저장된 details를 JSON 객체로 파싱해 반환 - 응답 스키마에 additionalProperties: true 추가 (fast-json-stringify가 스키마 미정의 키를 제거하던 문제 해결) - scheduler 에러 로그: err.cause / err.code / err.causeCode 함께 기록 (fetch failed 등 모호한 메시지의 진짜 원인 식별 가능) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
9e3bff9762
commit
6a24b997dd
2 changed files with 29 additions and 4 deletions
|
|
@ -9,6 +9,20 @@ const REDIS_PREFIX = 'bot:status:';
|
|||
const TIMEZONE = 'Asia/Seoul';
|
||||
const MAX_CONSECUTIVE_ERRORS = 10;
|
||||
|
||||
/**
|
||||
* 에러 객체에서 활동 로그용 details 구성
|
||||
* - err.cause(Node fetch failed의 진짜 원인 등), err.code를 함께 포함
|
||||
*/
|
||||
function buildErrorDetails(err) {
|
||||
const d = { error: err.message };
|
||||
if (err.code) d.code = err.code;
|
||||
if (err.cause) {
|
||||
d.cause = err.cause.message || String(err.cause);
|
||||
if (err.cause.code) d.causeCode = err.cause.code;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
async function schedulerPlugin(fastify, opts) {
|
||||
const tasks = new Map();
|
||||
const burstTimers = new Map(); // weekly 모드 내부 setInterval 핸들
|
||||
|
|
@ -269,7 +283,7 @@ async function schedulerPlugin(fastify, opts) {
|
|||
action: 'error',
|
||||
category: 'sync',
|
||||
summary: `${botId} 동기화 오류: ${err.message}`,
|
||||
details: { error: err.message },
|
||||
details: buildErrorDetails(err),
|
||||
});
|
||||
}
|
||||
if (consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
|
||||
|
|
@ -279,7 +293,7 @@ async function schedulerPlugin(fastify, opts) {
|
|||
action: 'stop',
|
||||
category: 'bot',
|
||||
summary: `${botId} 연속 ${MAX_CONSECUTIVE_ERRORS}회 실패로 자동 정지`,
|
||||
details: { error: err.message, consecutiveErrors },
|
||||
details: { ...buildErrorDetails(err), consecutiveErrors },
|
||||
});
|
||||
try {
|
||||
await stopBot(botId);
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ export default async function logsRoutes(fastify) {
|
|||
target_type: { type: 'string', nullable: true },
|
||||
target_id: { type: 'integer', nullable: true },
|
||||
summary: { type: 'string' },
|
||||
details: { type: 'object', nullable: true },
|
||||
details: { type: 'object', nullable: true, additionalProperties: true },
|
||||
created_at: { type: 'string' },
|
||||
},
|
||||
},
|
||||
|
|
@ -147,8 +147,19 @@ export default async function logsRoutes(fastify) {
|
|||
[...params, limit, offset]
|
||||
);
|
||||
|
||||
// details는 longtext(JSON 문자열)로 저장되어 있으므로 객체로 파싱
|
||||
const parsedLogs = logs.map(log => {
|
||||
if (!log.details) return log;
|
||||
if (typeof log.details === 'object') return log;
|
||||
try {
|
||||
return { ...log, details: JSON.parse(log.details) };
|
||||
} catch {
|
||||
return { ...log, details: { raw: log.details } };
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
logs,
|
||||
logs: parsedLogs,
|
||||
total,
|
||||
page,
|
||||
limit,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue