Search by

lukawar / lah-inspector

Bridges a Laravel app to lah-cli / laravel-api-helper — captures SQL queries (exact timings, bindings, source file:line) per request for the VS Code panel. Local/dev only.

Maintainers

Package info

github.com/lukawar/lah-inspector

pkg:composer/lukawar/lah-inspector

Transparency log

Statistics

Installs: 2

Dependents: 0

Suggesters: 1

Stars: 0

Open Issues: 0

1.0.0 2026-07-01 12:16 UTC

This package is auto-updated.

Last update: 2026-09-05 11:37:38 UTC


README

Bridges a Laravel application to lah-cli / the laravel-api-helper VS Code extension. It captures the SQL queries executed during a request — with exact timings, separated bindings and the source file:line — and streams them to the locally running lah-cli sidecar, which forwards them to the editor panel.

This is the Full mode counterpart to lah-cli's standalone general_log capture (Lite mode). It is local/development only and disables itself in production.

Capture modes at a glance

Mode Requires What you get
Core nothing Route listing, sending requests, viewing responses. Always works.
Lite lah-cli + MySQL general_log Queries captured from the DB log. No bindings, no file:line, time-window correlation, misses prepared statements.
Full lah-cli + this package Exact QueryExecuted timings, masked bindings, source file:line, request-id correlation.

The VS Code panel auto-detects the active mode and shows a banner + install hints when a higher tier is available but not installed. You never need this package for the core plugin to work — it only unlocks the richer Queries/Models detail.

How it works

laravel-api-helper ──HTTP (X-Lah-Request-Id)──▶ Laravel + lah-inspector
                                                   │ announce() → POST /ingest/hello (once)
                                                   │ DB::listen → collector
                                                   │ terminate() → POST /ingest/queries
                                                   ▼
                                                 lah-cli  ──▶  VS Code panel
  1. The plugin sets an X-Lah-Request-Id header on every request it sends.
  2. CaptureMiddleware announces the package to lah-cli once per process, then activates the request-scoped Inspector for that id.
  3. DB::listen records every QueryExecuted (sql, exact time, bindings, caller file:line).
  4. On terminate() the batch is POSTed to {ingest_url}/ingest/queries.

Correlation is by request id (not a time window), so it stays exact even under concurrent traffic.

Installation

One command installs both. This package depends on lukawar/lah-cli, so requiring it also pulls the sidecar binary into vendor/bin/lah-cli — you do not install lah-cli separately.

A. From Packagist (when published)

composer require --dev lukawar/lah-inspector

This resolves lukawar/lah-inspector and lukawar/lah-cli in one shot. The CLI ships prebuilt binaries for macOS/Linux (amd64/arm64) with a shim that auto-selects your platform, exposed as vendor/bin/lah-cli.

B. Local path repository (development / unpublished)

If you have the package source on disk (e.g. while developing it), point Composer at it with a path repository. In the Laravel app's composer.json:

{
  "repositories": [
    {
      "type": "path",
      "url": "src/lukawar/lah-inspector",
      "options": { "symlink": true }
    }
  ],
  "require-dev": {
    "lukawar/lah-inspector": "@dev"
  }
}

Then:

composer update lukawar/lah-inspector

With symlink: true, Composer links vendor/lukawar/lah-inspector to your source dir, so edits take effect immediately. (Under php-fpm with OPcache enabled you may need to restart the fpm process to pick up changes.)

Configure the environment

Add to the app's .env:

LAH_ENABLED=true
# optional — defaults shown:
# LAH_INGEST_URL=http://127.0.0.1:7331

Capture runs only when LAH_ENABLED=true and the app is not in the production environment.

Running Laravel in Docker (important)

ingest_url defaults to http://127.0.0.1:7331. Inside a container, 127.0.0.1 is the container itself, not your host — so if lah-cli runs on the host (the usual setup), the hello/queries POSTs go nowhere and the panel silently stays in Lite mode, prompting you to "add lukawar/lah-inspector" even though it is already installed.

Point the package at the host gateway instead. In the app's .env:

LAH_ENABLED=true
LAH_INGEST_URL=http://host.docker.internal:7331

On Docker Desktop (macOS/Windows) host.docker.internal already resolves to the host. On Linux, add it explicitly to the php service in docker-compose.yml:

services:
  php:
    extra_hosts:
      - "host.docker.internal:host-gateway"

Verify from inside the container:

php artisan lah:status   # lah-cli: reachable

If it still says not reachable, the container cannot reach the host on port 7331 — check the extra_hosts entry and that lah-cli is running in the project root. See Troubleshooting.

Verify the wiring

php artisan lah:status

Example output:

lah-inspector v0.1.0
  enabled:    yes
  env:        local
  ingest_url: http://127.0.0.1:7331
  lah-cli:    reachable
  • enabled: no → set LAH_ENABLED=true.
  • lah-cli: not reachable → start lah-cli in the project root (it must be listening on the ingest port).

Then send a request through the laravel-api-helper panel: the Queries tab should switch to the Full banner and show per-query timing, bindings and a clickable 📄 file:line.

Configuration

Publish the config to tweak defaults:

php artisan vendor:publish --tag=lah-inspector-config
Key Default Purpose
enabled false Master switch (LAH_ENABLED).
ingest_url http://127.0.0.1:7331 lah-cli base URL.
header X-Lah-Request-Id Correlation header.
capture_bindings true Send bindings (masked) alongside SQL.
capture_caller true Resolve source file:line via backtrace.
max_queries 500 Cap per request.
mask password, token, secret, … Columns whose col = ? bindings are masked.
timeout_ms 300 Upper bound on the ingest POST.

Each key also reads a matching LAH_* env var (LAH_INGEST_URL, LAH_HEADER, LAH_CAPTURE_BINDINGS, LAH_CAPTURE_CALLER, LAH_MAX_QUERIES, LAH_TIMEOUT_MS).

Security

  • Hard-disabled in production, regardless of LAH_ENABLED.
  • Data is sent only to the local ingest_url (loopback / host gateway).
  • Sensitive bindings (password = ?, token = ?, …) are masked to *** before leaving the app.
  • Ingest failures are swallowed — diagnostics never break the app request.
  • Installed as a --dev dependency; it is not shipped to production deploys.

Troubleshooting

Symptom Likely cause / fix
Queries tab stays in Lite (despite the package being installed) Package not loaded, LAH_ENABLED off, or — most commonly in Docker — ingest_url points at 127.0.0.1 from inside the container. Run php artisan lah:status; set LAH_INGEST_URL=http://host.docker.internal:7331; clear config cache (php artisan config:clear).
lah-cli: not reachable lah-cli not running, wrong ingest_url, or (in Docker) missing host.docker.internal — see Running Laravel in Docker.
Edits to package don't apply OPcache under php-fpm — restart the fpm process / container.
file:line points at vendor code The first non-internal frame is used; Caller skips Laravel/Illuminate/Symfony and this package's own dir.
No queries at all Confirm the plugin is sending the X-Lah-Request-Id header and that the route actually hits the DB.

Limitations (v1)

  • Binding masking covers column <op> ? clauses; INSERT value lists are not column-mapped yet.
  • Designed for the classic FPM request lifecycle; Octane is out of scope for now.

License

MIT