pulsehub/laravel

PulseHub Laravel SDK — send live error reports and health snapshots from your Laravel app to a PulseHub server.

Maintainers

Package info

github.com/taiaburbd/PulseHub

pkg:composer/pulsehub/laravel

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.2 2026-05-21 18:26 UTC

This package is not auto-updated.

Last update: 2026-05-22 18:59:54 UTC


README

Heartbeat of all your systems.

The official Laravel package for PulseHub. Drop it into your Laravel app and every uncaught exception is sent live to your PulseHub dashboard, where it becomes a task you can triage through new → in_progress → in_review → done.

What this package does

In one line: catches errors from your Laravel app and POSTs them to your PulseHub server, live.

It also:

  • Sends an hourly health report (PHP version, memory, CPU load, queue size).
  • Validates your API key against the server.
  • Detects when the PulseHub server is down or your token is bad — and logs exactly what's wrong to storage/logs/laravel.log so you spot the problem.

What about the URL?

There are two URLs in play. To make sure they don't get confused:

Setting What it is Example value
PULSEHUB_URL The server you POST to. Your PulseHub installation. https://pulsehub.diqcare.com
APP_URL Your Laravel app — leave it alone, that's not PulseHub. https://my-shop.example.com

The package never opens incoming ports. It only makes outbound HTTPS calls to PULSEHUB_URL carrying your bearer token.

1. Install (60 seconds)

composer require pulsehub/laravel
php artisan vendor:publish --tag=pulsehub-config

Not on Packagist yet? Until the package is on Packagist, pick one of the two alternative install paths below — both let you keep using the same composer require pulsehub/laravel command.

Install from GitHub (works today)

Add a VCS repository to your Laravel app's composer.json:

"repositories": [
    { "type": "vcs", "url": "https://github.com/taiaburbd/PulseHub" }
]

Then run the bare command:

composer require pulsehub/laravel
Install from a local clone (for SDK contributors)

Clone the SDK next to your Laravel app and add a path repository:

"repositories": [
    { "type": "path", "url": "../PulseHub", "options": { "symlink": true } }
]

Then run:

composer require pulsehub/laravel

Symlink mode means edits in your clone show up in vendor/pulsehub/laravel/ instantly — no reinstall needed.

After install

Open .env and add:

PULSEHUB_URL=https://pulsehub.diqcare.com
PULSEHUB_TOKEN=ph_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
PULSEHUB_SOURCE=my-ecommerce-site
PULSEHUB_TRANSPORT=queue
PULSEHUB_INTERVAL=hourly

Where does the token come from? Register at https://pulsehub.diqcare.com/admin/register (it's a free SaaS — your workspace and a starter source are created automatically), go to API Tokens → Generate API token, copy the ph_live_... value immediately — it's only shown once.

Viewer-role users can't generate tokens; ask your workspace admin.

2. Capture exceptions

For Laravel 11+ apps, add one line to bootstrap/app.php:

->withExceptions(function (Exceptions $exceptions) {
    \PulseHub\Laravel\Facades\PulseHub::registerExceptionHandler($exceptions);
})

That's it. Every uncaught Throwable in your app is now sent to PulseHub. Common noisy exceptions (404, validation, auth) are filtered out of the box; see config/pulsehub.php → ignore_exceptions to customize.

Manual reporting

use PulseHub\Laravel\Facades\PulseHub;

try {
    importInvoices($batchId);
} catch (Throwable $e) {
    PulseHub::context(['batch' => $batchId])
        ->user(auth()->id(), auth()->user()?->email)
        ->reportException($e);
}

3. Verify the connection

php artisan pulsehub:test

You'll see one of four outcomes:

Result What it means
Connected. HTTP 200. Token valid, server reachable. You're good.
Bad API key (HTTP 401/403) Token wrong or revoked. Generate a fresh one in the dashboard.
Endpoint not found (404) PULSEHUB_URL is pointing at the wrong host.
Server unreachable (5xx/network) PulseHub is down OR network/firewall is blocking outbound HTTPS.

These exact diagnoses also land in storage/logs/laravel.log whenever a real report fails — so if reports stop arriving, just tail your logs:

production.ERROR: [PulseHub] Bad API key — server rejected the token. Check PULSEHUB_TOKEN.
production.ERROR: [PulseHub] Server unreachable or erroring — PulseHub may be down.

Live vs queued delivery

By default the package queues outbound calls so they never block a user request:

PULSEHUB_TRANSPORT=queue   # default — uses your existing queue worker

If you want immediate (live) sends — useful for tiny apps or debugging:

PULSEHUB_TRANSPORT=sync

