laikmosh/plog

Advanced Laravel logging system with metadata capture, tagging, and powerful filtering

Maintainers

Package info

github.com/laikmosh/plog

pkg:composer/laikmosh/plog

Transparency log

Statistics

Installs: 53

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.8 2025-12-08 17:06 UTC

This package is auto-updated.

Last update: 2026-08-13 05:11:37 UTC


README

Plog is a powerful Laravel logging enhancement package that captures extensive metadata, supports tagging, and provides an interactive web interface for log exploration.

Features

  • Automatic Metadata Capture: User ID, Session ID, Request ID, file/line, class/method
  • Request Tracking: Track logs across HTTP requests, queued jobs, and CLI commands
  • Tagging System: Organize logs with tags for easy filtering
  • Interactive Web Interface: Filter, search, and explore logs with Livewire + Alpine.js
  • Flexible Storage: SQLite by default, configurable to any Laravel database
  • Granular Retention: Configure different retention periods for different log types

Installation

composer require laikmosh/plog

Configuration

Publish the configuration file and assets:

php artisan vendor:publish --tag=plog-config
php artisan vendor:publish --tag=plog-assets

Run migrations:

php artisan migrate

Environment Variables

# Enable/disable Plog
PLOG_ENABLED=true

# Authorized emails (comma-separated)
PLOG_AUTHORIZED_EMAILS=admin@example.com,developer@example.com

# Database connection (optional, defaults to SQLite)
PLOG_DB_CONNECTION=plog

# Default retention period
PLOG_RETENTION_DAYS=7

# Enable automatic cleanup
PLOG_CLEANUP_ENABLED=true

Usage

Basic Logging

All existing Laravel log calls automatically capture metadata:

Log::info('User logged in', ['user_id' => $user->id]);
Log::error('Payment failed', ['order_id' => $orderId]);

Using Tags

Add tags through the plog:tags context key — the one and only tagging syntax:

use Illuminate\Support\Facades\Log;

Log::info('Order processed', [
    'order_id' => $orderId,
    'plog:tags' => ['payment', 'stripe'],
]);

Log::error('Connection failed', ['plog:tags' => ['database', 'error']]);

Log::warning('Slow query', [
    'time' => 2.5,
    'plog:tags' => ['performance', 'database'],
]);

// The plog:tags key is extracted and stored as queryable tags;
// it never appears in the stored context data.

This works with all Laravel log methods on any channel. Because the key is a plain string literal (never a plog class constant or method), call sites survive uninstalling plog: standard Laravel simply logs the key as ordinary context, and nothing breaks. The vendor-namespaced plog: prefix keeps it from colliding with real context keys.

The same convention carries durations: pass 'plog:response_time' => $seconds in context and plog lifts it into the entry's response_time column.

Watchers

Opt-in watchers record framework activity as regular entries — filterable by tag, correlated with the request that caused them, and carrying the app call site like any other entry. Both are configured under plog.watchers and disabled by default.

Redis (plog.watchers.redis) — records commands via Laravel's CommandExecuted/CommandFailed events, tagged redis and redis:<connection>, with the duration in response_time. Guardrails: slower_than (ms threshold; 0 records everything), ignore_commands, and wildcard ignore_key_patterns (Horizon and queue chatter is ignored out of the box). Failed commands log as warnings.

Models (plog.watchers.models) — records Eloquent lifecycle events (created, updated, deleted, restored, forceDeleted — exactly the hooks observers run on), tagged eloquent and eloquent:<action>. Updates store the changed attributes (values truncated), creates store attribute names, deletes log at info level. Configure events to narrow the list and ignore to skip model classes; plog's own models are always skipped.

Viewing Logs

Access the web interface at the path configured in plog.route.path/logs by default, overridable via PLOG_ROUTE_PATH (requires authentication and authorization).

The interface allows you to:

  • Filter by level, user, request ID, session, environment, endpoint, and tags
  • Search through log messages and context
  • Click any field to instantly filter by that value
  • View detailed log entries with full context
  • Group logs by request to trace execution flow

