feat: record AP parsing failures, save activity in db for 24h

This commit is contained in:
Julian Lam
2026-04-01 15:08:53 -04:00
parent fa0b72e2a2
commit f008a65ea2
4 changed files with 16 additions and 1 deletions

View File

@@ -65,7 +65,8 @@
"content.break-string-help": "This delimiter can be manually inserted by power users when composing new topics. It instructs NodeBB to use content up until that point as part of the <code>summary</code>. If this string is not used, then the character count fallback applies. (Default: <code>[...]</code>)",
"content.world-default-cid": "Default category ID for &quot;World&quot; page composer",
"analytics.intro": "From this page you can view the state of your instance's federation with other servers",
"analytics.intro": "This page provides an overview of the state of your forum's federation with other instances/servers",
"analytics.details": "NodeBB tracks ActivityPub activity receipts and sends, and you are able to view them by hostname, either hourly or daily. Note that the metrics are only incremented on <em>successful</em> receipts and sends.",
"analytics.by-hostname": "Filter by Hostname",
"analytics.received": "Received Activities",
"analytics.sent": "Sent Activites",

View File

@@ -481,6 +481,18 @@ ActivityPub.record.send = async ({ type, target }) => {
]);
};
ActivityPub.record.receiptError = async (body) => {
const { id, actor } = body;
const now = Date.now();
const { hostname } = new URL(actor);
await Promise.all([
db.sortedSetAdd('ap.errors', now, id),
db.set(`ap.errors:${id}`, JSON.stringify(body)),
analytics.increment(['ap.inErr', `ap.inErr:byHost:${hostname}`]),
]);
await db.expire(`ap.errors:${id}`, 60 * 60 * 24); // 24 hours
};
ActivityPub.buildRecipients = async function (object, options) {
/**
* - Builds a list of targets for activitypub.send to consume

View File

@@ -272,6 +272,7 @@ Controller.postInbox = async (req, res) => {
await activitypub.record.receipt(req.body);
await helpers.formatApiResponse(202, res);
} catch (e) {
activitypub.record.receiptError(req.body);
helpers.formatApiResponse(500, res, e).catch(err => winston.error(err.stack));
}
};

View File

@@ -5,6 +5,7 @@
<div id="spy-container" class="col-12 col-md-8 px-0 mb-4" tabindex="0">
<div class="mb-4">
<p class="lead">[[admin/settings/activitypub:analytics.intro]]</p>
<p>[[admin/settings/activitypub:analytics.details]]</p>
<div class="mb-3 row">
<div class="col-6">