DEV Community

Dan
Dan

Posted on

Setting Up Error Monitoring in Laravel Without the Overhead

It's 2:17am and someone on X (man I miss it being Twitter) is telling me my app is broken.

Not how it's broken, mind you. Just a screenshot of a white page and "hey your thing is dead lol". So now I'm SSH'd into a server, running tail -f storage/logs/laravel.log, scrolling through thousands of lines of interleaved garbage — deprecation warnings I've been ignoring for months, some debug output I forgot to remove, and somewhere in there, presumably, the actual error that's causing a 500 for this person. I find it eventually. A null pointer on a relationship I forgot to eager load. Fifteen minutes of log archaeology for something that would've taken two seconds if I'd had any kind of monitoring set up.

This was like three years ago. I'd love to tell you I fixed it the next day. I didn't.

The Log::error() era

Here's what I did instead, and I suspect you've done the same thing. I sprinkled Log::error() calls in strategic places. I set up a Slack webhook that fired on 500 responses. I told myself this was monitoring.

And honestly? It kind of works. For a while.

The problem is that Log::error('Something went wrong', ['user' => $user->id]) gives you exactly one data point. You know that it happened. You don't know how often. You don't know what the request body looked like, or what the user was doing before the error, or whether this is the same bug you saw last Tuesday or a new one. Every error is an island. There's no grouping, no trends, no context.

I had a bug once that was happening about 40 times a day. I didn't know that. My Slack channel showed me "500 error on /dashboard" and I'd think ah, that one again, I'll fix it this week. Turns out "that one" was actually three different bugs hitting the same route, affecting different users in different ways. I only found out when I finally sat down and grep'd through a week's worth of logs. Fun afternoon.

The Sentry question

Look, Sentry is good software. I'm not going to pretend otherwise.

But when I looked at adding it to a Laravel side project — one with maybe 100 active users — something felt off. The SDK pulls in a fair amount. The dashboard is built for teams running microservices at scale, and half the features I'd be paying for (performance monitoring, session replay, release tracking) are things I genuinely don't need. The pricing tiers assume you're a startup burning through venture capital, not someone running a $29/month Digital Ocean droplet.

I wanted Laravel exception monitoring that felt like it belonged in a Laravel app. Not a platform-agnostic tool with a Laravel adapter bolted on. Something where the setup was measured in minutes, not in "follow this 12-step configuration guide and don't forget to publish the config file and set up the queue driver and..."

So I built one. (This is the part where I'm supposed to be casual about the self-promotion, but honestly, I built it because I needed it, and I think you might need it too.)

Actually setting it up

Two steps for PHP errors:

composer require oopsy/oopsy-laravel
Enter fullscreen mode Exit fullscreen mode

Then add your DSN to .env:

OOPSY_DSN=http://oops-xxx@oopsy.dev/api/v1/projects/1
Enter fullscreen mode Exit fullscreen mode

That's it. No publishing config files, no middleware to register, no service provider to add manually. The package auto-discovers and registers itself. When an exception happens in your app, it captures the full stack trace with code context, the request data, user information, environment — and sends it asynchronously using Laravel's Http::async(). Your response times don't change. The monitored app never slows down, and it never crashes because of the monitoring itself (which, hm, would be ironic).

For JavaScript errors — and this is the bit I'm probably most pleased with — you add a single script tag:

<script src="https://your-oopsy.dev/api/v1/js/oopsy_pub_xxx.js"></script>
Enter fullscreen mode Exit fullscreen mode

No npm install. No build step. No 200KB bundle imported into your frontend pipeline. It's a self-contained script served per-project that captures uncaught exceptions, unhandled promise rejections, and records breadcrumbs: click events, console errors, XHR and fetch requests, navigation changes. It uses sendBeacon for delivery, which means errors get reported even when the user is closing the tab. The whole thing is maybe a few kilobytes.

I spent an embarrassing amount of time getting that breadcrumb recording right, actually. There's this edge case with fetch where you need to monkey-patch the global but also not break anyone else's monkey-patching, and — anyway, that's a different blog post.

What shows up on the other end

When an error comes in, it gets fingerprinted and grouped automatically. So if 500 users hit the same null pointer exception, you see one issue with an event count of 500, not 500 separate entries you have to mentally deduplicate. The fingerprinting works off the exception class, the file, and the line number — first in-app frame, not vendor code — which means it groups things the way you'd actually think about them.

Each issue shows you the full stack trace with surrounding code, the HTTP request that triggered it, which user was affected, severity level, and environment. JavaScript errors get a little JS badge so you can immediately tell whether something is blowing up server-side or in the browser. You can filter by status (unresolved, resolved, ignored), severity, source, environment.

There are email and Telegram alerts too. Because what good is Laravel exception monitoring if it doesn't wake you up at 2am? (I'm joking. Set your notification schedule. Please.)

The money part

Free tier is 1,000 errors per month on one project with 7-day retention. For a side project, that's probably more than enough — and if you're getting more than 1,000 errors a month on a side project, you might have bigger problems than monitoring. Hobby tier is $5/month for 50,000 errors across 5 projects with 30-day retention, which is where most small production apps land. There's a Pro tier at $19/month if you need more, but I'm not going to sell you on it here.

The thing I specifically didn't want was the kind of pricing where you look at your error volume and think maybe I should just suppress some of these. Laravel exception monitoring should make you want to see every error, not dread the invoice.

Anyway

I don't have a neat conclusion for you. Error monitoring is one of those things that feels optional right up until the moment it isn't, and then you're reading log files at 2am in your pants wondering why you didn't set something up six months ago. I've been that person. More than once.

Two lines of config. That's the whole pitch, really.

Dan

Top comments (0)