Guides / Platforms & Tools
Inngest has its own dashboard, but checking it means switching context. Logging job events to LogIt puts failures in your existing event stream — and Smart Actions can alert you when jobs fail repeatedly.
// lib/logit-job.ts
import { logit } from "@/lib/logit";
export async function withJobLogging<T>(
jobName: string,
context: Record<string, unknown>,
fn: () => Promise<T>
): Promise<T> {
await logit.now("jobs", {
event: "Job started",
description: jobName,
icon: "⚙️",
notify: false,
tags: { job: jobName, status: "started" },
metadata: context,
});
try {
const result = await fn();
await logit.now("jobs", {
event: "Job completed",
description: `${jobName} succeeded`,
icon: "✅",
notify: false,
tags: { job: jobName, status: "completed" },
metadata: context,
});
return result;
} catch (err) {
await logit.now("jobs", {
event: "Job failed",
description: `${jobName} — ${err instanceof Error ? err.message : String(err)}`,
icon: "❌",
notify: true,
tags: { job: jobName, status: "failed" },
metadata: { ...context, error: err instanceof Error ? err.message : String(err) },
});
throw err; // re-throw so Inngest retries
}
}
// inngest/functions/send-onboarding-email.ts
import { inngest } from "./client";
import { withJobLogging } from "@/lib/logit-job";
export const sendOnboardingEmail = inngest.createFunction(
{ id: "send-onboarding-email" },
{ event: "user/signup.completed" },
async ({ event, step }) => {
await withJobLogging(
"send-onboarding-email",
{ eventId: event.id, email: event.data.email },
async () => {
await step.run("send-email", async () => {
await sendEmail(event.data.email, "welcome");
});
}
);
}
);
| Field | Value |
|---|---|
| Name | Job failure spike |
| Channel | jobs |
| Event name | Job failed |
| Threshold | 5 |
| Window | 10 minutes |
| Cooldown | 30 minutes |
| Action | Push notification |
job tag to filter the dashboard to a specific function's history.metadata by recording start time and computing elapsed ms at completion.Try LogIt free
7-day trial. No credit card required.