Skip to content

Commit

Permalink
feat(README.md): add OpenNext section to explain how to deploy on AWS…
Browse files Browse the repository at this point in the history
… using Serverless Framework plugin

fix(app/_actions.ts): import Notifier from @airbrake/node to use it in sendAirbrakeNodeException function
feat(app/_actions.ts): add sendAirbrakeNodeException function to send test exception to Airbrake using Node.js
feat(components/NoData.tsx): add button to send test exception to Airbrake using Node.js
feat(next.config.js): add @airbrake/node to serverComponentsExternalPackages in experimental configuration
feat(package.json): add @airbrake/node dependency to the project
  • Loading branch information
masterkain committed May 22, 2023
1 parent 0215ac1 commit 8aa0ccd
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 17 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ make run

You can override the default values in the `docker-compose.yml` file by creating a `docker-compose.override.yml` file in the same directory. This file is ignored by Git and will not be committed to the repository.

### OpenNext

For deploying on AWS beside Amplify you might want to use [OpenNext](https://github.com/serverless-stack/open-next) which is a Serverless Framework plugin for deploying Next.js applications on AWS.

## Setup

Please view all the available configuration variables in the [`.env.dist`](https://github.com/icoretech/airbroke/blob/main/.env.dist) file.
Expand Down
27 changes: 27 additions & 0 deletions app/_actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { prisma } from '@/lib/db';
import generateUniqueProjectKey from '@/lib/keygen';
import { parseGitURL } from '@/lib/parseGitUrl';
import { Notifier as AirbrakeNodeNotifier } from '@airbrake/node';
import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';

Expand Down Expand Up @@ -79,3 +80,29 @@ export async function deleteProject(projectId: bigint): Promise<void> {
revalidatePath('/projects');
redirect('/projects');
}

export async function sendAirbrakeNodeException(projectId: bigint, host: string) {
const project = await prisma.project.findUnique({ where: { id: projectId } });
if (!project) {
throw new Error('Project not found');
}

const airbrake = new AirbrakeNodeNotifier({
projectId: 1,
projectKey: project.api_key,
environment: 'test',
host: host,
remoteConfig: false,
performanceStats: false,
queryStats: false,
});

try {
throw new Error('This is a test exception from Airbroke');
} catch (err) {
await airbrake.notify(err);
}

revalidatePath(`/projects/${project.id}/notices`) // mm, this sometimes fails, https://www.reddit.com/r/nextjs/comments/13ilupe/nextjs_134_error_invariant_static_generation/
redirect(`/projects/${project.id}/notices`);
}
47 changes: 31 additions & 16 deletions components/NoData.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client';

import { sendAirbrakeNodeException } from '@/app/_actions';
import { Notifier } from '@airbrake/browser';
import { project } from '@prisma/client';
import { useRouter } from 'next/navigation';
Expand All @@ -10,7 +11,7 @@ export default function NoData({ project }: { project: project }) {
const [isPending, startTransition] = useTransition();
const { refresh } = useRouter();

const sendTestException = async () => {
const sendAirbrakeJsException = async () => {
const airbrake = new Notifier({
projectId: 1,
projectKey: project.api_key,
Expand All @@ -19,11 +20,10 @@ export default function NoData({ project }: { project: project }) {
remoteConfig: false,
performanceStats: false,
queryStats: false,
queueStats: false,
});

await airbrake.notify(new Error('This is a test exception from Airbroke'));
startTransition(() => refresh());
refresh();
};

return (
Expand All @@ -32,19 +32,34 @@ export default function NoData({ project }: { project: project }) {

<h3 className="my-5 text-sm font-semibold">{'No exceptions recorded'}</h3>

<button
onClick={sendTestException}
disabled={isPending}
className="inline-flex items-center rounded-md bg-indigo-400/10 px-3 py-2 text-sm font-semibold text-indigo-400 shadow-sm ring-indigo-400/30 transition-colors duration-200 hover:bg-indigo-500 hover:text-indigo-200 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:bg-indigo-400"
>
{isPending ? (
<SlDisc className="-ml-0.5 mr-1.5 h-5 w-5 animate-spin" aria-hidden="true" />
) : (
<SlEnergy className="-ml-0.5 mr-1.5 h-5 w-5" aria-hidden="true" />
)}

<span>{isPending ? 'Sending...' : 'Send a test exception'}</span>
</button>
<div className="flex flex-col items-center">
<button
onClick={() => startTransition(() => sendAirbrakeJsException())}
disabled={isPending}
className="mb-4 inline-flex items-center rounded-md bg-indigo-400/10 px-3 py-2 text-sm font-semibold text-indigo-400 shadow-sm ring-indigo-400/30 transition-colors duration-200 hover:bg-indigo-500 hover:text-indigo-200 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:text-white"
>
{isPending ? (
<SlDisc className="-ml-0.5 mr-1.5 h-5 w-5 animate-spin" aria-hidden="true" />
) : (
<SlEnergy className="-ml-0.5 mr-1.5 h-5 w-5" aria-hidden="true" />
)}

<span>{isPending ? 'Sending...' : 'Send a test exception (Airbrake JS)'}</span>
</button>
<button
onClick={() => startTransition(() => sendAirbrakeNodeException(project.id, window.location.origin))}
disabled={isPending}
className="inline-flex items-center rounded-md bg-indigo-400/10 px-3 py-2 text-sm font-semibold text-indigo-400 shadow-sm ring-indigo-400/30 transition-colors duration-200 hover:bg-indigo-500 hover:text-indigo-200 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-500 disabled:text-white"
>
{isPending ? (
<SlDisc className="-ml-0.5 mr-1.5 h-5 w-5 animate-spin" aria-hidden="true" />
) : (
<SlEnergy className="-ml-0.5 mr-1.5 h-5 w-5" aria-hidden="true" />
)}

<span>{isPending ? 'Sending...' : 'Send a test exception (Airbrake Node)'}</span>
</button>
</div>
</div>
);
}
2 changes: 1 addition & 1 deletion next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const nextConfig = {
},
experimental: {
serverActions: true,
serverComponentsExternalPackages: ['@prisma/client', 'chatgpt', '@octokit'],
serverComponentsExternalPackages: ['@prisma/client', 'chatgpt', '@octokit', '@airbrake/node'],
},
async rewrites() {
return [
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"dependencies": {
"@airbrake/browser": "^2.1.8",
"@airbrake/node": "^2.1.8",
"@headlessui/react": "^1.7.14",
"@prisma/client": "4.14.1",
"@tailwindcss/forms": "^0.5.3",
Expand Down
13 changes: 13 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ __metadata:
languageName: node
linkType: hard

"@airbrake/node@npm:^2.1.8":
version: 2.1.8
resolution: "@airbrake/node@npm:2.1.8"
dependencies:
"@airbrake/browser": ^2.1.8
cross-fetch: ^3.1.5
error-stack-parser: ^2.0.4
tdigest: ^0.1.1
checksum: 59dca142aee8b0efc0ff90438df27c6cd641307463e364f7b56e2bc48a9c19dc5c599fc1417443e00319bb5040d41456b34a4e139a6f47dcbacc14b5788fbf03
languageName: node
linkType: hard

"@alloc/quick-lru@npm:^5.2.0":
version: 5.2.0
resolution: "@alloc/quick-lru@npm:5.2.0"
Expand Down Expand Up @@ -1907,6 +1919,7 @@ __metadata:
resolution: "airbroke@workspace:."
dependencies:
"@airbrake/browser": ^2.1.8
"@airbrake/node": ^2.1.8
"@headlessui/react": ^1.7.14
"@jest/globals": ^29.5.0
"@prisma/client": 4.14.1
Expand Down

0 comments on commit 8aa0ccd

Please sign in to comment.