Skip to content

Commit

Permalink
chore(store-indexer): setup Sentry middleware in indexer (#2054)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kooshaba committed Dec 11, 2023
1 parent 5ab67e3 commit 85d16e4
Show file tree
Hide file tree
Showing 5 changed files with 571 additions and 16 deletions.
5 changes: 5 additions & 0 deletions .changeset/large-schools-grow.md
@@ -0,0 +1,5 @@
---
"@latticexyz/store-indexer": patch
---

Added a Sentry middleware and `SENTRY_DNS` environment variable to the postgres indexer.
6 changes: 6 additions & 0 deletions packages/store-indexer/bin/postgres-frontend.ts
Expand Up @@ -11,6 +11,7 @@ import postgres from "postgres";
import { frontendEnvSchema, parseEnv } from "./parseEnv";
import { createQueryAdapter } from "../src/postgres/deprecated/createQueryAdapter";
import { apiRoutes } from "../src/postgres/apiRoutes";
import { registerSentryMiddlewares } from "../src/sentry";

const env = parseEnv(
z.intersection(
Expand All @@ -24,6 +25,11 @@ const env = parseEnv(
const database = postgres(env.DATABASE_URL);

const server = new Koa();

if (process.env.SENTRY_DSN) {
registerSentryMiddlewares(server);
}

server.use(cors());
server.use(apiRoutes(database));

Expand Down
3 changes: 3 additions & 0 deletions packages/store-indexer/package.json
Expand Up @@ -42,6 +42,9 @@
"@latticexyz/protocol-parser": "workspace:*",
"@latticexyz/store": "workspace:*",
"@latticexyz/store-sync": "workspace:*",
"@sentry/node": "^7.86.0",
"@sentry/profiling-node": "^1.2.6",
"@sentry/utils": "^7.86.0",
"@trpc/client": "10.34.0",
"@trpc/server": "10.34.0",
"accepts": "^1.3.8",
Expand Down
105 changes: 105 additions & 0 deletions packages/store-indexer/src/sentry.ts
@@ -0,0 +1,105 @@
import * as Sentry from "@sentry/node";
import { ProfilingIntegration } from "@sentry/profiling-node";
import { stripUrlQueryAndFragment } from "@sentry/utils";
import { debug } from "./debug";
import Koa from "koa";

Sentry.init({
dsn: process.env.SENTRY_DSN,
integrations: [
// Automatically instrument Node.js libraries and frameworks
...Sentry.autoDiscoverNodePerformanceMonitoringIntegrations(),
new ProfilingIntegration(),
],
// Performance Monitoring
tracesSampleRate: 1.0,
// Set sampling rate for profiling - this is relative to tracesSampleRate
profilesSampleRate: 1.0,
});

const requestHandler: Koa.Middleware = (ctx, next) => {
return new Promise<void>((resolve, reject) => {
Sentry.runWithAsyncContext(async () => {
const hub = Sentry.getCurrentHub();
hub.configureScope((scope) =>
scope.addEventProcessor((event) =>
Sentry.addRequestDataToEvent(event, ctx.request, {
include: {
user: false,
},
})
)
);

try {
await next();
} catch (err) {
reject(err);
}
resolve();
});
});
};

// This tracing middleware creates a transaction per request
const tracingMiddleWare: Koa.Middleware = async (ctx, next) => {
const reqMethod = (ctx.method || "").toUpperCase();
const reqUrl = ctx.url && stripUrlQueryAndFragment(ctx.url);

// Connect to trace of upstream app
let traceparentData;
if (ctx.request.get("sentry-trace")) {
traceparentData = Sentry.extractTraceparentData(ctx.request.get("sentry-trace"));
}

const transaction = Sentry.startTransaction({
name: `${reqMethod} ${reqUrl}`,
op: "http.server",
...traceparentData,
});

ctx.__sentry_transaction = transaction;

// We put the transaction on the scope so users can attach children to it
Sentry.getCurrentHub().configureScope((scope) => {
scope.setSpan(transaction);
});

ctx.res.on("finish", () => {
// Push `transaction.finish` to the next event loop so open spans have a chance to finish before the transaction closes
setImmediate(() => {
// If you're using koa router, set the matched route as transaction name
if (ctx._matchedRoute) {
const mountPath = ctx.mountPath || "";
transaction.setName(`${reqMethod} ${mountPath}${ctx._matchedRoute}`);
}

transaction.setHttpStatus(ctx.status);
transaction.finish();
});
});

await next();
};

const errorHandler: Koa.Middleware = async (ctx, next) => {
try {
await next();
} catch (err) {
Sentry.withScope((scope) => {
scope.addEventProcessor((event) => {
return Sentry.addRequestDataToEvent(event, ctx.request);
});
Sentry.captureException(err);
});
throw err;
}
};

export const registerSentryMiddlewares = (server: Koa): void => {
debug("Registering Sentry middlewares");

server.use(errorHandler);
server.use(requestHandler);
server.use(tracingMiddleWare);
};

0 comments on commit 85d16e4

Please sign in to comment.