{"id":632,"date":"2025-09-05T11:29:42","date_gmt":"2025-09-05T11:29:42","guid":{"rendered":"https:\/\/1v0.net\/blog\/?p=632"},"modified":"2025-09-05T11:29:45","modified_gmt":"2025-09-05T11:29:45","slug":"debugging-laravel-applications-with-ray-and-telescope","status":"publish","type":"post","link":"https:\/\/1v0.net\/blog\/debugging-laravel-applications-with-ray-and-telescope\/","title":{"rendered":"Debugging Laravel Applications with Ray and Telescope"},"content":{"rendered":"\n<p>Debugging is a critical part of building reliable Laravel applications. While <code>dd()<\/code> and <code>dump()<\/code> are quick solutions, they don\u2019t scale well for complex apps. Laravel offers powerful debugging tools like <strong>Telescope<\/strong> for application-wide monitoring, and third-party tools like <strong>Ray<\/strong> to simplify debugging during development. In this article, we\u2019ll explore both tools, show how to set them up, and walk through real-world debugging workflows.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Installing Ray for Debugging<\/strong><\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">composer require spatie\/laravel-ray --dev<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><a href=\"https:\/\/myray.app\">Ray<\/a> is a desktop app by Spatie that displays debugging output in a clear, interactive interface. Once installed, you can use the <code>ray()<\/code> helper function anywhere in your Laravel app. Ray captures variables, queries, jobs, and more \u2014 without polluting your HTML responses or logs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Basic Usage<\/strong><\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">ray(<span class=\"hljs-string\">'Hello from Laravel'<\/span>);\nray($user);\nray($request-&gt;all());<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This sends text, objects, or arrays to the Ray desktop client. It works like <code>dd()<\/code> but doesn\u2019t halt execution. You can also chain styles and colors to organize debugging output.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Debugging Queries with Ray<\/strong><\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ In AppServiceProvider or a debug-only service provider<\/span>\n\\Illuminate\\Support\\Facades\\DB::listen(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">($query)<\/span> <\/span>{\n    ray($query-&gt;sql, $query-&gt;bindings, $query-&gt;time);\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Ray displays executed queries, bindings, and execution time. This makes query optimization easier during development.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Debugging Jobs and Events<\/strong><\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">ray()-&gt;showJobs();\nray()-&gt;showEvents();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Ray can automatically show when jobs are dispatched or events are fired, helping you track async flows in your app.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Installing and Using Laravel Telescope<\/strong><\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">composer require laravel\/telescope --dev\nphp artisan telescope:install\nphp artisan migrate<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><a href=\"https:\/\/laravel.com\/docs\/telescope\">Telescope<\/a> is Laravel\u2019s official debugging assistant. It provides a dashboard at <code>\/telescope<\/code> where you can view requests, jobs, events, queries, logs, cache hits, and more. It\u2019s particularly powerful for tracking production issues when paired with access restrictions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Tracking Requests and Responses<\/strong><\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ Example: telescope shows request lifecycle<\/span>\nGET \/posts\/<span class=\"hljs-number\">1<\/span>\n- Controller: PostController@show\n- Queries: <span class=\"hljs-number\">2<\/span> (<span class=\"hljs-number\">45<\/span>ms)\n- Response: <span class=\"hljs-number\">200<\/span> OK<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The Requests tab in Telescope shows complete details about each incoming request, including middleware, response time, and database queries executed during that request.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Monitoring Queries<\/strong><\/h3>\n\n\n\n<p>Telescope logs all queries executed in your app, including N+1 query problems. It highlights slow queries, so you can quickly identify bottlenecks.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Jobs, Events, and Cache<\/strong><\/h3>\n\n\n\n<p>From the dashboard, you can see when jobs are dispatched, events are triggered, and cache hits or misses occur. This visibility helps debug background tasks and performance issues.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Securing Telescope in Production<\/strong><\/h2>\n\n\n\n<p>Telescope can expose sensitive information. Protect it with authorization gates:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ app\/Providers\/TelescopeServiceProvider.php<\/span>\n<span class=\"hljs-keyword\">use<\/span> <span class=\"hljs-title\">Laravel<\/span>\\<span class=\"hljs-title\">Telescope<\/span>\\<span class=\"hljs-title\">Telescope<\/span>;\n\nTelescope::auth(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-params\">($request)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> in_array($request-&gt;user()?-&gt;email, &#91;\n        <span class=\"hljs-string\">'admin@example.com'<\/span>,\n    ]);\n});<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This ensures that only authorized developers can access Telescope in production environments. Always secure it before deployment.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Ray vs Telescope: When to Use Each<\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Feature<\/th><th>Ray<\/th><th>Telescope<\/th><\/tr><\/thead><tbody><tr><td>Scope<\/td><td>Developer-focused debugging<\/td><td>App-wide request monitoring<\/td><\/tr><tr><td>Best for<\/td><td>Quick dumps, inspecting variables, dev feedback<\/td><td>Tracking queries, jobs, events, logs<\/td><\/tr><tr><td>UI<\/td><td>Desktop client<\/td><td>Web dashboard at \/telescope<\/td><\/tr><tr><td>Environment<\/td><td>Local development only<\/td><td>Local + Production (with access control)<\/td><\/tr><tr><td>Integration<\/td><td>Simple ray() calls in code<\/td><td>Automatic hooks into Laravel internals<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Use Ray for quick, developer-centric debugging. Use Telescope for request and system-wide insights. Many teams run both in parallel: Ray locally, Telescope in staging\/production.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Wrapping Up<\/strong><\/h2>\n\n\n\n<p>Debugging effectively saves hours of guesswork. Ray is perfect for rapid feedback during development, while Telescope gives you full visibility into requests, queries, and background jobs. Together, they provide a powerful toolkit for debugging Laravel apps across environments.<\/p>\n\n\n\n<div style=\"height:100px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What\u2019s Next<\/strong><\/h2>\n\n\n\n<p>For further monitoring and debugging, check out these guides:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/blog\/using-laravel-telescope-to-debug-performance-issues\">Using Laravel Telescope to Debug Performance Issues<\/a><\/li>\n\n\n\n<li><a href=\"\/blog\/query-performance-tuning-in-laravel-mysql\">Query Performance Tuning in Laravel + MySQL<\/a><\/li>\n\n\n\n<li><a href=\"\/blog\/how-to-speed-up-laravel-with-database-indexing\">How to Speed Up Laravel with Database Indexing<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Debugging is a critical part of building reliable Laravel applications. While dd() and dump() are quick solutions, they don\u2019t scale well for complex apps. Laravel offers powerful debugging tools like Telescope for application-wide monitoring, and third-party tools like Ray to simplify debugging during development. In this article, we\u2019ll explore both tools, show how to set [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":636,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[72,149,44,148,73],"class_list":["post-632","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-laravel","tag-debugging","tag-monitoring","tag-performance","tag-ray","tag-telescope"],"_links":{"self":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/632","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/comments?post=632"}],"version-history":[{"count":1,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/632\/revisions"}],"predecessor-version":[{"id":635,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/632\/revisions\/635"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media\/636"}],"wp:attachment":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media?parent=632"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/categories?post=632"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/tags?post=632"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}