<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Dan</title>
    <description>The latest articles on Forem by Dan (@oopsydev).</description>
    <link>https://forem.com/oopsydev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3786817%2F149dae3d-9414-4d9e-8a99-b4d370240cd1.png</url>
      <title>Forem: Dan</title>
      <link>https://forem.com/oopsydev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/oopsydev"/>
    <language>en</language>
    <item>
      <title>Setting Up Error Monitoring in Laravel Without the Overhead</title>
      <dc:creator>Dan</dc:creator>
      <pubDate>Wed, 25 Feb 2026 19:19:52 +0000</pubDate>
      <link>https://forem.com/oopsydev/setting-up-error-monitoring-in-laravel-without-the-overhead-48fk</link>
      <guid>https://forem.com/oopsydev/setting-up-error-monitoring-in-laravel-without-the-overhead-48fk</guid>
      <description>&lt;p&gt;It's 2:17am and someone on X (man I miss it being Twitter) is telling me my app is broken.&lt;/p&gt;

&lt;p&gt;Not &lt;em&gt;how&lt;/em&gt; 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 &lt;code&gt;tail -f storage/logs/laravel.log&lt;/code&gt;, 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 &lt;em&gt;any&lt;/em&gt; kind of monitoring set up.&lt;/p&gt;

&lt;p&gt;This was like three years ago. I'd love to tell you I fixed it the next day. I didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;Log::error()&lt;/code&gt; era
&lt;/h2&gt;

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

&lt;p&gt;And honestly? It kind of works. For a while.&lt;/p&gt;

&lt;p&gt;The problem is that &lt;code&gt;Log::error('Something went wrong', ['user' =&amp;gt; $user-&amp;gt;id])&lt;/code&gt; gives you exactly one data point. You know &lt;em&gt;that&lt;/em&gt; 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.&lt;/p&gt;

&lt;p&gt;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 &lt;em&gt;ah, that one again, I'll fix it this week&lt;/em&gt;. 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Sentry question
&lt;/h2&gt;

&lt;p&gt;Look, Sentry is good software. I'm not going to pretend otherwise.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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..."&lt;/p&gt;

&lt;p&gt;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.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Actually setting it up
&lt;/h2&gt;

&lt;p&gt;Two steps for PHP errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require oopsy/oopsy-laravel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add your DSN to &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;OOPSY_DSN=http://oops-xxx@oopsy.dev/api/v1/projects/1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 &lt;code&gt;Http::async()&lt;/code&gt;. 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).&lt;/p&gt;

&lt;p&gt;For JavaScript errors — and this is the bit I'm probably most pleased with — you add a single script tag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://your-oopsy.dev/api/v1/js/oopsy_pub_xxx.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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 &lt;code&gt;sendBeacon&lt;/code&gt; for delivery, which means errors get reported even when the user is closing the tab. The whole thing is maybe a few kilobytes.&lt;/p&gt;

&lt;p&gt;I spent an embarrassing amount of time getting that breadcrumb recording right, actually. There's this edge case with &lt;code&gt;fetch&lt;/code&gt; 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  What shows up on the other end
&lt;/h2&gt;

&lt;p&gt;When an error comes in, it gets fingerprinted and grouped automatically. So if 500 users hit the same null pointer exception, you see &lt;em&gt;one&lt;/em&gt; 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.&lt;/p&gt;

&lt;p&gt;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 &lt;code&gt;JS&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;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.)&lt;/p&gt;

&lt;h2&gt;
  
  
  The money part
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Anyway
&lt;/h2&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Two lines of config. That's the whole pitch, really.&lt;/p&gt;

&lt;p&gt;Dan&lt;/p&gt;

</description>
      <category>backend</category>
      <category>laravel</category>
      <category>monitoring</category>
      <category>php</category>
    </item>
    <item>
      <title>I Built an Error Tracker Because Sentry Made Me Feel Poor</title>
      <dc:creator>Dan</dc:creator>
      <pubDate>Mon, 23 Feb 2026 15:05:40 +0000</pubDate>
      <link>https://forem.com/oopsydev/i-built-an-error-tracker-because-sentry-made-me-feel-poor-33pj</link>
      <guid>https://forem.com/oopsydev/i-built-an-error-tracker-because-sentry-made-me-feel-poor-33pj</guid>
      <description>&lt;p&gt;&lt;em&gt;I was just a Laravel dev who wanted to know when his app broke. The pricing pages said no. So I built my own error tracker.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I was three clicks deep into Sentry's pricing page when I did the maths on what monitoring my side project would actually cost. The side project that makes, on a good month, enough to cover its own hosting. &lt;em&gt;Forty bucks a month to watch for errors on an app that serves maybe two hundred people.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I closed the tab.&lt;/p&gt;

&lt;p&gt;Tried Flare. Nicer for Laravel, sure. Still felt like I was paying enterprise rent on a studio flat. Nightwatch? Same energy. Every single one of these tools is built for a team with a Jira board and a VP of Engineering and a budget that doesn't make someone physically wince. I'm just a bloke with a Laravel app and a DigitalOcean droplet. I only need to know when something breaks.&lt;/p&gt;

&lt;p&gt;That's it. That's the whole requirement. When a thing goes wrong, tell me about it. Maybe group the errors so I'm not drowning in five hundred copies of the same stack trace. Maybe send me a Telegram message so I notice before my users do. The bar is, honestly, not that high.&lt;/p&gt;

