aboutsummaryrefslogtreecommitdiffstats
path: root/packages/trpc/index.ts
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2025-07-06 18:07:56 +0000
committerMohamed Bassem <me@mbassem.com>2025-07-06 18:09:05 +0000
commitb60ece578304df21602d39c7022a7a4dbc6437e0 (patch)
treea5e3395b0b3b5c9bb01566bf68aa21334fd13784 /packages/trpc/index.ts
parentcfa0385b4dcd37f9cc29a15f94a59a4f48dd05fb (diff)
downloadkarakeep-b60ece578304df21602d39c7022a7a4dbc6437e0.tar.zst
feat: Add prometheus monitoring. Fixes #758
Diffstat (limited to 'packages/trpc/index.ts')
-rw-r--r--packages/trpc/index.ts42
1 files changed, 34 insertions, 8 deletions
diff --git a/packages/trpc/index.ts b/packages/trpc/index.ts
index e34e56eb..90f37ae4 100644
--- a/packages/trpc/index.ts
+++ b/packages/trpc/index.ts
@@ -5,6 +5,12 @@ import { ZodError } from "zod";
import type { db } from "@karakeep/db";
import serverConfig from "@karakeep/shared/config";
+import {
+ apiErrorsTotalCounter,
+ apiRequestDurationSummary,
+ apiRequestsTotalCounter,
+} from "./stats";
+
interface User {
id: string;
name?: string | null | undefined;
@@ -36,6 +42,11 @@ const t = initTRPC.context<Context>().create({
transformer: superjson,
errorFormatter(opts) {
const { shape, error } = opts;
+ apiErrorsTotalCounter.inc({
+ type: opts.type,
+ path: opts.path,
+ code: error.code,
+ });
return {
...shape,
data: {
@@ -51,15 +62,30 @@ const t = initTRPC.context<Context>().create({
export const createCallerFactory = t.createCallerFactory;
// Base router and procedure helpers
export const router = t.router;
-export const procedure = t.procedure.use(function isDemoMode(opts) {
- if (serverConfig.demoMode && opts.type == "mutation") {
- throw new TRPCError({
- message: "Mutations are not allowed in demo mode",
- code: "FORBIDDEN",
+export const procedure = t.procedure
+ .use(function isDemoMode(opts) {
+ if (serverConfig.demoMode && opts.type == "mutation") {
+ throw new TRPCError({
+ message: "Mutations are not allowed in demo mode",
+ code: "FORBIDDEN",
+ });
+ }
+ return opts.next();
+ })
+ .use(async (opts) => {
+ const end = apiRequestDurationSummary.startTimer({
+ path: opts.path,
+ type: opts.type,
});
- }
- return opts.next();
-});
+ const res = await opts.next();
+ apiRequestsTotalCounter.inc({
+ type: opts.type,
+ path: opts.path,
+ is_error: res.ok ? 0 : 1,
+ });
+ end();
+ return res;
+ });
export const publicProcedure = procedure;
export const authedProcedure = procedure.use(function isAuthed(opts) {