richness/laravel-monitoring-agent

Safely report Laravel application exceptions to a central monitoring server. Monitoring failure must never break the host application.

Maintainers

Package info

github.com/richnessagency/laravel-monitoring-agent

pkg:composer/richness/laravel-monitoring-agent

Transparency log

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-08-17 00:39 UTC

This package is auto-updated.

Last update: 2026-08-17 01:06:47 UTC


README

Latest Version on Packagist Software License

A production-grade, security-hardened, and lightweight monitoring client package for Laravel. It captures unhandled exceptions and logs them securely to an external Central Monitoring Server without affecting the host application's performance, stability, or database.

📖 Table of Contents

  1. Core Safety Philosophy
  2. Architecture Overview
  3. Installation
  4. Configuration Reference
  5. In-Depth Feature Explanations
  6. Developer API (Facade & Breadcrumbs)
  7. Console & Scheduling Commands
  8. Central Server API Ingestion Contracts
  9. Troubleshooting & FAQs

🛡️ Core Safety Philosophy

Important

THE MONITORING PACKAGE MUST NEVER BREAK THE HOST APPLICATION Error reporting is a secondary concern. The user-facing application lifecycle must remain fast, stable, and completely unimpeded.

  • Defensive Error Boundaries: Every remote call is wrapped in try-catch blocks with short timeouts (default: 2s connection timeout, 5s request timeout).
  • Circuit Breaker state-machine: Prevents cascade failures when the Central Server goes offline or experiences network congestion.
  • Zero-DB Footprint: Installs without any migrations, database tables, or queries, preserving database connection pools.
  • Re-Entry Protection: A thread-safe RecursionGuard prevents infinite loops if the package itself encounters an internal error during report delivery.

🏗️ Architecture Overview

The agent hooks directly into the Laravel Exception Handler container lifecycle, intercepting exceptions during boot:

Host App Exception
       │
       ▼
[RecursionGuard] (Checks nested call depth)
       │
       ▼
[Sanitization & Enrichment] (Strip secrets, read resources, check source context)
       │
       ▼
[Circuit Breaker]
       ├──► CLOSED: Attempt HTTP Transport
       │               ├──► Success (201): Event delivered.
       │               └──► Failure (5xx/429/Timeout): Writes to [Local Buffer]
       │
       └──► OPEN: Bypasses HTTP entirely, goes directly to [Local Buffer]

🚀 Installation

Install the package via Composer:

composer require richness/laravel-monitoring-agent

Publish the config file and initialize setup:

php artisan monitoring:install

This command publishes config/monitoring.php and runs test diagnostics.

⚙️ Configuration Reference

Below is the complete set of .env configurations supported:

# Enable/disable monitoring entirely
MONITORING_ENABLED=true

# Central Server Connection Settings
MONITORING_URL=https://monitor.example.com
MONITORING_TOKEN=mon_live_your_project_token_here

# Release & Server Identifiers
MONITORING_RELEASE=v1.0.4
MONITORING_SERVER_NAME=web-prod-01

# Transport Timeouts (in seconds)
MONITORING_CONNECT_TIMEOUT=2
MONITORING_TIMEOUT=5

# Circuit Breaker Options
MONITORING_CIRCUIT_BREAKER_ENABLED=true
MONITORING_CIRCUIT_FAILURE_THRESHOLD=5
MONITORING_CIRCUIT_COOLDOWN_SECONDS=60

# Capture Settings
MONITORING_CAPTURE_EXCEPTIONS=true
MONITORING_CAPTURE_LOGS=false
MONITORING_MIN_LEVEL=error

# Source Window & Breadcrumbs
MONITORING_SOURCE_CONTEXT=true
MONITORING_MAX_SOURCE_LINES=5
MONITORING_BREADCRUMBS=true
MONITORING_MAX_BREADCRUMBS=25

# Privacy Toggles
MONITORING_SEND_USER=false
MONITORING_SEND_IP=false
MONITORING_SEND_HOSTNAME=false

🔍 In-Depth Feature Explanations

Circuit Breaker State Machine

The Circuit Breaker prevents the application from hanging when the monitoring server is offline:

         [Closed]  ◄───────────────────────────┐
            │                                  │
      (5 consecutive                             │ (Success Probe)
         failures)                             │
            │                                  │
            ▼                                  │
          [Open]  ──► (60s Cooldown) ──► [Half-Open]
  1. Closed (Normal Operation): All events are sent immediately over HTTP. If a request fails, it records a failure.
  2. Open (Tripped State): Occurs after 5 consecutive failures. Outbound HTTP requests are blocked. Events go straight to the buffer.
  3. Half-Open (Testing Probe): Occurs after the 60-second cooldown has passed. The next event is sent via HTTP as a test probe. If successful, state returns to Closed. If it fails, state returns to Open.

Recursive Privacy Sanitizer

Our sanitizer scrubs payloads recursively to prevent credential leakage:

  • Redacted Keys: Matches keys containing password, secret, token, authorization, card, cvv, cookie, or session.
  • Trace Sanitization: Function argument lists in backtraces are completely removed to prevent DB password exposure.
  • Query Params: URL query strings (e.g. ?token=123) are parsed, redacted, and reconstructed.
  • Path Normalization: Replaces absolute host paths (e.g., /home/username/public_html/app) with relative roots (/app) to conceal folder structures.

