补充数据库备份上传错误日志

为 OSS 上传失败补充备份对象路径上下文

输出错误 cause 链和网络字段,便于定位 fetch failed

(cherry picked from commit 48ee0eb75dd84e2db95f828b256f233e6618f5d9)
This commit is contained in:
2026-06-30 16:06:41 +08:00
parent 65acf9f429
commit d699036b76
+58 -11
View File
@@ -396,16 +396,21 @@ async function uploadArchive({archivePath, bucket, endpoint, objectKey, accessKe
});
console.log(`[database-backup] 上传 OSS: oss://${bucket}/${objectKey}`);
const response = await fetch(targetUrl, {
method: 'PUT',
headers: {
...headers,
authorization,
'content-length': String(fileStat.size),
},
body: createReadStream(archivePath),
duplex: 'half',
});
let response;
try {
response = await fetch(targetUrl, {
method: 'PUT',
headers: {
...headers,
authorization,
'content-length': String(fileStat.size),
},
body: createReadStream(archivePath),
duplex: 'half',
});
} catch (error) {
throw new Error(`OSS 上传请求失败: oss://${bucket}/${objectKey}`, {cause: error});
}
const responseText = await response.text();
if (!response.ok) {
@@ -584,7 +589,49 @@ async function main() {
}
}
function formatErrorDetails(error) {
if (!error || typeof error !== 'object') {
return '';
}
return ['code', 'errno', 'syscall', 'hostname', 'host', 'port', 'address']
.map((field) => {
const value = error[field];
return value === undefined || value === null || value === '' ? '' : `${field}=${String(value)}`;
})
.filter(Boolean)
.join(' ');
}
function describeError(error) {
const lines = [];
let current = error;
for (let depth = 0; current && depth < 5; depth += 1) {
const label = depth === 0 ? 'error' : `cause[${depth}]`;
if (!(current instanceof Error)) {
lines.push(`${label}: ${String(current)}`);
break;
}
lines.push(`${label}: ${current.name}: ${current.message}`);
const details = formatErrorDetails(current);
if (details) {
lines.push(`${label} details: ${details}`);
}
if (current instanceof AggregateError) {
current.errors.slice(0, 3).forEach((item, index) => {
const itemText = item instanceof Error ? `${item.name}: ${item.message}` : String(item);
const itemDetails = formatErrorDetails(item);
lines.push(`${label}.errors[${index}]: ${itemText}${itemDetails ? ` (${itemDetails})` : ''}`);
});
}
current = current.cause;
}
return lines;
}
main().catch((error) => {
console.error(`[database-backup] ${error instanceof Error ? error.message : String(error)}`);
for (const line of describeError(error)) {
console.error(`[database-backup] ${line}`);
}
process.exit(1);
});