mirror of
https://github.com/n8n-io/n8n.git
synced 2026-08-29 01:39:24 +08:00
fix: Make QA metrics telemetry truly fire-and-forget (#32597)
Co-authored-by: n8n-cat-bot[bot] <n8n-cat-bot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -101,9 +101,10 @@ GROUP BY 1, 2 ORDER BY 1;
|
||||
```javascript
|
||||
import { sendMetrics, metric } from './send-metrics.mjs';
|
||||
|
||||
await sendMetrics([
|
||||
// Fire-and-forget — best-effort telemetry, must never block CI.
|
||||
sendMetrics([
|
||||
metric('my-metric', 42.0, 'ms', { context: 'value' }),
|
||||
]);
|
||||
]).catch((err) => console.warn(`[metrics] send failed: ${err.message}`));
|
||||
```
|
||||
|
||||
**From a Playwright test:**
|
||||
|
||||
@@ -70,4 +70,10 @@ metrics.push(
|
||||
}),
|
||||
);
|
||||
|
||||
await sendMetrics(metrics, 'build-stats');
|
||||
// Fire-and-forget: don't await. The in-flight fetch is cancelled on process
|
||||
// exit, which is the right trade-off — we drop a data point rather than block
|
||||
// CI on a slow webhook. sendMetrics swallows its own errors, but attach a
|
||||
// .catch defensively in case that ever changes.
|
||||
sendMetrics(metrics, 'build-stats').catch((err) =>
|
||||
console.warn(`[metrics] send failed: ${err.message}`),
|
||||
);
|
||||
|
||||
@@ -85,4 +85,7 @@ if (metrics.length === 0) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
await sendMetrics(metrics, 'docker-stats');
|
||||
// Fire-and-forget: see send-build-stats.mjs for rationale.
|
||||
sendMetrics(metrics, 'docker-stats').catch((err) =>
|
||||
console.warn(`[metrics] send failed: ${err.message}`),
|
||||
);
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
* Shared metrics sender for CI scripts.
|
||||
* See .github/CI-TELEMETRY.md for payload shape and BigQuery schema.
|
||||
*
|
||||
* Usage:
|
||||
* Usage (fire-and-forget — best-effort, never blocks CI):
|
||||
* import { sendMetrics, metric } from './send-metrics.mjs';
|
||||
* await sendMetrics([metric('build-duration', 45.2, 's', { package: '@n8n/cli' })]);
|
||||
* sendMetrics([metric('build-duration', 45.2, 's', { package: '@n8n/cli' })])
|
||||
* .catch((err) => console.warn(`[metrics] send failed: ${err.message}`));
|
||||
*
|
||||
* Env: QA_METRICS_WEBHOOK_URL, QA_METRICS_WEBHOOK_USER, QA_METRICS_WEBHOOK_PASSWORD
|
||||
*/
|
||||
@@ -78,22 +79,31 @@ export async function sendMetrics(metrics, benchmarkName = null) {
|
||||
const payload = { ...buildContext(benchmarkName), metrics };
|
||||
const basicAuth = Buffer.from(`${webhookUser}:${webhookPassword}`).toString('base64');
|
||||
|
||||
const response = await fetch(webhookUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Basic ${basicAuth}`,
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
signal: AbortSignal.timeout(30_000),
|
||||
});
|
||||
// Best-effort telemetry: never throw into the caller. Slow/down webhook
|
||||
// becomes a one-line warning instead of an uncaught rejection. 5s caps
|
||||
// wall-time in callers that do await this; fire-and-forget callers exit
|
||||
// before then anyway.
|
||||
try {
|
||||
const response = await fetch(webhookUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Basic ${basicAuth}`,
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
signal: AbortSignal.timeout(5_000),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const body = await response.text().catch(() => '');
|
||||
throw new Error(
|
||||
`Webhook failed: ${response.status} ${response.statusText}${body ? `\n${body}` : ''}`,
|
||||
);
|
||||
if (!response.ok) {
|
||||
const body = await response.text().catch(() => '');
|
||||
console.warn(
|
||||
`[metrics] webhook ${response.status} ${response.statusText}${body ? `\n${body}` : ''}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Sent ${metrics.length} metric(s): ${response.status}`);
|
||||
} catch (err) {
|
||||
console.warn(`[metrics] send failed (non-fatal): ${err.message}`);
|
||||
}
|
||||
|
||||
console.log(`Sent ${metrics.length} metric(s): ${response.status}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user