PHPackages                             bluecapapps/downctl-laravel - 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. bluecapapps/downctl-laravel

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

bluecapapps/downctl-laravel
===========================

Laravel integration for the Downctl error and metrics reporting API.

v1.1.1(1mo ago)06MITPHPPHP ^8.2

Since May 25Pushed 1mo agoCompare

[ Source](https://github.com/bluecapapps/downctl-laravel)[ Packagist](https://packagist.org/packages/bluecapapps/downctl-laravel)[ RSS](/packages/bluecapapps-downctl-laravel/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (4)Dependencies (13)Versions (5)Used By (0)

bluecapapps/downctl-laravel
===========================

[](#bluecapappsdownctl-laravel)

Laravel integration for the Downctl error and metrics reporting API. It adds automatic exception capture, a Facade, queue support, and an Artisan health-check command.

Requirements
------------

[](#requirements)

- PHP 8.2+
- Laravel 10, 11, 12, or 13
- `curl` extension

Installation
------------

[](#installation)

```
composer require bluecapapps/downctl-laravel
```

The service provider and `Downctl` facade are registered automatically via Laravel's package auto-discovery.

### Publish the config file

[](#publish-the-config-file)

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

This creates `config/downctl.php` in your application.

Configuration
-------------

[](#configuration)

Add your server-side API key to `.env`:

```
DOWNCTL_API_KEY=your-secret-api-key
```

Downctl reports are always sent to `https://downctl.com`; there is no URL setting to configure.

KeyEnv variableDefaultDescription`api_key``DOWNCTL_API_KEY``null`Server-side secret key`public_key``DOWNCTL_PUBLIC_KEY``null`Public key for frontend JS use`silent``DOWNCTL_SILENT``true`Swallow transport errors`queue``DOWNCTL_QUEUE``false`Report asynchronously via a queue job`capture_level``DOWNCTL_CAPTURE_LEVEL``error`Minimum log level to auto-capture`redact_context``DOWNCTL_REDACT_CONTEXT``true`Redact sensitive context values`redacted_value`-`[REDACTED]`Replacement for redacted values`max_context_depth`-`8`Maximum nested context depth`redacted_keys`-see configContext keys redacted at any nesting levelIf `DOWNCTL_API_KEY` is missing, automatic capture is skipped so a newly installed application will not crash before credentials are configured.

### Verify your setup

[](#verify-your-setup)

```
php artisan downctl:test
```

This pings Downctl and sends a test `info` report.

Usage
-----

[](#usage)

### Facade

[](#facade)

```
use Bluecapapps\DownctlLaravel\Facades\Downctl;

Downctl::captureException($e);

Downctl::report('Stripe webhook signature invalid', level: 'error');

Downctl::captureException($e, level: 'warning', context: [
    'user_id' => auth()->id(),
    'plan' => $user->plan,
]);
```

### Dependency injection

[](#dependency-injection)

The underlying client is bound as a singleton and can be injected anywhere:

```
use Bluecapapps\DownctlLaravel\DownctlClient;

class PaymentService
{
    public function __construct(private DownctlClient $downctl) {}

    public function charge(Order $order): void
    {
        try {
            $this->gateway->charge($order);
        } catch (\Throwable $e) {
            $this->downctl->captureException($e, context: ['order_id' => $order->id]);
            throw $e;
        }
    }
}
```

Automatic Capture
-----------------

[](#automatic-capture)

The package listens to Laravel's `MessageLogged` event and forwards any log entry at or above `capture_level` to Downctl. No changes to your exception handler are required.

Laravel uses the full PSR-3 scale (`debug`, `info`, `notice`, `warning`, `error`, `critical`, `alert`, `emergency`). Downctl accepts three levels, so the listener normalizes them:

Laravel log levelReported as`error`, `critical`, `alert`, `emergency``error``warning``warning``info`, `notice`, `debug``info`Capture only `error` and above:

```
DOWNCTL_CAPTURE_LEVEL=error
```

Capture `warning` and above:

```
DOWNCTL_CAPTURE_LEVEL=warning
```

Disable automatic capture entirely:

```
DOWNCTL_CAPTURE_LEVEL=
```

With capture disabled you can still call `Downctl::captureException()` manually.

### Context redaction

[](#context-redaction)

Report context is redacted by default before it is sent to Downctl. When `DOWNCTL_QUEUE=true`, context is redacted before the queued job is stored, so queue payloads do not contain the original sensitive values.

Downctl assumes encrypted transport and trusted source and destination systems, so the default redaction policy preserves troubleshooting detail such as user IDs, order IDs, route names, statuses, and email addresses. It redacts high-confidence secret keys such as `password`, `access_token`, `refresh_token`, `api_key`, `authorization`, `cookie`, `client_secret`, `session_id`, and `private_key`. Matching is case-insensitive and applies at any nesting level. You can customize the list in `config/downctl.php`.

Context objects are always normalized before sending, even when `redact_context` is disabled. Laravel `Arrayable` objects and `JsonSerializable` objects are converted and redacted recursively, `Stringable` objects are sent as strings, and other objects are summarized by class name. Deeply nested context is bounded by `max_context_depth`.

Log messages and stack traces are sent as-is. Avoid placing secrets directly in log message text or exception messages.

Queue Support
-------------

[](#queue-support)

```
DOWNCTL_QUEUE=true
```

When enabled, the `CaptureLoggedError` listener dispatches a `SendDownctlReport` job instead of making a direct HTTP call. The job retries 3 times with a 30-second backoff.

You must have a working queue driver configured. The `sync` driver sends reports immediately, the same as `DOWNCTL_QUEUE=false`.

Cron Monitoring
---------------

[](#cron-monitoring)

Cron monitoring lets Downctl alert you when a scheduled job misses its expected window, takes too long, or exits with an error. Each monitor has a unique ping token; your job hits that URL to prove it ran.

### 1. Create a monitor in Downctl

[](#1-create-a-monitor-in-downctl)

Open your site in Downctl, navigate to **Cron monitors**, and add a monitor. Set the schedule (cron expression or a simple minute frequency) and a grace period. Copy the ping token shown on the monitor card.

Monitor ping tokens are credentials. Store them in `.env` rather than writing them directly in `routes/console.php`:

```
DOWNCTL_REPORTS_DAILY_MONITOR_TOKEN=a1b2c3d4e5f6...
DOWNCTL_CACHE_PRUNE_MONITOR_TOKEN=x7y8z9...
```

Expose the values through a Laravel config file, such as `config/downctl.php`, so they continue to work when configuration is cached:

```
'monitors' => [
    'reports_daily' => env('DOWNCTL_REPORTS_DAILY_MONITOR_TOKEN'),
    'cache_prune' => env('DOWNCTL_CACHE_PRUNE_MONITOR_TOKEN'),
],
```

### 2. Add the Schedule macro

[](#2-add-the-schedule-macro)

In your `routes/console.php`, chain `->cronMonitor()` onto each scheduled task using the configured token:

```
use Illuminate\Support\Facades\Schedule;

Schedule::command('reports:daily')
    ->dailyAt('06:00')
    ->cronMonitor(config('downctl.monitors.reports_daily'));

Schedule::command('cache:prune')
    ->hourly()
    ->cronMonitor(config('downctl.monitors.cache_prune'));
```

The macro automatically:

- Pings `/started` immediately before the task runs.
- Pings `/finished` (with the measured runtime in seconds) after a successful run.
- Pings `/failed` if the command exits with a non-zero code.

No other changes are required. Downctl updates the monitor status in real time and opens an alert incident if a ping does not arrive within the configured grace period.

### 3. Verify your configuration

[](#3-verify-your-configuration)

```
php artisan downctl:crons:sync
```

This lists every scheduled task that has `->cronMonitor()` applied and shows the ping URL it will call:

```
+---------------------+-------------+----------------------------------------------------------+
| Task                | Schedule    | Ping URL                                                 |
+---------------------+-------------+----------------------------------------------------------+
| reports:daily       | 0 6 * * *   | https://downctl.com/ping/cron/a1b2c3d4e5f6...           |
| cache:prune         | 0 * * * *   | https://downctl.com/ping/cron/x7y8z9...                 |
+---------------------+-------------+----------------------------------------------------------+

```

### Manual pinging

[](#manual-pinging)

For jobs that run outside the Laravel scheduler (queue workers, shell scripts, external cron jobs), ping the URLs directly using the Facade or client:

```
use Bluecapapps\DownctlLaravel\Facades\Downctl;

// Simple heartbeat — marks the monitor as healthy
Downctl::pingCron('your-token');

// Lifecycle pings with optional metadata
Downctl::pingCronStarted('your-token');

Downctl::pingCronFinished('your-token', [
    'runtime'     => 12.4,  // seconds
    'memory'      => 52428800,  // bytes
]);

Downctl::pingCronFailed('your-token', [
    'exit_code'       => 1,
    'failure_message' => 'Connection to database timed out',
]);
```

Ping URLs do not require the API key; the token in the URL is the credential. You can also call them with a plain `curl` from a shell script:

```
# Simple ping
curl -s "https://downctl.com/ping/cron/your-token"

# With lifecycle and metadata
curl -s "https://downctl.com/ping/cron/your-token/started"
curl -s -X POST "https://downctl.com/ping/cron/your-token/finished" \
     -H "Content-Type: application/json" \
     -d '{"runtime": 4.2, "exit_code": 0}'
curl -s -X POST "https://downctl.com/ping/cron/your-token/failed" \
     -H "Content-Type: application/json" \
     -d '{"exit_code": 1, "failure_message": "Unexpected error"}'
```

### Accepted ping metadata

[](#accepted-ping-metadata)

FieldTypeDescription`runtime`floatJob duration in seconds`memory`intPeak memory usage in bytes`exit_code`intProcess exit code (non-zero promotes a `/finished` ping to `/failed`)`failure_message`stringHuman-readable failure reason (max 255 chars)All fields are optional. A non-zero `exit_code` sent to any endpoint is always treated as a failure.

Troubleshooting
---------------

[](#troubleshooting)

### `downctl:test` reports "Health check failed"

[](#downctltest-reports-health-check-failed)

- Confirm `DOWNCTL_API_KEY` is set.
- Check that the app can reach `https://downctl.com/api/v1/health`.
- Set `DOWNCTL_SILENT=false` locally if you want transport failures to throw.

### Errors are not appearing in Downctl

[](#errors-are-not-appearing-in-downctl)

1. Run `php artisan downctl:test`.
2. Check `DOWNCTL_CAPTURE_LEVEL`.
3. Make sure `DOWNCTL_API_KEY` is set.
4. If `DOWNCTL_QUEUE=true`, make sure your queue worker is running.

### Reports appear in Downctl but are missing stack traces

[](#reports-appear-in-downctl-but-are-missing-stack-traces)

Laravel only includes the `exception` key in the log context when you use `Log::error('message', ['exception' => $e])` or when the exception handler logs it. If you call `Log::error('message')` without an exception object, no stack trace is available. Use `Downctl::captureException($e)` directly when you have a `Throwable`.

### Auto-discovery is not registering the provider

[](#auto-discovery-is-not-registering-the-provider)

Check that `dont-discover` in your `composer.json` does not include `bluecapapps/downctl-laravel`. If you've disabled auto-discovery project-wide, register the provider manually:

```
// bootstrap/providers.php (Laravel 11+)
return [
    Bluecapapps\DownctlLaravel\DownctlServiceProvider::class,
];
```

```
// config/app.php (Laravel 10)
'providers' => [
    Bluecapapps\DownctlLaravel\DownctlServiceProvider::class,
],
```

Running the tests
-----------------

[](#running-the-tests)

```
composer install
./vendor/bin/pest
```

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance93

Actively maintained with recent releases

Popularity6

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity49

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 ~9 days

Total

4

Last Release

33d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/264159736?v=4)[mgibson-bca](/maintainers/mgibson-bca)[@mgibson-bca](https://github.com/mgibson-bca)

---

Top Contributors

[![mgibson-bca](https://avatars.githubusercontent.com/u/264159736?v=4)](https://github.com/mgibson-bca "mgibson-bca (6 commits)")

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/bluecapapps-downctl-laravel/health.svg)

```
[![Health](https://phpackages.com/badges/bluecapapps-downctl-laravel/health.svg)](https://phpackages.com/packages/bluecapapps-downctl-laravel)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M347](/packages/psalm-plugin-laravel)[laravel/mcp

Rapidly build MCP servers for your Laravel applications.

77922.3M186](/packages/laravel-mcp)[illuminate/auth

The Illuminate Auth package.

10528.2M1.3k](/packages/illuminate-auth)[api-platform/laravel

API Platform support for Laravel

58174.6k17](/packages/api-platform-laravel)[defstudio/telegraph

A laravel facade to interact with Telegram Bots

813336.8k3](/packages/defstudio-telegraph)[illuminate/routing

The Illuminate Routing package.

1419.2M3.2k](/packages/illuminate-routing)

PHPackages © 2026

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