maksudur-dev/laravel-logpilot

A lightweight activity logging package for Laravel with request tracing.

Maintainers

Package info

github.com/maksudur-dev/laravel-logpilot

pkg:composer/maksudur-dev/laravel-logpilot

Transparency log

Statistics

Installs: 8

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

v1.0.3 2026-08-14 08:51 UTC

This package is auto-updated.

Last update: 2026-08-14 08:52:51 UTC


README

Latest Version on Packagist Total Downloads License

A lightweight Laravel activity logging package that improves debugging, tracing, and business-event visibility while using Laravel's EXISTING logging system or a database.

Key Features

  • Request Tracing: Group multiple logs under a single log_id automatically.
  • Dual Drivers: Support for Laravel Logs, Database, or both.
  • Auto-Context: Automatically captures User ID, IP, URL, and Method.
  • Model Support: Easily associate activities with Eloquent models.
  • API Support: Optional API endpoints to view activity logs.
  • Artisan Commands: Install, prune, and test your setup easily.
  • Laravel 8-13 & PHP 8.1+: Compatible with Laravel 8, 9, 10, 11, 12, and 13.
  • Lightweight: Zero-config by default, minimal overhead.

Installation

You can install the package via composer:

composer require maksudur-dev/laravel-logpilot

Run the installation command:

php artisan activity:install

If you are using the database driver, run the migrations:

php artisan migrate

Updating Package

To update the package to the latest version (v1.0.3):

composer update maksudur-dev/laravel-logpilot

Or target the version explicitly:

composer require maksudur-dev/laravel-logpilot:^1.0.3

If you are developing locally with a path repository in composer.json, simply run:

composer update maksudur-dev/laravel-logpilot

Configuration

The configuration file is located at config/logpilot.php.

return [
    'enabled' => env('LOGPILOT_ENABLED', true),
    'driver' => env('LOGPILOT_DRIVER', 'log'), // log, database, both
    'channel' => env('LOGPILOT_CHANNEL', null), // default log channel
    'auto_group_id' => true,
    'store_request_context' => true,
    'api_enabled' => env('LOGPILOT_API_ENABLED', false),
    'queue' => env('LOGPILOT_QUEUE', false),
    'retention_days' => 30,
];

Usage

1. Global Helper (Quickest)

activity('user_login');

// With details
activity('profile_updated', $user, 'User updated their profile photo');

// With array message (automatically cast to JSON)
activity('api_response', null, [
    'status' => 'success',
    'data' => ['id' => 1]
]);

// Full control
activity(
    action: 'withdraw_request',
    model: $user,
    message: 'Gateway timeout',
    level: 'error',
    meta: ['amount' => 500]
);

2. Eloquent Trait (Recommended for Models)

Add the LogsActivity trait to your models:

use LaravelLogPilot\Traits\LogsActivity;

class Order extends Model
{
    use LogsActivity;
}

// Now you can do:
$order->logActivity('shipped', 'Order has been shipped to customer');

// Retrieve logs for this model:
$logs = $order->activities;

3. Service Usage

Inject the ActivityLogger service into your classes:

use LaravelLogPilot\Services\ActivityLogger;

class PaymentService
{
    public function __construct(protected ActivityLogger $logger) {}

    public function process()
    {
        $this->logger->log('payment_started');
    }
}

4. Grouping Related Logs (Tracing)

Perfect for complex flows like checkouts or background jobs:

activity_group('checkout_flow_001');

activity('cart_validated');
activity('payment_processing');
activity('order_created'); // All will share log_id: checkout_flow_001

5. Clean Architecture (DTOs, Enums & Services)

LogPilot uses Clean Architecture patterns out-of-the-box. You can leverage Enums, DTOs, and Services in your application:

Enums

use LaravelLogPilot\Enums\LogLevel;
use LaravelLogPilot\Enums\ActivityAction;

activity(
    action: ActivityAction::UPDATED->value,
    message: 'User profile updated',
    level: LogLevel::WARNING
);

ActivityService & DTOs

use LaravelLogPilot\Services\ActivityService;
use LaravelLogPilot\DataTransferObjects\ActivityQueryDTO;

class ActivityReportController
{
    public function __construct(protected ActivityService $activityService) {}

    public function index(Request $request)
    {
        $dto = ActivityQueryDTO::fromRequest($request);
        $paginatedLogs = $this->activityService->getPaginatedLogs($dto);

        return response()->json($paginatedLogs);
    }
}

Encapsulated Model Query Methods

use LaravelLogPilot\Models\ActivityLog;

