LaraLogsToolkit is a package that allows you to analyze your logs and get the count of errors, info and warnings.
ravols/lara-logs-toolkit is a Laravel package for laralogstoolkit is a package that allows you to analyze your logs and get the count of errors, info and warnings..
It currently has 0 GitHub stars and 6 downloads on Packagist (latest version 1.1.0).
Install it with composer require ravols/lara-logs-toolkit.
Discover more Laravel packages by ravols
or browse all Laravel packages to compare alternatives.
Last updated
A Laravel package that helps you track deployments and monitor log file growth by providing deployment markers and log record counting capabilities.
The Issue: After a deployment, your logs might start filling up with errors, but if you're distracted or not actively monitoring, you might miss critical issues until they become severe.
The Solution: This package provides a command to quickly check how many log records exist in any specified log channel from your config/logging.php. Run it after deployments or set it up in monitoring to get instant visibility into log growth.
Extended Possibilities: You can create your own custom commands that check for new log records and send notifications (Slack, email, or SMS) when a threshold is met. This allows you to set up automated alerting that triggers when log growth exceeds acceptable levels after deployments.
The Issue: When you see errors in your logs, it's often impossible to tell if they happened before or after your latest deployment. This makes debugging much harder, especially when you need to determine if a deployment introduced new issues.
The Solution: This package automatically logs a timestamp marker whenever composer dump-autoload finishes. By adding a single line to your composer.json, you'll have clear deployment markers in your logs, making it easy to see which errors occurred before or after each deployment.
You can install the package via composer:
composer require ravols/lara-logs-toolkit
Publish the configuration file:
php artisan vendor:publish --tag=lara-logs-toolkit-config
This will create config/lara-logs-toolkit.php where you can configure the composer dump-autoload log channel and cache settings:
'composer_dump_autoload_channel' => env('LARA_LOGS_TOOLKIT_COMPOSER_DUMP_AUTOLOAD_CHANNEL', 'daily'),
'comparison_cache_ttl' => env('LARA_LOGS_TOOLKIT_COMPARISON_CACHE_TTL', 600),
Configuration Options:
composer_dump_autoload_channel - The log channel where the composer dump-autoload notification will be written. This should match one of the channels defined in your application's logging configuration (default: daily)comparison_cache_ttl - Cache time-to-live in seconds for storing log analysis comparison results (default: 600 seconds / 10 minutes)To automatically log when composer dump-autoload finishes, you need to add the command to your composer.json file.
Step 1: Open your composer.json file in the root of your Laravel project.
Step 2: Find the scripts section. If it doesn't exist, create it at the root level of your JSON.
Step 3: Add or update the post-autoload-dump array. Add "@php artisan lara-logs:composer-dump-autoload" as the last item in the array.
Example - of a post-autoload-dump script:
{
"scripts": {
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi",
"@php artisan lara-logs:composer-dump-autoload"
]
}
}
Important: The line "@php artisan lara-logs:composer-dump-autoload" should be added as the last item in the post-autoload-dump array, after the existing Laravel commands.
Now, every time you run composer dump-autoload (which happens automatically during deployments), you'll see a log entry like:
[2025-12-25 11:01:23] local.INFO: Composer dump-autoload finished at 2025-12-25 11:01:23
This creates a clear marker in your logs, making it easy to identify which errors occurred before or after each deployment.
To check how many log records exist in a specific channel:
php artisan lara-logs:check-records [channel]
If no channel is specified, it defaults to daily.
Examples:
# Check the default channel (from config)
php artisan lara-logs:check-records
# Check a specific channel
php artisan lara-logs:check-records daily
php artisan lara-logs:check-records api
The command will output:
Channel 'daily' contains 1523 log record(s).
This is especially useful after deployments to quickly see if error counts have increased, or you can integrate it into your monitoring/alerting system.
To delete log records from configured log channels:
php artisan lara-logs:delete-logs
Options:
--channels=* - Comma-separated list of log channel names to delete (e.g., --channels=daily,api)--action= - Delete action: latest or all (defaults to interactive selection)Examples:
# Interactive mode - select channels and action
php artisan lara-logs:delete-logs
# Delete all logs from specific channels
php artisan lara-logs:delete-logs --channels=daily,api --action=all
# Delete latest record from a single channel
php artisan lara-logs:delete-logs --channels=single --action=latest
# Multiple channels with comma-separated list
php artisan lara-logs:delete-logs --channels=daily,api --action=all
Interactive Features:
Safety Features:
Delete Actions:
latest - Deletes the latest log file for each selected channelall - Deletes all log files for each selected channel (handles both single and daily log file formats)The package provides a method to compare current log analysis with previously cached results. This is useful for detecting changes in log counts over time:
use Illuminate\Support\Facades\Log;
use Ravols\LaraLogsToolkit\Facades\LaraLogsToolkit;
$logger = Log::channel('daily');
$comparison = LaraLogsToolkit::getLogAnalysisComparison($logger);
// Access the results using properties
$currentCounts = $comparison->current; // LogCountsData
$cachedCounts = $comparison->cached; // LogCountsData
$differences = $comparison->differences; // LogCountsData
// Example: Check if errors increased using methods
if ($comparison->isNewError()) {
echo "Errors increased by {$comparison->getNewErrorCount()} since last check\n";
}
// Or access directly via properties
if ($comparison->differences->error > 0) {
echo "Errors increased by {$comparison->differences->error} since last check\n";
}
// Use helper methods for convenience
if ($comparison->hasAnyNewIssues()) {
echo "Total new issues: {$comparison->getTotalNewIssuesCount()}\n";
echo "New errors: {$comparison->getNewErrorCount()}\n";
echo "New warnings: {$comparison->getNewWarningCount()}\n";
}
// Check when the cache was created
if ($comparison->cachedAt !== null) {
echo "Cache was created at: {$comparison->cachedAt}\n";
} else {
echo "No previous cache found (first run)\n";
}
The method automatically caches the current analysis results for comparison on the next call. The cache TTL is configurable via config/lara-logs-toolkit.php using the comparison_cache_ttl key (default: 600 seconds).
Return Type: LogAnalysisComparisonData containing:
current - LogCountsData with current log counts by levelcached - LogCountsData with previously cached log countsdifferences - LogCountsData showing the difference between current and cached (current - cached)logFileName - The log file name used for cachingcachedAt - DateTime string (e.g., "2025-01-15 10:30:45") indicating when the cache was created, or null if no cache existedLogCountsData Properties:
error, info, warning, emergency, alert, critical, debug, notice - Individual log level countsgetTotal() - Get total count across all levelsYou can analyze all log channels at once using getAllChannelsLogAnalysis(). This method automatically excludes certain channels by default (like stack, null, single, daily, etc.) but allows you to customize which channels to include or exclude.
use Ravols\LaraLogsToolkit\Facades\LaraLogsToolkit;
// Analyze all channels (excluding defaults)
$analysis = LaraLogsToolkit::getAllChannelsLogAnalysis();
// Get aggregated totals across all channels
$totalErrors = $analysis->getError();
$totalWarnings = $analysis->getWarning();
$total = $analysis->getTotal();
// Get specific channel data
$carriersData = $analysis->getChannel('carriers');
if ($carriersData) {
$carriersErrors = $carriersData->error;
}
// With caching/comparison enabled
$analysis = LaraLogsToolkit::getAllChannelsLogAnalysis(useCache: true);
// Access comparison data for specific channels
$comparison = $analysis->getComparisonChannel('carriers');
if ($comparison && $comparison->hasAnyNewIssues()) {
$newErrors = $comparison->getNewErrorCount();
echo "New errors in carriers channel: {$newErrors}\n";
}
// Customize excluded channels
$analysis = LaraLogsToolkit::excludeChannels(['stack', 'null', 'slack'])
->getAllChannelsLogAnalysis();
// Include a normally excluded channel
$analysis = LaraLogsToolkit::includeChannels('stack')
->getAllChannelsLogAnalysis();
// Chain configuration methods
$analysis = LaraLogsToolkit::excludeChannels(['carriers'])
->includeChannels('stack')
->getAllChannelsLogAnalysis(useCache: true);
Default Excluded Channels: single, daily, null, papertrail, stderr, syslog, errorlog, slack, emergency
AllChannelsLogAnalysisData Methods:
getChannel(string $channelName) - Get data for a specific channelgetChannels() - Get all channels datagetError(), getInfo(), getWarning(), etc. - Aggregated totals across all channelsgetTotal() - Total count across all channels and log levelsgetComparisonChannel(string $channelName) - Get comparison data for a channelhasComparisonData() - Check if any channels have comparison datatoArray() - Convert to array formatYou can create your own commands that monitor log growth and send notifications when thresholds are exceeded. Here's an example:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
use Ravols\LaraLogsToolkit\LaraLogsToolkit;
class MonitorLogGrowth extends Command
{
protected $signature = 'logs:monitor {channel=daily : The log channel to monitor} {--threshold=100 : Alert threshold}';
protected $description = 'Monitor log growth and send alerts when threshold is exceeded';
public function handle(LaraLogsToolkit $laraLogsToolkit): int
{
$channel = $this->argument('channel');
$threshold = (int) $this->option('threshold');
$logger = Log::channel($channel);
// Get total count
$logCounts = $laraLogsToolkit->getLogAnalysis($logger);
$count = $logCounts->getTotal();
// Or get count for a specific log level
// $count = $logCounts->error; // or $logCounts->warning, etc.
// Or compare with cached results to detect changes
// $comparison = $laraLogsToolkit->getLogAnalysisComparison($logger);
// if ($comparison->isNewError()) {
// $newErrors = $comparison->getNewErrorCount();
// // Handle new errors since last check
// }
if ($count > $threshold) {
// Send Slack notification
Notification::route('slack', config('services.slack.webhook_url'))
->notify(new LogThresholdExceeded($channel, $count, $threshold));
// Or send email
// Mail::to(config('app.admin_email'))->send(new LogAlert($channel, $count));
// Or send SMS
// Notification::route('vonage', config('app.admin_phone'))
// ->notify(new LogThresholdExceeded($channel, $count, $threshold));
$this->warn("Alert sent! Channel '{$channel}' has {$count} records (threshold: {$threshold})");
return self::FAILURE;
}
$this->info("Channel '{$channel}' is within limits ({$count} records)");
return self::SUCCESS;
}
}
You can then schedule this command in your app/Console/Kernel.php:
protected function schedule(Schedule $schedule): void
{
// Check every 5 minutes after deployment
$schedule->command('logs:monitor daily --threshold=100')->everyFiveMinutes();
}
LogCountsDataRepresents log counts for all log levels. Provides readonly properties for direct access to log level counts.
Properties:
error, info, warning, emergency, alert, critical, debug, notice - Individual log level countsMethods:
getTotal() - Get total count across all levelstoArray() - Convert to array formatfromArray(array $counts): self - Static factory method to create from arrayExample:
$logCounts = LaraLogsToolkit::getLogAnalysis(Log::channel('daily'));
// Access individual log level counts via properties
$errors = $logCounts->error;
$warnings = $logCounts->warning;
$info = $logCounts->info;
// Get total count across all levels
$total = $logCounts->getTotal();
LogAnalysisComparisonDataRepresents a comparison between current and cached log analysis results.
Properties:
current - LogCountsData with current log countscached - LogCountsData with previously cached log countsdifferences - LogCountsData showing differences (current - cached)logFileName - The log file name used for cachingcachedAt - DateTime string (e.g., "2025-01-15 10:30:45") indicating when the cache was created, or null if no cache existedHelper Methods:
isNewError(), isNewWarning(), isNewCritical(), isNewAlert(), isNewEmergency() - Boolean checks for new entrieshasAnyNewIssues() - Check if there are any new issuesgetNewErrorCount(), getNewWarningCount(), etc. - Get count of new entries (returns 0 if negative)getTotalNewIssuesCount() - Get total count of all new issuesgetTotalNewCount() - Get total count of all new log entriesgetCurrentErrorCount(), getCurrentWarningCount() - Get current countsgetCachedErrorCount(), getCachedWarningCount() - Get cached countsExample:
$comparison = LaraLogsToolkit::getLogAnalysisComparison(Log::channel('daily'));
// Check for new errors
if ($comparison->isNewError()) {
$newErrors = $comparison->getNewErrorCount();
}
// Access properties directly
$currentErrors = $comparison->current->error;
$cachedErrors = $comparison->cached->error;
$errorDiff = $comparison->differences->error;
// Check when cache was created
if ($comparison->cachedAt) {
echo "Last cached at: {$comparison->cachedAt}\n";
}
The LaraLogsToolkit class provides the following methods:
getLogAnalysis(LoggerInterface $logger): LogCountsDataAnalyzes logs and returns a LogCountsData with detailed log counts by level.
$logCounts = LaraLogsToolkit::getLogAnalysis(Log::channel('daily'));
// Access individual log level counts
$errorCount = $logCounts->error;
$infoCount = $logCounts->info;
$warningCount = $logCounts->warning;
// Get total count across all levels
$total = $logCounts->getTotal();
getLogAnalysisComparison(LoggerInterface $logger): LogAnalysisComparisonDataCompares current log analysis with cached results and returns a LogAnalysisComparisonData containing:
current - LogCountsData with current log counts by levelcached - LogCountsData with previously cached log countsdifferences - LogCountsData showing differences between current and cached (current - cached)logFileName - The log file name used for cachingcachedAt - DateTime string indicating when the cache was created, or null if no cache existedThe results are automatically cached for the next comparison. Cache TTL is configurable.
$comparison = LaraLogsToolkit::getLogAnalysisComparison(Log::channel('daily'));
// Use helper methods
if ($comparison->isNewError()) {
$newErrors = $comparison->getNewErrorCount();
}
// Or access directly
$newErrors = $comparison->differences->error;
$currentErrors = $comparison->current->error;
// Check for any new issues
if ($comparison->hasAnyNewIssues()) {
$totalNewIssues = $comparison->getTotalNewIssuesCount();
}
// Check when the cache was created
if ($comparison->cachedAt) {
echo "Cache created at: {$comparison->cachedAt}\n";
}
LogAnalysisComparisonData Helper Methods:
isNewError(), isNewWarning(), isNewCritical(), isNewAlert(), isNewEmergency() - Check if specific log level has new entrieshasAnyNewIssues() - Check if there are any new issues (errors, warnings, critical, alert, or emergency)getNewErrorCount(), getNewWarningCount(), etc. - Get count of new entries for each level (returns 0 if negative)getTotalNewIssuesCount() - Get total count of all new issuesgetTotalNewCount() - Get total count of all new log entries across all levelsgetCurrentErrorCount(), getCurrentWarningCount() - Get current countsgetCachedErrorCount(), getCachedWarningCount() - Get cached countsgetAllChannelsLogAnalysis(bool $useCache = false): AllChannelsLogAnalysisDataAnalyzes all log channels defined in config/logging.php (excluding default excluded channels) and returns an AllChannelsLogAnalysisData DTO with aggregated results.
Default Excluded Channels: single, daily, null, papertrail, stderr, syslog, errorlog, slack, emergency
Parameters:
$useCache (bool, default: false) - If true, uses getLogAnalysisComparison() instead of getLogAnalysis() for each channel, providing comparison data with cached results.Chainable Configuration Methods:
excludeChannels(array|string $channels): self - Override the default excluded channelsincludeChannels(array|string $channels): self - Include channels by removing them from the excluded list// Basic usage - analyze all channels (excluding defaults)
$analysis = LaraLogsToolkit::getAllChannelsLogAnalysis();
// Get aggregated totals across all channels
$totalErrors = $analysis->getError();
$totalWarnings = $analysis->getWarning();
$total = $analysis->getTotal();
// Get specific channel data
$carriersData = $analysis->getChannel('carriers');
if ($carriersData instanceof LogCountsData) {
$carriersErrors = $carriersData->error;
}
// With caching/comparison enabled
$analysis = LaraLogsToolkit::getAllChannelsLogAnalysis(useCache: true);
// Access comparison data for a specific channel
$comparison = $analysis->getComparisonChannel('carriers');
if ($comparison) {
$newErrors = $comparison->getNewErrorCount();
$hasNewIssues = $comparison->hasAnyNewIssues();
}
// Check if any channels have comparison data
if ($analysis->hasComparisonData()) {
// Handle comparison-specific logic
}
// Customize excluded channels
$analysis = LaraLogsToolkit::excludeChannels(['stack', 'null', 'slack'])
->getAllChannelsLogAnalysis();
// Include a normally excluded channel
$analysis = LaraLogsToolkit::includeChannels('stack')
->getAllChannelsLogAnalysis();
// Chain both methods
$analysis = LaraLogsToolkit::excludeChannels(['carriers', 'api'])
->includeChannels('stack')
->getAllChannelsLogAnalysis(useCache: true);
AllChannelsLogAnalysisData Methods:
getChannel(string $channelName): LogCountsData|LogAnalysisComparisonData|null - Get data for a specific channelgetChannels(): array - Get all channels datagetError(), getInfo(), getWarning(), getEmergency(), getAlert(), getCritical(), getDebug(), getNotice() - Get aggregated totals across all channels for each log levelgetTotal(): int - Get total count across all channels and all log levelsgetComparisonChannel(string $channelName): ?LogAnalysisComparisonData - Get comparison data for a specific channel (returns null if channel doesn't have comparison data)hasComparisonData(): bool - Check if any channels have comparison datatoArray(): array - Convert to array format (includes both individual channels and aggregated totals)fromArray(array $data): self - Static factory method to create from arrayExample with aggregated totals:
$analysis = LaraLogsToolkit::getAllChannelsLogAnalysis();
// Aggregated totals across all channels
$allErrors = $analysis->getError(); // Sum of all errors from all channels
$allWarnings = $analysis->getWarning(); // Sum of all warnings from all channels
$allInfo = $analysis->getInfo(); // Sum of all info logs from all channels
$total = $analysis->getTotal(); // Total of all log levels from all channels
// Individual channel access
foreach ($analysis->getChannels() as $channelName => $channelData) {
if ($channelData instanceof LogCountsData) {
echo "{$channelName}: {$channelData->error} errors\n";
}
}
getLastError(string $channel = 'stack', bool $withStackTrace = false): ?stringRetrieves the last error message from a specific log channel. By default, returns only the error message without the stack trace.
Parameters:
$channel (string, default: 'stack') - The log channel name to check$withStackTrace (bool, default: false) - If true, returns the full error entry including stack traceReturns: string|null - The last error message (or full error with stack trace), or null if no error is found
use Ravols\LaraLogsToolkit\Facades\LaraLogsToolkit;
// Get last error message only (default channel: 'stack')
$error = LaraLogsToolkit::getLastError();
// Get last error from specific channel
$error = LaraLogsToolkit::getLastError('api');
// Get last error with stack trace
$error = LaraLogsToolkit::getLastError('stack', true);
// Get last error with stack trace from specific channel
$error = LaraLogsToolkit::getLastError('api', true);
Example:
$lastError = LaraLogsToolkit::getLastError('daily');
if ($lastError !== null) {
echo "Last error: {$lastError}\n";
} else {
echo "No errors found in daily channel\n";
}
// With stack trace
$fullError = LaraLogsToolkit::getLastError('daily', true);
if ($fullError) {
// Contains full error with stack trace
echo $fullError;
}
getLastRecord(string $channel = 'stack', bool $withStackTrace = false): ?stringRetrieves the last log record from a specific channel, regardless of log level (ERROR, INFO, WARNING, etc.). Useful for getting the most recent log entry of any type.
Parameters:
$channel (string, default: 'stack') - The log channel name to check$withStackTrace (bool, default: false) - If true, returns the full log entry including stack trace (if available)Returns: string|null - The last log record (or full entry with stack trace), or null if no record is found
use Ravols\LaraLogsToolkit\Facades\LaraLogsToolkit;
// Get last record (any log level) - message only
$record = LaraLogsToolkit::getLastRecord();
// Get last record from specific channel
$record = LaraLogsToolkit::getLastRecord('api');
// Get last record with stack trace
$record = LaraLogsToolkit::getLastRecord('stack', true);
// Get last record with stack trace from specific channel
$record = LaraLogsToolkit::getLastRecord('api', true);
Example:
$lastRecord = LaraLogsToolkit::getLastRecord('daily');
if ($lastRecord !== null) {
echo "Last log entry: {$lastRecord}\n";
} else {
echo "No log entries found in daily channel\n";
}
// With stack trace (if available)
$fullRecord = LaraLogsToolkit::getLastRecord('daily', true);
if ($fullRecord) {
// Contains full log entry with stack trace
echo $fullRecord;
}
The package provides convenient helper functions for use in artisan tinker. These functions allow you to quickly access the last error and last record methods without using the facade or dependency injection.
lastError(string $channel = 'stack', bool $withStackTrace = false): ?stringHelper function to get the last error from a specific log channel. This is a convenience wrapper around LaraLogsToolkit::getLastError().
Note: This function is intended for use in artisan tinker only.
Parameters:
$channel (string, default: 'stack') - The log channel name to check$withStackTrace (bool, default: false) - If true, returns the full error entry including stack traceReturns: string|null - The last error message (or full error with stack trace), or null if no error is found
Example in Tinker:
php artisan tinker
>>> lastError()
=> "SQLSTATE[HY000] [2002] Connection refused"
>>> lastError('api')
=> "Route not found: GET /api/users"
>>> lastError('stack', true)
=> "[2025-01-03 10:30:45] local.ERROR: SQLSTATE[HY000] [2002] Connection refused
[stack trace]
#0 /path/to/file.php(123): function()
..."
lastRecord(string $channel = 'stack', bool $withStackTrace = false): ?stringHelper function to get the last log record from a specific channel, regardless of log level. This is a convenience wrapper around LaraLogsToolkit::getLastRecord().
Note: This function is intended for use in artisan tinker only.
Parameters:
$channel (string, default: 'stack') - The log channel name to check$withStackTrace (bool, default: false) - If true, returns the full log entry including stack trace (if available)Returns: string|null - The last log record (or full entry with stack trace), or null if no record is found
Example in Tinker:
php artisan tinker
>>> lastRecord()
=> "User logged in successfully"
>>> lastRecord('api')
=> "API request processed"
>>> lastRecord('stack', true)
=> "[2025-01-03 10:30:45] local.INFO: User logged in successfully
[stack trace]
#0 /path/to/file.php(123): function()
..."
php artisan lara-logs:composer-dump-autoload - Manually log a deployment markerphp artisan lara-logs:check-records [channel] - Check log record count for a channelphp artisan lara-logs:delete-logs - Delete log records from selected channels (supports --channels and --action options)Please see CHANGELOG for more information on what has changed recently.
The MIT License (MIT). Please see License File for more information.