Offline Local File Buffer

When the server is down, retryable events are written to storage/app/monitoring/:

  • Atomic Writes: Written to a temporary file first and renamed (rename()) to avoid partial write corruptions.
  • File Locks: Retry tasks acquire an exclusive lock (flock) on individual files to avoid concurrent retry tasks sending the same payload twice.
  • Pruning Policy: Enforces limits (default 500 files, 50MB) and evicts oldest items first (FIFO) to prevent server disk bloat.

Server Resource Collector

Every reported error automatically appends a resource snapshot:

  • PHP Memory: Current process memory usage, peak memory, and configured limit.
  • System Load: 1-minute, 5-minute, and 15-minute load averages via sys_getloadavg() (returns null on unsupported operating systems).
  • Disk Usage: Total, free, and used bytes of the main partition.
  • Writable Directories: Verifies permissions for storage/, storage/logs/, and bootstrap/cache/.

OOM Safety (Minimal Mode)

If the agent catches a fatal Out-Of-Memory (OOM) error or a Maximum Execution Time Exceeded error:

  • It bypasses expensive CPU and memory-intensive processes (like reading files for source code, scanning DB status, or traversing heavy stack frames).
  • It compiles a minimal payload containing the error class, OOM message, memory usage details, and basic environment details.
  • This ensures the report is delivered successfully before the PHP engine terminates.

🛠️ Developer API

Manual Capture

use Richness\LaravelMonitoring\MonitoringFacade as Monitoring;

try {
    // ...
} catch (\Throwable $e) {
    Monitoring::captureException($e);
}

Attaching Breadcrumbs

Breadcrumbs act as a timeline of events leading up to the error:

Monitoring::breadcrumb(
    message: 'User added item to cart',
    metadata: ['item_id' => 456, 'quantity' => 1],
    category: 'cart'
);

Custom Scope Context & Tags

Context attached to Monitoring is scoped to the current request and is automatically cleared in long-running processes (like Laravel Octane or Horizon):

Monitoring::context([
    'tenant_id' => 99,
    'user_tier' => 'premium',
])->tags([
    'feature' => 'billing',
]);

💻 Console & Scheduling Commands

The package includes Artisan commands to manage local buffering and diagnostics:

php artisan monitoring:test

Sends a mock connection test exception to the central server.

php artisan monitoring:health

Prints configuration status, local buffer metrics, circuit breaker state, and server resources.

php artisan monitoring:health-report

Gathers database/cache latency status and resource load, and sends a system health check payload to the server.

php artisan monitoring:retry

Attempts to deliver buffered events to the central server using exponential backoff.

php artisan monitoring:prune

Cleans up expired or over-budget buffered event files.

Automation via Laravel Scheduler:

Add the following tasks to routes/console.php:

use Illuminate\Support\Facades\Schedule;

Schedule::command('monitoring:health-report')->everyFiveMinutes();
Schedule::command('monitoring:retry')->everyFiveMinutes();
Schedule::command('monitoring:prune')->daily();

📡 Central Server API Ingestion Contracts

For your central server to process events, it must expose the following JSON API contracts:

1. Exception Report (POST /api/monitor/v1/errors)

{
  "schema_version": 1,
  "event_type": "error",
  "event_id": "01M6HV2NVJ...",
  "timestamp": "2026-08-17T03:00:00+00:00",
  "correlation_id": "01M6HV2NT...",
  "environment": "production",
  "release": "v1.0.4",
  "server_name": "web-prod-01",
  "level": "error",
  "exception_class": "RuntimeException",
  "message": "Division by zero",
  "code": 0,
  "file": "/app/Http/Controllers/MathController.php",
  "line": 42,
  "category": "application",
  "previous_exceptions": [],
  "trace": [],
  "resources": {}
}

2. Health Check (POST /api/monitor/v1/health)

{
  "schema_version": 1,
  "event_type": "health",
  "event_id": "01M6HV2NV...",
  "timestamp": "2026-08-17T03:00:00+00:00",
  "environment": "production",
  "release": "v1.0.4",
  "server_name": "web-prod-01",
  "resources": {
    "memory": {},
    "load_average": {},
    "disk": {},
    "storage": {},
    "runtime": {}
  },
  "services": {
    "database": {
      "reachable": true,
      "latency_ms": 15
    },
    "cache": {
      "working": true
    }
  }
}

❓ Troubleshooting & FAQs

Q: Does the package buffer errors in database tables? No. It has a zero-DB footprint. It buffers failed events strictly as flat .json files inside storage/app/monitoring/ to ensure no load is placed on MySQL/PostgreSQL during outages.

Q: Can I use this in Octane / Swoole daemons? Yes. All context memory storage is managed by MonitoringContextStore utilizing Laravel's request-lifecycle container bindings, preventing memory leaks between separate HTTP worker requests.

Q: How do I know if the Circuit Breaker is tripped? Run php artisan monitoring:health. It will report the current status: Closed, Open, or Half-Open.

📄 License

The MIT License (MIT). See LICENSE.md for details.