PHPackages                             tuser/query-spy - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Logging &amp; Monitoring](/categories/logging)
4. /
5. tuser/query-spy

ActiveLibrary[Logging &amp; Monitoring](/categories/logging)

tuser/query-spy
===============

QuerySpy: Real-time Laravel query performance monitoring — N+1 detection, slow queries, duplicate queries, memory tracking, and a beautiful developer dashboard.

v1.0.4(1mo ago)02MITBladePHP ^8.1

Since Mar 19Pushed 1mo agoCompare

[ Source](https://github.com/ohtuser/query-spy)[ Packagist](https://packagist.org/packages/tuser/query-spy)[ Docs](https://github.com/ohtuser/query-spy)[ RSS](/packages/tuser-query-spy/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (5)Versions (6)Used By (0)

🔍 QuerySpy
==========

[](#-queryspy)

**Real-time Laravel query performance monitoring.** Drop it in, browse your app, and instantly see N+1 queries, slow SQL, duplicates, memory spikes, and more — all in a beautiful developer dashboard.

[![Packagist](https://camo.githubusercontent.com/9408a2c873ef1a8b65ff1b232d746a5243dbad94cb29282be4846b7635f25ac4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f74757365722f71756572792d737079)](https://packagist.org/packages/tuser/query-spy)[![PHP](https://camo.githubusercontent.com/83dd395020c37276225039739320f6c8e7e99963ab21ee3d09282cb48dad2a60/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e312532422d626c7565)](https://php.net)[![Laravel](https://camo.githubusercontent.com/ee337ee470ffb0e41791962cacd6df22ccfcff8f8891e71cdeecd731a9e6390f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d313025374331312d726564)](https://laravel.com)[![License: MIT](https://camo.githubusercontent.com/5caa455d8debc46fb23abbadb45a733a937f3910a73fc875c2f7820468e1bb54/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e)](LICENSE)

---

✨ Features
----------

[](#-features)

FeatureDescription🔁**N+1 Detection**Finds repeated SQL patterns caused by missing eager-loading🐢**Slow Queries**Flags individual queries over your ms threshold📄**Duplicate SQL**Catches identical queries run multiple times per request🧠**Memory Tracking**Peak memory, growth per request, configurable alert threshold⭐**SELECT \* Detection**Warns when all columns are fetched unnecessarily🔍**Index Hints**Detects leading-wildcard `LIKE '%...'` that force full table scans📊**Severity Score**Every request scored 0–100 and labelled OK / Notice / Warning / Critical🖥**Dashboard**Dark, dev-friendly UI at `/queryspy`📈**Timeline Chart**Dual-axis Chart.js bar+line showing request time and query count📋**Pagination**25 entries per page with smart controls♻️**Auto-refresh**10-second polling toggle on the dashboard📋**Copy SQL**One-click copy button on every SQL block📤**Export**Download as JSON or CSV directly from the dashboard🌐**Response Headers**`X-QuerySpy-*` headers visible in your browser's Network tab🔐**Password Protection**Optional dashboard password via `.env`🌍**Environment Guard**Skips production, CLI commands, and ignored URL patterns🖨**Artisan Commands**`summary`, `watch`, `clear`, `export`---

📦 Installation
--------------

[](#-installation)

```
composer require tuser/query-spy
```

> Laravel auto-discovers the service provider — no manual registration needed.

**Publish the config:**

```
php artisan vendor:publish --tag=queryspy-config
```

---

⚙️ Configuration
----------------

[](#️-configuration)

Add any of these to your `.env` (all are optional):

```
QS_ENABLED=true
QS_SLOW_QUERY_MS=100          # Flag queries slower than this (ms)
QS_MAX_QUERIES=50             # Alert when queries/request exceed this
QS_N_PLUS_ONE=5               # Same SQL pattern N times = N+1 warning
QS_SLOW_REQUEST_SECONDS=2     # Flag requests slower than this
QS_MEMORY_THRESHOLD_MB=64     # Alert when peak memory exceeds this (MB)
QS_INJECT_HEADERS=true        # Add X-QuerySpy-* headers to responses
QS_LOG_CHANNEL=stack          # Laravel log channel for alerts
QS_DASHBOARD_URL=/queryspy    # Dashboard URL
QS_PASSWORD=                  # Optional dashboard password
QS_MAX_LOG_ENTRIES=200        # Max entries kept in storage
```

Full reference: `config/queryspy.php`

---

🖥 Dashboard
-----------

[](#-dashboard)

Visit **`/queryspy`** in your browser after installing.

### What you get:

[](#what-you-get)

- **7 stat cards** — Total, Critical, Warning, Notice, Clean, Avg Duration, Total N+1
- **Sidebar** — avg queries, avg memory, avg severity score with progress bar
- **Timeline chart** — request duration (bars) + query count (line), coloured by severity
- **Filters** — by severity level or issue type (N+1, slow, dupes, memory)
- **Search** — by URL, route name, or any SQL text
- **Pagination** — 25 per page
- **Auto-refresh** — 10-second toggle
- **Export CSV / JSON** — one-click download
- **Per-request drill-down** with tabs:
    - **Summary** — all metrics, memory, index hints, SELECT\* warnings
    - **All Queries** — time badge, full SQL with Copy button, source `file:line`
    - **N+1** — pattern, count, total time, eager-load suggestion, source
    - **Slow** — full SQL, caller, source
    - **Duplicates** — count, source

---

🌐 Response Headers
------------------

[](#-response-headers)

When `QS_INJECT_HEADERS=true`, every response includes:

```
X-QuerySpy-Queries:    14
X-QuerySpy-Time-Ms:    87.4
X-QuerySpy-Memory-MB:  12.5
X-QuerySpy-Severity:   warning
X-QuerySpy-Score:      45
X-QuerySpy-N1:         2
X-QuerySpy-Slow:       1
X-QuerySpy-Duplicates: 0

```

Visible in your browser's **Network tab → select request → Headers**.

---

🖨 Artisan Commands
------------------

[](#-artisan-commands)

```
# Pretty table of recent entries
php artisan queryspy:summary
php artisan queryspy:summary --limit=50

# Live tail — prints new entries as they arrive
php artisan queryspy:watch
php artisan queryspy:watch --interval=5

# Wipe all stored logs
php artisan queryspy:clear

# Export to file
php artisan queryspy:export --format=csv
php artisan queryspy:export --format=json
php artisan queryspy:export --format=csv --output=/tmp/report.csv
```

---

📡 JSON API
----------

[](#-json-api)

All endpoints accept `?password=` when `QS_PASSWORD` is set.

```
GET  /queryspy/api               → paginated JSON log
GET  /queryspy/api?severity=critical
GET  /queryspy/api?page=2&per_page=20
GET  /queryspy/export/csv        → CSV download
POST /queryspy/clear             → clear all logs

```

**API response shape:**

```
{
  "data":  [ ... ],
  "stats": { "total": 42, "critical": 3, "warning": 8, ... },
  "meta":  { "total": 42, "page": 1, "per_page": 50, "last_page": 1 }
}
```

---

🌍 Environment Guard
-------------------

[](#-environment-guard)

QuerySpy only runs in:

```
// config/queryspy.php
'environments' => ['local', 'development', 'staging'],
```

It **never runs** in `production` by default, in CLI/Artisan commands, or for URLs matching `ignore_urls` patterns (`/queryspy*`, `/_ignition*`, `/telescope*`, `/horizon*`).

---

🔐 Password Protection
---------------------

[](#-password-protection)

```
QS_PASSWORD=my-secret
```

The dashboard shows a password form. Pass `?password=my-secret` to API endpoints.

---

🗂 Issue Types Explained
-----------------------

[](#-issue-types-explained)

### 🔁 N+1 Queries

[](#-n1-queries)

The same SQL pattern (with bindings normalised to `?`) runs 5+ times per request. Classic sign of missing `with('relation')` in Eloquent.

### 🐢 Slow Queries

[](#-slow-queries)

Any individual query taking longer than `QS_SLOW_QUERY_MS` (default 100ms). Includes full SQL with real binding values and the source `file:line`.

### 📄 Duplicate SQL

[](#-duplicate-sql)

Identical SQL (including bindings) run more than once — usually a missing cache or a logic loop.

### 🧠 Memory

[](#-memory)

Peak PHP memory exceeds `QS_MEMORY_THRESHOLD_MB`. Also tracks memory growth across the request lifecycle.

### ⭐ SELECT \*

[](#-select-)

`SELECT *` on wide tables fetches unnecessary columns, wasting memory and network bandwidth.

### 🔍 Index Hints

[](#-index-hints)

`LIKE '%value'` (leading wildcard) can't use a B-tree index and results in a full table scan. Consider a full-text index or a dedicated search engine.

---

🛠 Publishing
------------

[](#-publishing)

```
# Config
php artisan vendor:publish --tag=queryspy-config

# Blade views (to customise the dashboard)
php artisan vendor:publish --tag=queryspy-views
```

---

📝 Changelog
-----------

[](#-changelog)

See [CHANGELOG.md](CHANGELOG.md).

---

📄 License
---------

[](#-license)

MIT © QuerySpy

###  Health Score

38

—

LowBetter than 85% of packages

Maintenance90

Actively maintained with recent releases

Popularity3

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

5

Last Release

51d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ccae38173bd39fd89b5813269a35996306d6ece5cd1ffb8fbf11bc04d2a29666?d=identicon)[ohtuser](/maintainers/ohtuser)

---

Top Contributors

[![ohtuser1](https://avatars.githubusercontent.com/u/82013776?v=4)](https://github.com/ohtuser1 "ohtuser1 (5 commits)")

---

Tags

laravelmonitoringperformancedebuggingqueryslow query

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/tuser-query-spy/health.svg)

```
[![Health](https://phpackages.com/badges/tuser-query-spy/health.svg)](https://phpackages.com/packages/tuser-query-spy)
```

###  Alternatives

[yadahan/laravel-authentication-log

Laravel Authentication Log provides authentication logger and notification for Laravel.

416632.8k5](/packages/yadahan-laravel-authentication-log)[scoutapp/scout-apm-laravel

Scout Application Performance Monitoring Agent - https://scoutapm.com

23831.3k](/packages/scoutapp-scout-apm-laravel)[kitloong/laravel-app-logger

Laravel log for your application

101.2M8](/packages/kitloong-laravel-app-logger)[hryha/laravel-request-logger

A Laravel package to log requests and responses

102.2k](/packages/hryha-laravel-request-logger)[kssadi/log-tracker

A powerful, intuitive, and efficient log viewer for Laravel applications.

264.8k](/packages/kssadi-log-tracker)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
