diff --git a/components/HitCounter/HitCounter.tsx b/components/HitCounter/HitCounter.tsx
index 3009c7d5..ffe66529 100644
--- a/components/HitCounter/HitCounter.tsx
+++ b/components/HitCounter/HitCounter.tsx
@@ -14,22 +14,26 @@ const HitCounter = ({ slug, className }: HitCounterProps) => {
revalidateOnFocus: false,
});
- // show spinning loading indicator if data isn't fetched yet
- if (!data) {
- return ;
- }
+ try {
+ // show spinning loading indicator if data isn't fetched yet
+ if (!data) {
+ return ;
+ }
- // fail secretly
- if (error) {
- return;
- }
+ // fail secretly
+ if (error) {
+ return null;
+ }
- // we have data!
- return (
-
- {data.hits.toLocaleString("en-US")}
-
- );
+ // we have data!
+ return (
+
+ {data.hits.toLocaleString("en-US")}
+
+ );
+ } catch (error) {
+ return null;
+ }
};
export default HitCounter;
diff --git a/components/VNC/VNC.tsx b/components/VNC/VNC.tsx
index 2c2a929b..46347ec1 100644
--- a/components/VNC/VNC.tsx
+++ b/components/VNC/VNC.tsx
@@ -31,7 +31,7 @@ const VNC = ({ server }: VNCProps) => {
terminalRef.current.textContent = `${message}${
anyKey ? "\n\nPress the Any key or refresh the page to continue." : ""
}`;
- } catch (e) {} // eslint-disable-line no-empty
+ } catch (error) {} // eslint-disable-line no-empty
};
// hides the console and show the screen when VM connects
@@ -44,7 +44,7 @@ const VNC = ({ server }: VNCProps) => {
const disconnectVM = () => {
try {
rfbRef.current.disconnect();
- } catch (e) {} // eslint-disable-line no-empty
+ } catch (error) {} // eslint-disable-line no-empty
};
// prepare for possible navigation away from this page, and disconnect if/when it happens
diff --git a/lib/sentry.ts b/lib/sentry.ts
new file mode 100644
index 00000000..71a72a5a
--- /dev/null
+++ b/lib/sentry.ts
@@ -0,0 +1,31 @@
+import * as Sentry from "@sentry/node";
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import * as Tracing from "@sentry/tracing";
+
+// https://docs.sentry.io/platforms/node/configuration/options/
+Sentry.init({
+ dsn: process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN || "",
+ environment: process.env.NODE_ENV || process.env.VERCEL_ENV || process.env.NEXT_PUBLIC_VERCEL_ENV || "",
+ tracesSampleRate: 1.0,
+});
+
+export const logServerError = async (error: string | Error) => {
+ try {
+ // log error to sentry
+ Sentry.captureException(error);
+ // give it 2 seconds to finish sending:
+ // https://docs.sentry.io/platforms/node/configuration/draining/
+ await Sentry.flush(2000);
+ } catch (sentryError) {
+ // cue inception bong
+ console.error("Encountered an error logging an error... We are doomed.", sentryError);
+ }
+
+ // also log the error normally to the Vercel console; will get picked up by log drain
+ console.error(error);
+
+ // we really don't want to return *any* error from logging an error, so just keep it on the dl
+ return true;
+};
+
+export default Sentry;
diff --git a/package.json b/package.json
index 46bdc118..1e23766e 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"@octokit/graphql": "^4.8.0",
"@primer/octicons": "^16.3.1",
"@sentry/node": "^6.17.7",
+ "@sentry/tracing": "^6.17.7",
"classnames": "^2.3.1",
"copy-to-clipboard": "^3.3.1",
"critters": "^0.0.16",
@@ -91,7 +92,7 @@
"@typescript-eslint/eslint-plugin": "^5.11.0",
"@typescript-eslint/parser": "^5.11.0",
"cross-env": "^7.0.3",
- "eslint": "~8.8.0",
+ "eslint": "~8.9.0",
"eslint-config-next": "12.0.10",
"eslint-config-prettier": "~8.3.0",
"eslint-plugin-import": "~2.25.4",
diff --git a/pages/api/contact.ts b/pages/api/contact.ts
index 91ad5dd4..41b556ef 100644
--- a/pages/api/contact.ts
+++ b/pages/api/contact.ts
@@ -1,13 +1,8 @@
-import * as Sentry from "@sentry/node";
import fetch from "node-fetch";
import queryString from "query-string";
+import { logServerError } from "../../lib/sentry";
import type { NextApiRequest, NextApiResponse } from "next";
-Sentry.init({
- dsn: process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN || "",
- environment: process.env.NODE_ENV || process.env.VERCEL_ENV || process.env.NEXT_PUBLIC_VERCEL_ENV || "",
-});
-
// fallback to dummy secret for testing: https://docs.hcaptcha.com/#integration-testing-test-keys
const HCAPTCHA_SITE_KEY =
process.env.HCAPTCHA_SITE_KEY || process.env.NEXT_PUBLIC_HCAPTCHA_SITE_KEY || "10000000-ffff-ffff-ffff-000000000001";
@@ -56,15 +51,12 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
// success! let the client know
return res.status(200).json({ success: true });
} catch (error) {
- console.error(error);
-
+ // extract just the error message to send back to client
const message = error instanceof Error ? error.message : "UNKNOWN_EXCEPTION";
- // don't log PEBCAK errors to sentry
+ // log errors (except PEBCAK) to console and sentry
if (!message.startsWith("USER_")) {
- // log error to sentry, give it 2 seconds to finish sending
- Sentry.captureException(error);
- await Sentry.flush(2000);
+ await logServerError(error);
}
// 500 Internal Server Error
diff --git a/pages/api/hits.ts b/pages/api/hits.ts
index f0887666..eab5dfb0 100644
--- a/pages/api/hits.ts
+++ b/pages/api/hits.ts
@@ -1,14 +1,9 @@
-import * as Sentry from "@sentry/node";
import pRetry from "p-retry";
import faunadb from "faunadb";
import { getAllNotes } from "../../lib/parse-notes";
+import { logServerError } from "../../lib/sentry";
import type { NextApiRequest, NextApiResponse } from "next";
-Sentry.init({
- dsn: process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN || "",
- environment: process.env.NODE_ENV || process.env.VERCEL_ENV || process.env.NEXT_PUBLIC_VERCEL_ENV || "",
-});
-
type PageStats = {
slug: string;
hits: number;
@@ -57,14 +52,12 @@ const handler = async (req: NextApiRequest, res: NextApiResponse) => {
return res.status(200).json(siteStats);
}
} catch (error) {
- console.error(error);
-
- // log error to sentry, give it 2 seconds to finish sending
- Sentry.captureException(error);
- await Sentry.flush(2000);
-
+ // extract just the error message to send back to client
const message = error instanceof Error ? error.message : "Unknown error.";
+ // log full error to console and sentry
+ await logServerError(error);
+
// 500 Internal Server Error
return res.status(500).json({ success: false, message });
}
diff --git a/yarn.lock b/yarn.lock
index 28390cf6..4d720163 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1035,14 +1035,14 @@
resolved "https://registry.yarnpkg.com/@corex/deepmerge/-/deepmerge-2.6.148.tgz#8fa825d53ffd1cbcafce1b6a830eefd3dcc09dd5"
integrity sha512-6QMz0/2h5C3ua51iAnXMPWFbb1QOU1UvSM4bKBw5mzdT+WtLgjbETBBIQZ+Sh9WvEcGwlAt/DEdRpIC3XlDBMA==
-"@eslint/eslintrc@^1.0.5":
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318"
- integrity sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==
+"@eslint/eslintrc@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.1.0.tgz#583d12dbec5d4f22f333f9669f7d0b7c7815b4d3"
+ integrity sha512-C1DfL7XX4nPqGd6jcP01W9pVM1HYCuUkFk1432D7F0v3JSlUIeOYn9oCoi3eoLZ+iwBSb29BMFxxny0YrrEZqg==
dependencies:
ajv "^6.12.4"
debug "^4.3.2"
- espree "^9.2.0"
+ espree "^9.3.1"
globals "^13.9.0"
ignore "^4.0.6"
import-fresh "^3.2.1"
@@ -1359,7 +1359,7 @@
lru_map "^0.3.3"
tslib "^1.9.3"
-"@sentry/tracing@6.17.7":
+"@sentry/tracing@6.17.7", "@sentry/tracing@^6.17.7":
version "6.17.7"
resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.17.7.tgz#f4536683b29bb3ac7ddda5ca49494731cec6b619"
integrity sha512-QzIDHOjjdi/0LTdrK2LTC27YEOODI473KD8KmMJ+r9PmjDeIjNzz4hJlPwQSnXR3Mu/8foxGJGXsAt3LNmKzlQ==
@@ -2801,10 +2801,10 @@ eslint-scope@^5.1.1:
esrecurse "^4.3.0"
estraverse "^4.1.1"
-eslint-scope@^7.1.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153"
- integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==
+eslint-scope@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
+ integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
dependencies:
esrecurse "^4.3.0"
estraverse "^5.2.0"
@@ -2821,17 +2821,17 @@ eslint-visitor-keys@^2.0.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
-eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.2.0:
- version "3.2.0"
- resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz#6fbb166a6798ee5991358bc2daa1ba76cc1254a1"
- integrity sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==
+eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
+ integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
-eslint@~8.8.0:
- version "8.8.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.8.0.tgz#9762b49abad0cb4952539ffdb0a046392e571a2d"
- integrity sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==
+eslint@~8.9.0:
+ version "8.9.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.9.0.tgz#a2a8227a99599adc4342fd9b854cb8d8d6412fdb"
+ integrity sha512-PB09IGwv4F4b0/atrbcMFboF/giawbBLVC7fyDamk5Wtey4Jh2K+rYaBhCAbUyEI4QzB1ly09Uglc9iCtFaG2Q==
dependencies:
- "@eslint/eslintrc" "^1.0.5"
+ "@eslint/eslintrc" "^1.1.0"
"@humanwhocodes/config-array" "^0.9.2"
ajv "^6.10.0"
chalk "^4.0.0"
@@ -2839,10 +2839,10 @@ eslint@~8.8.0:
debug "^4.3.2"
doctrine "^3.0.0"
escape-string-regexp "^4.0.0"
- eslint-scope "^7.1.0"
+ eslint-scope "^7.1.1"
eslint-utils "^3.0.0"
- eslint-visitor-keys "^3.2.0"
- espree "^9.3.0"
+ eslint-visitor-keys "^3.3.0"
+ espree "^9.3.1"
esquery "^1.4.0"
esutils "^2.0.2"
fast-deep-equal "^3.1.3"
@@ -2867,14 +2867,14 @@ eslint@~8.8.0:
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
-espree@^9.2.0, espree@^9.3.0:
- version "9.3.0"
- resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.0.tgz#c1240d79183b72aaee6ccfa5a90bc9111df085a8"
- integrity sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==
+espree@^9.3.1:
+ version "9.3.1"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd"
+ integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==
dependencies:
acorn "^8.7.0"
acorn-jsx "^5.3.1"
- eslint-visitor-keys "^3.1.0"
+ eslint-visitor-keys "^3.3.0"
esprima@^4.0.0:
version "4.0.1"