DEV Community

Lutif Ali
Lutif Ali

Posted on • Edited on

Say Goodbye to Paid Sentry Alerts: Get Error Notifications on Slack for Free!

Are you tired of paying for Sentry's Slack integration? What if I told you there's a way to send error notifications to Slack for free? That's right—no more paying for what you can do with a few simple tricks. By leveraging Sentry's webhook, Vercel's edge functions, and Slack’s free API, you can set up a system that gets real-time error alerts sent straight to Slack without shelling out a dime. Intrigued? Let me show you how.

Why Pay for Something You Can Do for Free?

Sentry offers a built-in integration with Slack, but it’s locked behind a paywall. For smaller projects or indie developers, that’s just not worth it. Luckily, we can bypass this by creating a webhook listener on Vercel that formats error notifications and sends them to Slack via the free Slack API.

Ready to ditch the paid plans? Let’s dive in.

Step 1: Configuring the Sentry Webhook (No, It’s Not Hard)

Sentry provides a webhook legacy integration that lets you send error events to external services. Here’s how you hook that up to a free Vercel edge function:

  1. Open Your Sentry Project: Head to your project settings in Sentry.
  2. Enable Webhooks: Under Legacy Integrations, add a new webhook. This is where Sentry will send error data.
  3. Point It to Vercel: Once we set up our Vercel function, you’ll use that URL here. But first, let’s get the listener set up.

Step 2: Vercel Edge Function—The Magic Sauce

If you’re new to Vercel, it’s a serverless platform that allows you to run code at the "edge" for free (within certain limits). We’re going to deploy an edge function that will listen for Sentry events, format them, and send them to Slack. Here’s the code that does it all:

export const config = {
  runtime: 'edge',
};

const sendMessage = async (channel, { level, formatted, environment, email, title, culprit, project }) => {
  console.info({ channel, level, formatted, environment, email, title, culprit, project });
  const isError = level === "error";
  const blocks = [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": `${isError ? ":red_circle:" : ""} *${title}*`,
      },
    },
    {
      "type": "section",
      "fields": [
        {
          "type": "mrkdwn",
          "text": `*Environment:*\n${environment}`,
        },
        {
          "type": "mrkdwn",
          "text": `*Level:*\n${level}`,
        },
        {
          "type": "mrkdwn",
          "text": `*Project:*\n${project}`,
        },
      ],
    },
    {
      "type": "section",
      "fields": [
        {
          "type": "mrkdwn",
          "text": `*User:*\n${email}`,
        },
      ],
    },
    {
      "type": "divider",
    },
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": `*Message:*\n${formatted}`,
      },
    },
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": `*Message:*\n${culprit}`,
      },
    },
    {
      "type": "divider",
    },
  ];

  try {
    const response = await fetch('https://slack.com/api/chat.postMessage', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json; charset=utf-8',
        'Authorization': `Bearer ${process.env.SLACK_ACCESS_TOKEN}`,
      },
      body: JSON.stringify({
        channel,
        blocks,
      }),
    });

    return response.data;
  } catch (e) {
    console.error(e);
  }
};

export default async (req) => {
  const body = await req.json();
  const { project, culprit, event: { level, logentry: { formatted }, user: { email }, environment, metadata: { title } } } = body;

  await sendMessage(process.env.CHANNEL_ID, { level, formatted, environment, email, title, culprit, project });

  return new Response(`Hello from Edge.js! ${body}`);
};
Enter fullscreen mode Exit fullscreen mode

What This Code Does:

  • Receives Sentry Events: The function is triggered when Sentry sends an event (like an error).
  • Formats the Message: It parses the event and formats a Slack message using blocks (the fancy Slack message formatting system).
  • Sends It to Slack: Using Slack’s API, it posts the error message to a channel of your choice.

Step 3: Slack Setup—Let the Notifications Begin

Here’s how you make sure Slack gets the error alerts:

  1. Create a Slack App: Visit api.slack.com/apps and create a new app in your workspace.
  2. Permissions: Under OAuth & Permissions, add the chat:write permission.
  3. Install the App: Grab the OAuth token after installing the app to your workspace.
  4. Environment Variables: Set SLACK_ACCESS_TOKEN and CHANNEL_ID as environment variables in Vercel.

Step 4: Deploy the Function to Vercel

Push the code to a GitHub repository, connect it to Vercel, and deploy. You’ll need to add your Slack token and channel ID as environment variables. Vercel will handle the rest.

Now, when an error happens in Sentry, it will trigger your edge function, and you’ll see those notifications in Slack within seconds!

Step 5: Testing the Integration

To test if everything’s working, trigger an error in your Sentry project. Check your Slack channel for the notification! If it worked, you should see a neatly formatted message with all the error details.

Why This is Awesome

  • It’s Free: No more paying for Sentry’s Slack integration.
  • Real-Time Alerts: Get instant error notifications as soon as they happen.
  • Customizable: You control how the Slack messages look and what data they contain.
  • No Maintenance: Vercel’s serverless functions handle everything with almost no setup costs.

Bonus: Get the Code & Show Some Love ❤️

You can grab this ready-made solution on my GitHub! Feel free to customize it, use it in your projects, or even improve upon it. If you find it helpful, consider giving the repo a star ⭐ to support more content like this.

Check out the GitHub Repository Here


Got Feedback? Drop a comment or share your thoughts. And if this tutorial saved you some money or gave you a new tool in your dev arsenal, give it a share. Let’s make development easier for everyone!

Top comments (0)