Skip to content

Commit 51c96f3

Browse files
committed
temp log
1 parent fc75ad2 commit 51c96f3

2 files changed

Lines changed: 90 additions & 10 deletions

File tree

‎apps/api/src/index.ts‎

Lines changed: 86 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,49 @@
11
import "./polyfills/compression";
22
import { auth } from "@databuddy/auth";
3-
import { appRouter, createRPCContext } from "@databuddy/rpc";
3+
import {
4+
appRouter,
5+
createAbortSignalInterceptor,
6+
createRPCContext,
7+
recordORPCError,
8+
setupUncaughtErrorHandlers,
9+
} from "@databuddy/rpc";
410
import { logger } from "@databuddy/shared/logger";
511
import cors from "@elysiajs/cors";
6-
import { onError } from "@orpc/server";
12+
import { context } from "@opentelemetry/api";
13+
import { ORPCError, onError } from "@orpc/server";
714
import { RPCHandler } from "@orpc/server/fetch";
815
import { autumnHandler } from "autumn-js/elysia";
916
import { Elysia } from "elysia";
17+
import {
18+
endRequestSpan,
19+
initTracing,
20+
shutdownTracing,
21+
startRequestSpan,
22+
} from "./lib/tracing";
1023
import { assistant } from "./routes/assistant";
1124
import { exportRoute } from "./routes/export";
1225
import { health } from "./routes/health";
1326
import { publicApi } from "./routes/public";
1427
import { query } from "./routes/query";
1528

29+
initTracing();
30+
setupUncaughtErrorHandlers();
31+
1632
const rpcHandler = new RPCHandler(appRouter, {
1733
interceptors: [
34+
createAbortSignalInterceptor(),
1835
onError((error) => {
1936
logger.error(error);
2037
}),
2138
],
2239
});
2340

2441
const app = new Elysia()
42+
.state("tracing", {
43+
span: null as ReturnType<typeof startRequestSpan>["span"] | null,
44+
activeContext: null as ReturnType<typeof context.active> | null | undefined,
45+
startTime: 0,
46+
})
2547
.use(
2648
cors({
2749
credentials: true,
@@ -35,6 +57,31 @@ const app = new Elysia()
3557
)
3658
.use(publicApi)
3759
.use(health)
60+
.onBeforeHandle(function startTrace({ request, path, store }) {
61+
const method = request.method;
62+
const startTime = Date.now();
63+
64+
// Extract route from path (e.g., "/rpc/websites.list" -> "websites.list")
65+
const route = path.startsWith("/rpc/") ? path.slice(5) : path;
66+
const { span, activeContext } = startRequestSpan(
67+
method,
68+
request.url,
69+
route
70+
);
71+
72+
// Store span, context, and start time in Elysia store
73+
store.tracing = {
74+
span,
75+
activeContext,
76+
startTime,
77+
};
78+
})
79+
.onAfterHandle(function endTrace({ response, store }) {
80+
if (store.tracing?.span && store.tracing.startTime) {
81+
const statusCode = response instanceof Response ? response.status : 200;
82+
endRequestSpan(store.tracing.span, statusCode, store.tracing.startTime);
83+
}
84+
})
3885
.use(
3986
autumnHandler({
4087
identify: async ({ request }) => {
@@ -62,17 +109,35 @@ const app = new Elysia()
62109
.use(exportRoute)
63110
.all(
64111
"/rpc/*",
65-
async ({ request }) => {
112+
async ({ request, store }) => {
66113
try {
67114
const rpcContext = await createRPCContext({
68115
headers: request.headers,
69116
});
70-
const { response } = await rpcHandler.handle(request, {
71-
prefix: "/rpc",
72-
context: rpcContext,
73-
});
117+
118+
const handler = async () => {
119+
const { response } = await rpcHandler.handle(request, {
120+
prefix: "/rpc",
121+
context: rpcContext,
122+
});
123+
return response;
124+
};
125+
126+
const activeContext = store.tracing?.activeContext;
127+
const response = activeContext
128+
? await context.with(activeContext, handler)
129+
: await handler();
130+
74131
return response ?? new Response("Not Found", { status: 404 });
75132
} catch (error) {
133+
// Record ORPC errors in OpenTelemetry
134+
if (error instanceof ORPCError) {
135+
recordORPCError({
136+
code: error.code,
137+
message: error.message,
138+
});
139+
}
140+
76141
logger.error({ error }, "RPC handler failed");
77142
return new Response("Internal Server Error", { status: 500 });
78143
}
@@ -81,7 +146,12 @@ const app = new Elysia()
81146
parse: "none",
82147
}
83148
)
84-
.onError(function handleError({ error, code }) {
149+
.onError(function handleError({ error, code, store }) {
150+
if (store.tracing?.span && store.tracing.startTime) {
151+
const statusCode = code === "NOT_FOUND" ? 404 : 500;
152+
endRequestSpan(store.tracing.span, statusCode, store.tracing.startTime);
153+
}
154+
85155
const errorMessage = error instanceof Error ? error.message : String(error);
86156
logger.error({ error, code }, errorMessage);
87157

@@ -100,12 +170,18 @@ export default {
100170
port: 3001,
101171
};
102172

103-
process.on("SIGINT", () => {
173+
process.on("SIGINT", async () => {
104174
logger.info("SIGINT received, shutting down gracefully...");
175+
await shutdownTracing().catch((error) =>
176+
logger.error({ error }, "Shutdown error")
177+
);
105178
process.exit(0);
106179
});
107180

108-
process.on("SIGTERM", () => {
181+
process.on("SIGTERM", async () => {
109182
logger.info("SIGTERM received, shutting down gracefully...");
183+
await shutdownTracing().catch((error) =>
184+
logger.error({ error }, "Shutdown error")
185+
);
110186
process.exit(0);
111187
});

‎packages/rpc/src/orpc.ts‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ import {
88
} from "./lib/otel";
99

1010
export const createRPCContext = async (opts: { headers: Headers }) => {
11+
1112
const session = await auth.api.getSession({
1213
headers: opts.headers,
1314
});
1415

16+
console.log("createRPCContext", session);
17+
console.log("createRPCContext", opts.headers);
1518
return {
1619
db,
1720
auth,
@@ -46,6 +49,7 @@ export const protectedProcedure = os.use(({ context, next }) => {
4649
}
4750

4851
if (!(context.user && context.session)) {
52+
console.log("UNAUTHORIZED", context.user, context.session);
4953
recordORPCError({ code: "UNAUTHORIZED" });
5054
throw new ORPCError("UNAUTHORIZED");
5155
}

0 commit comments

Comments
 (0)