Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[back-end] Add Glitchtip error tracking #93

Merged
merged 2 commits into from
Nov 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/back-end/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
},
"dependencies": {
"@fastify/cors": "^9.0.1",
"@immobiliarelabs/fastify-sentry": "^8.0.2",
"@mykomap/common": "*",
"@mykomap/node-utils": "*",
"@seriousme/openapi-schema-validator": "^2.2.1",
Expand Down
7 changes: 7 additions & 0 deletions apps/back-end/src/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export class HttpError extends Error {
statusCode: number;
constructor(statusCode: number, message: string) {
super(message);
this.statusCode = statusCode;
}
}
15 changes: 15 additions & 0 deletions apps/back-end/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import fastifySentryPlugin from "@immobiliarelabs/fastify-sentry";
import closeWithGrace from "close-with-grace";
import Fastify from "fastify";
import cors from "@fastify/cors";
Expand Down Expand Up @@ -35,6 +36,20 @@ export const start = async () => {
querystringParser: (str) => qs.parse(str),
});

// The Sentry error handler must be the first plugin registered
if (process.env.GLITCHTIP_KEY) {
console.log("Initialising Sentry...");
app.register(fastifySentryPlugin, {
dsn: `https://${process.env.GLITCHTIP_KEY}@app.glitchtip.com/9203`,
environment: process.env.NODE_ENV,
release: __BUILD_INFO__.version.join("."),
// Capture all uncaught or HTTP 4xx and 5xx errors
// Note this doesn't work for TsRestResponseErrors since they skip this middleware
shouldHandleError: (error) =>
!error.statusCode || error.statusCode >= 400,
});
}

