52 lines
1.9 KiB
TypeScript
52 lines
1.9 KiB
TypeScript
/** 관리자 장애 기록에서도 연결 URL과 인증값을 보존하지 않는다. */
|
|
export const sanitizeRuntimeErrorText = (text: string): string =>
|
|
text
|
|
.replace(/\b(?:https?|postgres(?:ql)?|rediss?):\/\/[^\s"'<>]+/gi, '[REDACTED_URL]')
|
|
.replace(/\bBearer\s+[^\s"',;]+/gi, 'Bearer [REDACTED]')
|
|
.replace(
|
|
/((?:password|passwd|token|secret|authorization|cookie|api[_-]?key)["']?\s*[:=]\s*)(?:"[^"\n]*"|'[^'\n]*'|[^\s,;]+)/gi,
|
|
'$1[REDACTED]'
|
|
)
|
|
.slice(0, 2000);
|
|
|
|
export const describeRuntimeError = (error: unknown): { code: string; message: string; frames: string[] } => ({
|
|
code: error instanceof Error ? error.name.slice(0, 100) : 'RuntimeError',
|
|
message: sanitizeRuntimeErrorText(error instanceof Error ? error.message : String(error)),
|
|
frames:
|
|
error instanceof Error
|
|
? (error.stack ?? '')
|
|
.split('\n')
|
|
.filter((line) => /^\s*at\s/.test(line))
|
|
.slice(0, 8)
|
|
.map(sanitizeRuntimeErrorText)
|
|
: [],
|
|
});
|
|
|
|
export interface ProfileRuntimeDiagnostics {
|
|
profileName: string;
|
|
checkedAt: string;
|
|
database: 'AVAILABLE' | 'UNAVAILABLE' | 'UNINITIALIZED';
|
|
processObservation: 'AVAILABLE' | 'UNAVAILABLE';
|
|
processes: Array<{ name: string; status: string; restartCount: number; exitCode: number | null }>;
|
|
lease: {
|
|
ownerId: string;
|
|
fencingEpoch: string;
|
|
heartbeatAt: string;
|
|
leaseUntil: string;
|
|
heartbeatAgeMs: number;
|
|
valid: boolean;
|
|
clockReady: boolean;
|
|
} | null;
|
|
clock: {
|
|
phase: string;
|
|
revision: string;
|
|
tick: string | null;
|
|
lastTurnTick: string | null;
|
|
year: number;
|
|
month: number;
|
|
wallAnchor: string | null;
|
|
recoveryStartWallAt: string | null;
|
|
recoveryEndTick: string | null;
|
|
} | null;
|
|
}
|