&lt;p&gt;So of course — &lt;em&gt;of course&lt;/em&gt; — my brain did the thing. You know the thing. The thing where you're a developer and you look at a problem and instead of paying someone to solve it, you think: &lt;em&gt;I could build this.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is almost always a terrible idea. I know this. You know this. We all know this. And yet.&lt;/p&gt;




&lt;p&gt;I opened a blank Laravel project on a Tuesday evening. Told myself I'd just prototype the ingestion endpoint. See if I could catch an exception from another Laravel app and store it. Two hours, tops, then I'd come to my senses and just pay for Flare.&lt;/p&gt;

&lt;p&gt;That was months ago.&lt;/p&gt;

&lt;p&gt;The thing I built is called Oopsy, and it's a proper laravel error monitoring tool now, which still surprises me a bit. TALL stack — Tailwind, Alpine, Livewire, Laravel - because that's what I know and I wasn't about to learn React for this. Domain-driven design because the codebase started getting messy around week three and I needed to impose some order before I lost my mind.&lt;/p&gt;

&lt;p&gt;Here's what it actually does. On the PHP side, you run &lt;code&gt;composer require&lt;/code&gt; on a small Laravel package. It hooks into the exception handler, captures the stack trace with code context, grabs request and user info, collects breadcrumbs from your logs and queries, then fires it off asynchronously. Your app doesn't slow down, doesn't crash if Oopsy is unreachable. It just quietly reports what went wrong.&lt;/p&gt;

&lt;p&gt;The bit I'm weirdly proud of is the JavaScript error catching. You add a single script tag. That's it. No npm install, no build step, no configuration file with forty options. The script captures uncaught exceptions, unhandled promise rejections, parses stack traces across Chrome, Firefox, and Safari (which all format them differently, because browsers hate us), records breadcrumbs of what the user clicked and what network requests happened, then sends everything via &lt;code&gt;sendBeacon&lt;/code&gt; so it doesn't block the page unload. I spent an embarrassing amount of time getting &lt;code&gt;sendBeacon&lt;/code&gt; to work without CORS preflight requests. The trick is sending as &lt;code&gt;text/plain&lt;/code&gt;. Anyway.&lt;/p&gt;

&lt;p&gt;Errors get grouped by fingerprint — a hash of the exception class, the file, and the line number from the first non-vendor stack frame. So when your &lt;code&gt;PaymentController&lt;/code&gt; throws the same &lt;code&gt;StripeException&lt;/code&gt; forty times in an hour, you see one issue with a count of forty, not forty separate issues cluttering up your dashboard. You can filter by severity, by environment, by whether it came from PHP or JavaScript. You can mark things resolved, and if they come back, they automatically flip to regressed.&lt;/p&gt;

&lt;p&gt;It's laravel error monitoring without the complexity tax. That was the whole point.&lt;/p&gt;




&lt;p&gt;Then came the pricing question, which felt strange from the other side. I'd started this project &lt;em&gt;because&lt;/em&gt; pricing annoyed me, and now I had to set prices myself.&lt;/p&gt;

&lt;p&gt;I kept it simple. Free tier gives you a thousand errors a month, one project, seven days of retention. For most hobby projects, that's probably enough. For five dollars a month — the Hobby plan — you get fifty thousand errors, five projects, thirty days. And if you're running something more serious, nineteen dollars a month gets you half a million errors, unlimited projects, ninety days of retention, unlimited team members.&lt;/p&gt;

&lt;p&gt;I don't know if those numbers are right. I genuinely don't. Maybe the free tier is too generous and I'll bleed money on infrastructure. Maybe the Pro tier is too cheap and I'm leaving money on the table. But I kept coming back to the feeling I had on that Sentry pricing page — that sinking &lt;em&gt;this isn't for people like me&lt;/em&gt; feeling — and I figured I'd rather err on the side of affordable.&lt;/p&gt;

&lt;p&gt;(There's a joke in there about erring on the side of errors. I'm choosing not to make it. You're welcome.)&lt;/p&gt;




&lt;p&gt;The honest bit, the bit I almost didn't write: I have no idea if this works as a business. The economics of running a laravel error monitoring SaaS are not straightforward. You're ingesting potentially huge volumes of data, storing stack traces and breadcrumbs, running background jobs to process and group everything. The free tier users generate real costs. Hosting isn't free. My time isn't free, even though I keep pretending it is.&lt;/p&gt;

&lt;p&gt;But it works as a tool. I use it on my own projects. When something breaks at 2am, my phone buzzes with a Telegram message that tells me exactly what happened, which file, which line, what the user was doing. I fix it in the morning. Nobody writes me an angry email.&lt;/p&gt;

&lt;p&gt;And look, maybe that's enough for now. Not everything has to be a venture-scale business. Sometimes you build a thing because the existing options made you feel like you couldn't afford to be a professional developer, and you think other people might feel that way too. Sometimes the "I could build this" impulse, against all odds, produces something that actually works and that you're actually a little bit proud of.&lt;/p&gt;

&lt;p&gt;Sometimes the terrible idea turns out fine.&lt;/p&gt;

&lt;p&gt;Oopsy is at &lt;a href="https://oopsy.dev" rel="noopener noreferrer"&gt;oopsy.dev&lt;/a&gt; if you want to poke at it. Free tier, no credit card, takes about two minutes to set up. If you're doing laravel error monitoring on a budget — or just on principle — maybe it's useful to you. Maybe it's not. I'm not going to pretend I've solved monitoring forever.&lt;/p&gt;

&lt;p&gt;I just wanted to know when my app broke.&lt;/p&gt;

&lt;p&gt;Dan&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>laravel</category>
      <category>javascript</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