In dev environments with no queue worker (QUEUE_CONNECTION=sync) the package auto-downgrades to sync, so things "just work" without configuration.

Hourly health reports

The package auto-registers an hourly schedule. As long as your Laravel scheduler cron is running:

* * * * * cd /path-to-your-app && php artisan schedule:run >> /dev/null 2>&1

…PulseHub gets a snapshot every hour:

{
  "source": "my-ecommerce-site",
  "php_version": "8.2.10",
  "framework_version": "11.x",
  "environment": "production",
  "memory_usage_mb": 45.2,
  "cpu_load": 0.18,
  "queue_status": { "connection": "redis", "size": 12, "status": "ok" },
  "error_count_last_hour": 3,
  "status": "healthy",
  "timestamp": "2026-01-01T10:00:00+00:00"
}

Run it manually any time:

php artisan pulsehub:report        # queue (default)
php artisan pulsehub:report --sync # send immediately

Useful Artisan commands

php artisan pulsehub:test     # validate token + connectivity
php artisan pulsehub:report   # send a health report now
php artisan pulsehub:status   # show config + last delivery result

Capturing 5xx responses (optional middleware)

If you want HTTP 5xx responses reported even when no exception was thrown:

// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
    $middleware->append(\PulseHub\Laravel\Middleware\PulseHubMiddleware::class);
})

Configuration reference

Full config lives in config/pulsehub.php. Most-used keys:

Key Default What it does
token null PulseHub bearer token. Required.
base_url pulsehub.io The PulseHub server URL.
source_name APP_NAME Label shown in the dashboard.
enabled true Master kill switch.
interval hourly Health report frequency. null to disable.
transport queue queue or sync.
retry.attempts 3 HTTP retry attempts.
sample_rate 1.0 Probability errors are forwarded (0–1).
ignore_exceptions (defaults) Classes to drop before sending.
before_send null Hook to mutate or drop the payload.
local_log.enabled false Persist every attempt to pulsehub_logs for debugging.

Events you can hook into

use PulseHub\Laravel\Events\ReportSent;
use PulseHub\Laravel\Events\ReportFailed;

Event::listen(ReportSent::class,   fn ($e) => /* ... */);
Event::listen(ReportFailed::class, function ($e) {
    if ($e->category() === 'auth_invalid') {
        // page the on-call: PulseHub key is broken
    }
});

Troubleshooting

"PULSEHUB_TOKEN is not set" → You forgot to add the token to your .env, or you haven't restarted PHP-FPM / queue worker after adding it.

"Bad API key" in logs → Token revoked or copy/paste error. Generate a fresh one from the dashboard.

Reports not arriving despite "Delivered (HTTP 200)" → Check that the source slug in the dashboard matches PULSEHUB_SOURCE in your .env. The server identifies sources by their token, not by name.

"Server unreachable" but curl https://pulsehub.diqcare.com works → The queue worker is on a host with different outbound firewall rules. Try PULSEHUB_TRANSPORT=sync to isolate.

Reports stop arriving after deploy → The package config is cached. Run php artisan config:clear or php artisan config:cache.

Testing the package itself

composer install
./vendor/bin/phpunit

22 tests covering payload shape, queue dispatch, retries, failure categorization, and CLI commands.

Publishing to Packagist (maintainer notes)

After Packagist is set up, anyone in the world can run composer require pulsehub/laravel — no VCS or path repository tricks.

One-time setup

  1. Push to GitHub (the repo is https://github.com/taiaburbd/PulseHub).
  2. Remove the "version" field from composer.json — Packagist derives versions from Git tags. The field is only there today so path-repo installs resolve as 1.0.0 instead of dev-main.
  3. Tag the first release:
    git tag v1.0.0
    git push origin v1.0.0
  4. Submit at https://packagist.org/packages/submit, paste the GitHub URL. Packagist validates composer.json, scans tags, and the package goes live.
  5. Wire up the GitHub webhook (Settings → Webhooks → Add webhook) so Packagist picks up future tags automatically. Packagist provides the URL and secret in your package's "Settings" tab.

Cutting a new release

# 1. Bump CHANGELOG, commit
# 2. Tag and push
git tag v1.1.0
git push origin v1.1.0
# 3. Packagist picks it up via webhook (or hit "Update" in the Packagist UI)

Why the version field is in composer.json today

Composer's path repository assigns dev-main to every package unless the package's own composer.json declares a version. That made composer require pulsehub/laravel (no version constraint) fail with "Could not find a version… matching your minimum-stability (stable)".

The version: 1.0.0 we added is a local development aid. Strip it before submitting to Packagist (Composer prints a warning reminding you).

License

MIT — see LICENSE.