Skip to content

Commit b91ea84

Browse files
Merge pull request #481 from CodeForAfrica/ft/capture-api-errors
feat(meedan-sync): add Sentry error tracking for webhook processing
2 parents 512b7df + b4c5cba commit b91ea84

File tree

1 file changed

+54
-3
lines changed

1 file changed

+54
-3
lines changed

src/app/api/meedan-sync/route.ts

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { NextRequest, NextResponse } from "next/server";
22
import { unlink } from "node:fs/promises";
33

4+
import * as Sentry from "@sentry/nextjs";
5+
46
import { getGlobalPayload } from "@/lib/payload";
57
import type { Media, Promise as PromiseDoc } from "@/payload-types";
68
import { downloadFile } from "@/utils/files";
@@ -72,9 +74,11 @@ export const POST = async (request: NextRequest) => {
7274
const configuredSecret = process.env[WEBHOOK_SECRET_ENV_KEY];
7375

7476
if (!configuredSecret) {
75-
console.error(
76-
"meedan-sync:: Missing WEBHOOK_SECRET_KEY environment variable"
77-
);
77+
const message =
78+
"meedan-sync:: Missing WEBHOOK_SECRET_KEY environment variable";
79+
80+
console.error(message);
81+
Sentry.captureMessage(message, "error");
7882
return NextResponse.json(
7983
{ ok: false, updated: false, error: "Service misconfigured" },
8084
{ status: 200 }
@@ -92,11 +96,19 @@ export const POST = async (request: NextRequest) => {
9296
try {
9397
parsed = (await request.json()) as MeedanWebhookPayload;
9498
} catch (_error) {
99+
const message = "meedan-sync:: Failed to parse JSON payload";
100+
101+
console.error(message);
102+
Sentry.captureMessage(message, "error");
95103
return NextResponse.json({ error: "Invalid JSON" }, { status: 400 });
96104
}
97105
const meedanId = normaliseString(parsed?.data?.id);
98106

99107
if (!meedanId) {
108+
const message = "meedan-sync:: Missing Meedan ID";
109+
110+
console.error(message);
111+
Sentry.captureMessage(message, "error");
100112
return NextResponse.json(
101113
{
102114
error: "Missing Meedan ID",
@@ -108,6 +120,10 @@ export const POST = async (request: NextRequest) => {
108120
const imageUrl = normaliseString(parsed?.object?.file?.[0]?.url ?? null);
109121

110122
if (!imageUrl) {
123+
const message = "meedan-sync:: Missing image URL";
124+
125+
console.error(message);
126+
Sentry.captureMessage(message, "error");
111127
return NextResponse.json(
112128
{ error: "No image URL provided" },
113129
{ status: 400 }
@@ -130,6 +146,10 @@ export const POST = async (request: NextRequest) => {
130146
const promise = (docs[0] ?? null) as PromiseDoc | null;
131147

132148
if (!promise) {
149+
const message = "meedan-sync:: Promise not found";
150+
151+
console.error(message);
152+
Sentry.captureMessage(message, "error");
133153
return NextResponse.json({ error: "Promise not found" }, { status: 404 });
134154
}
135155

@@ -171,6 +191,19 @@ export const POST = async (request: NextRequest) => {
171191
}
172192

173193
if (!mediaId) {
194+
Sentry.withScope((scope) => {
195+
scope.setTag("route", "meedan-sync");
196+
scope.setContext("promise", {
197+
id: promise.id,
198+
existingImageId,
199+
meedanId,
200+
imageUrl,
201+
});
202+
Sentry.captureMessage(
203+
"meedan-sync:: Failed to cache image after processing webhook",
204+
"error"
205+
);
206+
});
174207
return NextResponse.json(
175208
{ error: "Failed to cache image" },
176209
{ status: 500 }
@@ -195,11 +228,29 @@ export const POST = async (request: NextRequest) => {
195228
"meedan-sync:: Failed to clean up temp image",
196229
cleanupError
197230
);
231+
232+
Sentry.withScope((scope) => {
233+
scope.setTag("route", "meedan-sync");
234+
scope.setLevel("warning");
235+
scope.setContext("cleanup", {
236+
filePath,
237+
});
238+
Sentry.captureException(cleanupError);
239+
});
198240
}
199241
}
200242
}
201243
} catch (error) {
202244
console.error("meedan-sync:: Failed to process webhook", error);
245+
246+
Sentry.withScope((scope) => {
247+
scope.setTag("route", "meedan-sync");
248+
scope.setContext("payload", {
249+
meedanId,
250+
imageUrl,
251+
});
252+
Sentry.captureException(error);
253+
});
203254
return NextResponse.json(
204255
{ ok: false, updated: false, error: "Failed to process webhook" },
205256
{ status: 200 }

0 commit comments

Comments
 (0)