Installation
composer require dragonwize/dw-log-bundle
Configure DBAL Connection
Add a connection in config/packages/dw_log.yaml:
dw_log:
db_connection: default # or your custom connection name
table_name: app_logs
Create Log Table Run the console command:
bin/console dw:log:create-table
Configure Monolog
Update config/packages/monolog.yaml to use the custom handler:
monolog:
handlers:
dw_log:
type: service
id: DwLogBundle\Monolog\DwLogHandler
level: debug # or your preferred level
channels: ["app", "doctrine"] # channels to log
First Log Test Trigger a log entry (e.g., via a route or CLI):
$this->addLog('test', 'This is a test log message', ['context' => 'key' => 'value']);
Verify logs appear in the /admin/logs route.
Log a Request In your controller:
use Psr\Log\LoggerInterface;
public function index(LoggerInterface $logger)
{
$logger->info('User accessed route', ['user_id' => 123, 'route' => 'home']);
return response()->json(['status' => 'success']);
}
View Logs
Navigate to /admin/logs and search for user_id:123 to inspect the request.
Use arrays for context to maintain consistency:
$logger->debug('Processing order', [
'order_id' => $order->id,
'status' => $order->status,
'user' => $user->email,
]);
Configure Monolog channels in monolog.yaml to separate logs (e.g., app, security, cli):
handlers:
dw_log_app:
type: service
id: DwLogBundle\Monolog\DwLogHandler
channels: ["app"]
dw_log_security:
type: service
id: DwLogBundle\Monolog\DwLogHandler
channels: ["security"]
Use the DwLogBundle\Repository\LogRepository service:
$logs = $logRepository->findBy([
'level' => 'ERROR',
'message' => '%timeout%',
'context' => json_encode(['exception' => '%SQLSTATE%']),
]);
Extend the bundle’s log levels by modifying the DwLogBundle\Monolog\DwLogHandler or adding a custom level to Monolog:
monolog:
handlers:
dw_log:
level: custom_level # Add to Monolog's levels in config
Service Container Binding
Bind the Monolog handler to Laravel’s container in config/services.php:
$app->bind('DwLogBundle\Monolog\DwLogHandler', function ($app) {
return new \DwLogBundle\Monolog\DwLogHandler(
$app['dw_log.connection'],
$app['monolog.logger']
);
});
Laravel Log Channel
Create a custom Monolog channel in config/logging.php:
'channels' => [
'dw_log' => [
'driver' => 'monolog',
'handler' => 'DwLogBundle\Monolog\DwLogHandler',
'with' => [
'channels' => ['app', 'queue'],
],
],
],
Queue Workers Log queue job processing:
public function handle(Job $job, LoggerInterface $logger)
{
$logger->info('Job started', ['job_id' => $job->id, 'queue' => $job->queue]);
// Process job...
$logger->info('Job completed', ['job_id' => $job->id, 'duration' => '100ms']);
}
DwLogBundle\Monolog\DwLogHandler to buffer logs and flush periodically.message and context columns are indexed in the database for fast searches:
ALTER TABLE app_logs ADD INDEX idx_message_context (message, context);
Database Schema Mismatch
dw:log:create-table after modifying the bundle’s schema (e.g., adding columns) may not update the table.bin/console dw:log:drop-table
bin/console dw:log:create-table
Context Serialization
context column stores JSON, but malformed data (e.g., circular references) may break logging.$context = json_decode(json_encode($context), true);
$logger->info('Event', $context);
Monolog Handler Conflicts
DwLogHandler instances may cause duplicate logs or conflicts.monolog.yaml.Tailwind CSS Conflicts
/* Disable Tailwind in the log UI */
.dw-log-ui *[class*="tw-"] { all: unset; }
Log Handler Not Writing
bin/console debug:config monolog
id matches the service definition.Empty Log Table
dw_log.yaml:
dw_log:
db_connection: default # Must match your Doctrine connection
$connection = $this->get('dw_log.connection');
var_dump($connection->getWrappedConnection()->getDatabasePlatform());
Search Not Returning Results
SELECT * FROM app_logs WHERE message LIKE '%test%';
Custom Log Fields
Extend the schema by overriding the DwLogBundle\Doctrine\DbalSchemaManager:
// src/DwLogBundle/Doctrine/CustomSchemaManager.php
class CustomSchemaManager extends DbalSchemaManager
{
public function getSchema(): Schema
{
$schema = parent::getSchema();
$table = $schema->getTable('app_logs');
$table->addColumn('custom_field', 'string', ['notnull' => false]);
return $schema;
}
}
Bind the service in config/services.yaml:
services:
DwLogBundle\Doctrine\DbalSchemaManager:
class: App\DwLogBundle\Doctrine\CustomSchemaManager
Webhook Notifications Add a post-log hook to send logs to an external service:
// src/EventListener/LogWebhookListener.php
class LogWebhookListener implements ContainerAwareInterface
{
public function onLogEntry(PostLogEntryEvent $event)
{
$log = $event->getLogEntry();
// Send to webhook...
}
}
Register the listener in config/services.yaml:
services:
App\EventListener\LogWebhookListener:
tags:
- { name: kernel.event_listener, event: dw_log.post_entry, method: onLogEntry }
Log Retention Policy Implement a cron job to purge old logs using DBAL:
$connection = $this->get('dw_log.connection');
$connection->executeStatement(
'DELETE FROM app_logs WHERE created_at < ?',
[new \DateTime('-30 days')]
);
How can I help you explore Laravel packages today?