Database Viewer

A second section of the web UI (the Database link in the header, or /logs/db) browses and edits the host app's databases:

  • Left column — every configured connection (default preselected), and the selected connection's tables from live schema introspection. Tables backed by an Eloquent model show a badge; models are auto-discovered by scanning plog.db.model_paths (defaults to app/Models) and correlated by table + connection.
  • Middle column — column/operator/value filters, free-text search across text columns, sortable headers, and incremental "load more" pagination. Model-backed tables get a collapsible intel strip: relations, casts, fillable/guarded/hidden, dispatched events, observers, rules(), global scopes.
  • Right column — the selected record with type-aware editable fields (bool checkboxes, datetime pickers, JSON textareas with validation, NULL toggles), Save/Delete (soft-delete aware), and relationship chips that navigate to related records. A breadcrumb trail tracks the navigation; each crumb's ▾ lists its siblings.

Behavior worth knowing:

  • Listing reads through the query builder (global scopes don't hide rows; soft-deleted rows are tinted). Writes go through the model when one exists — via forceFill, and model events, observers and the model watcher fire. If the model defines rules(), changed columns are validated before saving.
  • Tables without a single-column primary key are browse-only.
  • Access is gated by viewPlogDb (defaults to the viewPlog email allowlist — an empty allowlist means everyone). Set PLOG_DB_READONLY=true to disable all writes server-side; PLOG_DB_ENABLED=false removes the section entirely.
'db' => [
    'enabled' => env('PLOG_DB_ENABLED', true),
    'read_only' => env('PLOG_DB_READONLY', false),
    'connections' => ['only' => [], 'exclude' => []],
    'model_paths' => [],          // relative to base_path(); empty ⇒ app/Models
    'model_exclude' => [],        // class names or glob patterns
    'model_cache_ttl' => 300,     // seconds; 0 disables the discovery cache
    'per_page' => 50,
    'list_columns' => 8,
    'sibling_limit' => 25,
    'hidden_tables' => [],
],

On Laravel 10 without doctrine/dbal, column types can't be introspected and the viewer degrades to read-only browsing; Laravel 11+ needs nothing extra.

Advanced Configuration

Custom Database Connection

In config/plog.php:

'database' => [
    'connection' => 'mysql', // Use your app's main database
    'table' => 'plog_entries',
],

Retention Policies

Configure granular retention rules:

'retention' => [
    'default_days' => 7,
    'rules' => [
        ['tags' => ['payment'], 'days' => 30],
        ['tags' => ['authentication'], 'days' => 90],
        ['level' => 'error', 'days' => 14],
    ],
],

Authorization

Control access via email whitelist:

'authorized_emails' => [
    'admin@example.com',
    'developer@example.com',
],

Or customize the gate in your AuthServiceProvider:

Gate::define('viewPlog', function ($user) {
    return $user->hasRole('admin');
});

Request ID Tracking

Plog automatically generates and tracks request IDs across:

  • HTTP requests
  • Queued jobs (preserves original request ID)
  • CLI commands

Access the current request ID:

use Laikmosh\Plog\Services\RequestIdService;

$requestId = app(RequestIdService::class)->getRequestId();

Captured Metadata

Each log entry captures:

  • Time: Timestamp with microseconds
  • Level: debug, info, notice, warning, error, critical, alert, emergency
  • Message: Log message
  • Context: Additional data passed to the log
  • User ID: Currently authenticated user
  • Session ID: Current session identifier
  • Request ID: Unique request identifier
  • Environment: http, cli, queue, testing
  • Endpoint: Route name or URI, CLI command
  • File & Line: Source code location
  • Class & Method: Calling class and method
  • Tags: Custom tags for organization

Performance Considerations

  • Logs are written synchronously by default
  • Consider using a dedicated database for high-volume applications
  • Indexes are automatically created for common query patterns
  • Use retention policies to manage database size

License

MIT