// Filtered logs via DTO
$logs = ActivityLog::fetchFiltered($queryDTO);

// Grouped trace logs by log_id
$traceLogs = ActivityLog::fetchByGroup('checkout_flow_001');

// Logs for a specific Eloquent model
$modelLogs = ActivityLog::fetchForModel(User::class, 1, perPage: 15);

Frontend Integration (Vue/React Example)

Since LogPilot provides an API, you can easily build a "Recent Activity" component.

Example Vue Component

<template>
  <div class="activity-feed">
    <div v-for="log in logs" :key="log.id" class="log-item">
      <span class="badge" :class="log.level">{{ log.action }}</span>
      <p v-if="typeof log.message === 'string'">{{ log.message }}</p>
      <pre v-else>{{ JSON.stringify(log.message, null, 2) }}</pre>
      <small>{{ formatDate(log.created_at) }}</small>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';

const props = defineProps(['modelType', 'modelId']);
const logs = ref([]);

onMounted(async () => {
  const response = await fetch(`/api/activity-logs/model/${props.modelType}/${props.modelId}`);
  const data = await response.json();
  logs.value = data.data;
});
</script>

Example React Component

import React, { useState, useEffect } from 'react';

const ActivityFeed = ({ modelType, modelId }) => {
  const [logs, setLogs] = useState([]);

  useEffect(() => {
    fetch(`/api/activity-logs/model/${modelType}/${modelId}`)
      .then(res => res.json())
      .then(data => setLogs(data.data));
  }, [modelType, modelId]);

  return (
    <div className="activity-feed">
      {logs.map(log => (
        <div key={log.id} className={`log-item ${log.level}`}>
          <span className="badge">{log.action}</span>
          {typeof log.message === 'object' ? (
            <pre>{JSON.stringify(log.message, null, 2)}</pre>
          ) : (
            <p>{log.message}</p>
          )}
          <small>{new Date(log.created_at).toLocaleString()}</small>
        </div>
      ))}
    </div>
  );
};

export default ActivityFeed;

Example Blade Component

If you prefer server-side rendering, you can pass logs to a Blade component:

{{-- In your controller --}}
$logs = $order->activities()->paginate(10);
return view('orders.show', compact('order', 'logs'));

{{-- In orders/show.blade.php --}}
<div class="activity-feed">
    @foreach($logs as $log)
        <div class="log-item {{ $log->level }}">
            <strong>{{ $log->action }}</strong>
            <div>
                @if(is_array($log->message))
                    <pre>{{ json_encode($log->message, JSON_PRETTY_PRINT) }}</pre>
                @else
                    {{ $log->message }}
                @endif
            </div>
            <small>{{ $log->created_at->diffForHumans() }}</small>
        </div>
    @endforeach
    {{ $logs->links() }}
</div>

API Support

LogPilot exposes clean, JSON-ready endpoints with comprehensive search, filtering, and pagination support:

  • GET /api/activity-logs: List and filter activity logs.
  • GET /api/activity-logs/levels: Get all log levels formatted for frontend select/dropdown inputs.
  • GET /api/activity-logs/trace/{log_id}: Trace a full request lifecycle by log_id.
  • GET /api/activity-logs/model/{type}/{id}: Activity for a specific resource.

Query Parameters & Filtering (GET /api/activity-logs)

You can pass query parameters to filter, search, and paginate logs:

Parameter Type Description Example
search / q / query string Search across action, message, url, log_id, ip, and model_type fields. ?search=Failed
level string Filter by log level (case-insensitive: error, warning, info, debug, critical, alert, emergency, notice). Pass all or empty to include all levels. ?level=Error
action string Filter by exact action name. ?action=USER_LOGIN
user_id mixed Filter logs for a specific User ID. ?user_id=42
log_id string Filter logs by trace ID (log_id). ?log_id=c2753c6f-6f06-...
model_type string Filter logs for a specific model class. ?model_type=App\Models\User
model_id mixed Filter logs for a specific model ID. ?model_id=5
start_date / date_from / from date Filter logs created on or after date/time. ?start_date=2026-08-01
end_date / date_to / to date Filter logs created on or before date/time. ?end_date=2026-08-14
per_page integer Results per page (default: 20, max: 500). ?per_page=50
page integer Page number for pagination (default: 1). ?page=2

Filtering Example

GET /api/activity-logs?search=Reward&level=Error&per_page=20&page=1

Artisan Commands

  • php artisan activity:install: Setup everything.
  • php artisan activity:prune: Cleanup old logs.
  • php artisan activity:test: Verify installation.

License

The MIT License (MIT). Please see License File for more information.