// This closes the application with a delay to clear up.
closeWithGrace(
{ delay: closeGraceDelay },
Expand Down
7 changes: 2 additions & 5 deletions apps/back-end/src/routes.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { TsRestResponseError } from "@ts-rest/core";
import { RouterImplementation } from "@ts-rest/fastify";
import { contract } from "@mykomap/common";
import { FastifyPluginOptions } from "fastify";
Expand All @@ -11,6 +10,7 @@ import {
initDatasets,
searchDataset,
} from "./services/datasetService.js";
import { HttpError } from "./errors.js";

/** Provides the shared configuration options for the Mykomap router implementation. */
export interface MykomapRouterConfig extends FastifyPluginOptions {
Expand Down Expand Up @@ -92,10 +92,7 @@ export function MykomapRouter(
// assume it is an Index.
// TODO: extend this method to handle full IDs too
if (!datasetItemIdOrIx.startsWith("@")) {
throw new TsRestResponseError(contract.getDatasetItem, {
status: 400,
body: { message: `We can only handle item indexes right now` },
});
throw new HttpError(400, `We can only handle item indexes right now`);
}

const itemIx = Number(datasetItemIdOrIx.substring(1));
Expand Down
27 changes: 7 additions & 20 deletions apps/back-end/src/services/Dataset.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import fs from "node:fs";
import path from "node:path";
import _ from "lodash";
import { TsRestResponseError } from "@ts-rest/core";
import { z } from "zod";

import {
contract,
PropDefs,
PropDefsFactory,
schemas,
TextSearch,
} from "@mykomap/common";
import { HttpError } from "../errors.js";

// Infer type from Zod schema
type ConfigData = z.infer<typeof schemas.ConfigData>;
Expand Down Expand Up @@ -90,12 +89,10 @@ export class Dataset {

getItem = (itemIx: number) => {
if (!fs.existsSync(path.join(this.folderPath, "items", `${itemIx}.json`))) {
throw new TsRestResponseError(contract.getDatasetItem, {
status: 404,
body: {
message: `can't retrieve data for dataset ${this.id} item @${itemIx}`,
},
});
throw new HttpError(
404,
`Can't retrieve data for dataset ${this.id}, item index @${itemIx}`,
);
}

return JSON.parse(
Expand Down Expand Up @@ -135,12 +132,7 @@ export class Dataset {

const propDef = this?.propDefs[propName];
if (!propDef?.isFiltered())
throw new TsRestResponseError(contract.searchDataset, {
status: 400,
body: {
message: `Unknown propery name '${propName}'`,
},
});
throw new HttpError(400, `Unknown propery name '${propName}'`);

const isMulti = propDef.type === "multi";
const propMatcher = (value: string | string[]) => {
Expand Down Expand Up @@ -218,12 +210,7 @@ export class Dataset {

for (const prop of returnProps) {
if (item[prop] === undefined) {
throw new TsRestResponseError(contract.searchDataset, {
status: 400,
body: {
message: `Unknown propery name '${prop}'`,
},
});
throw new HttpError(400, `Unknown propery name '${prop}'`);
}
strippedItem[prop] = item[prop];
}
Expand Down
13 changes: 3 additions & 10 deletions apps/back-end/src/services/datasetService.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import fs from "node:fs";
import path from "node:path";
import {
AppRoute,
ServerInferResponseBody,
TsRestResponseError,
} from "@ts-rest/core";
import { AppRoute, ServerInferResponseBody } from "@ts-rest/core";

import { contract } from "@mykomap/common";
import { Dataset } from "./Dataset.js";
import { HttpError } from "../errors.js";

type GetConfigBody = ServerInferResponseBody<typeof contract.getConfig, 200>;
type SearchDatasetBody = ServerInferResponseBody<
Expand Down Expand Up @@ -40,11 +37,7 @@ const getDatasetOrThrow404 = (
): Dataset => {
const dataset = datasets[datasetId];

if (!dataset)
throw new TsRestResponseError(appRoute, {
status: 404,
body: { message: `dataset ${datasetId} doesn't exist` },
});
if (!dataset) throw new HttpError(404, `dataset ${datasetId} doesn't exist`);

return dataset;
};
Expand Down
1 change: 0 additions & 1 deletion apps/front-end/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
VITE_API_URL=replace-me
VITE_GLITCHTIP_KEY=replace-me
VITE_MAPTILER_API_KEY=replace-me
6 changes: 4 additions & 2 deletions deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ set -vx
# - PROXY_PORT: the port number being proxied (e.g. '4000')
# - PROXY_PATH: the path being proxied (e.g. '/api')
# - BASE_URL_PATH # not actually used but might be in future?
# - GLITCHTIP_KEY
# - FE_GLITCHTIP_KEY
# - BE_GLITCHTIP_KEY
# - MAPTILER_API_KEY
# - DBUS_SESSION_BUS_ADDRESS: required for service management
# - FIXME the user can write to DEPLOY_DEST, WWW_ROOT
Expand Down Expand Up @@ -84,7 +85,7 @@ cp .tool-versions "$DEPLOY_DEST"
# FIXME these shouldn't be hardwired!
cat >>.env <<EOF
VITE_API_URL=/api
VITE_GLITCHTIP_KEY=${GLITCHTIP_KEY:?}
VITE_GLITCHTIP_KEY=${FE_GLITCHTIP_KEY:?}
VITE_MAPTILER_API_KEY=${MAPTILER_API_KEY:?}
EOF

Expand All @@ -105,6 +106,7 @@ EOF
cat >>"$BE_DEST/.env" <<EOF
SERVER_DATA_ROOT=$DATA_DEST
FASTIFY_PORT=$PROXY_PORT
GLITCHTIP_KEY=${BE_GLITCHTIP_KEY:?}
# root address?
EOF

Expand Down
3 changes: 2 additions & 1 deletion docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ values redacted:
export PROXY_PORT=1$UID
export PROXY_PATH=/api
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$UID/bus
export GLITCHTIP_KEY=*REDACTED*
export FE_GLITCHTIP_KEY=*REDACTED*
export BE_GLITCHTIP_KEY=*REDACTED*
export MAPTILER_API_KEY=*REDACTED*

*Note: paths here should be absolute - relative paths will not work in
Expand Down
Loading
Loading