Code Monkey home page Code Monkey logo

laravel-log-to-db's Introduction

Laravel Log-to-DB

GitHub PHP from Packagist GitHub release GitHub tag Codecov CodeFactor CircleCI

Hi, this is a custom Laravel 5.6+ Log channel handler that can store log events to SQL or MongoDB databases. Uses Laravel native logging functionality trough Monolog.

⚠️ For Laravel version 10 and beyond, please use version 4 or later of this package.
For Laravel version 5.6 to 9, please use version 3.x.x.

Installation

Use the composer require or add to composer.json.

composer require danielme85/laravel-log-to-db

If you are using SQL database server to store log events you can use the migration included. The MongoDB driver does not require the migration. Copy the migration file for log the database table to your app (you can also do any changes you want or manually copy this file your database/migrations folder).

php artisan vendor:publish --tag=migrations --provider="danielme85\LaravelLogToDB\ServiceProvider"

Run the Laravel migration artisan command.

php artisan migrate

For optional MongoDB support you need to install jenseegers/mongodb addon to Laravel

#Optional mongodb support, not required!

composer require jenssegers/mongodb

Configuration

Starting with Laravel 5.6 and later, you will have a new config file: "config/logging.php". You will need to add an array under 'channels' for Log-to-DB here like so:

'database' => [
    'driver' => 'custom',
    'via' => danielme85\LaravelLogToDB\LogToDbHandler::class
    ...
    ],

These are the minimum required logging.php config settings to get started. Please note that the array index 'database' can be whatever string you like as long as it is unique to this logging config. You can also give the logging channel a name that later is referenced in a column in the DB table, this way you can have multiple logging-to-db channels.

'channels' => [
    'stack' => [
        'name' => 'Log Stack',
        'driver' => 'stack',
        'channels' => ['database', 'other-database', 'file'],
    ],
    'database' => [
        'driver' => 'custom',
        'via' => danielme85\LaravelLogToDB\LogToDbHandler::class,
        'name' => 'Basic DB Logging'
    ],
    'other-database' => [
        'driver' => 'custom',
        'via' => danielme85\LaravelLogToDB\LogToDbHandler::class,
        //'model' => App\Model\Log::class, //Your own optional custom model
        'level' => env('APP_LOG_LEVEL', 'debug'),
        'name' => 'My DB Log with a bunch more settings',
        'connection' => 'default',
        'collection' => 'log',
        'detailed' => true,
        'queue' => false,
        'queue_name' => '',
        'queue_connection' => '',
        'max_records' => false,
        'max_hours' => false,
        'processors' => [
              //Monolog\Processor\HostnameProcessor::class
              // ..
         ]
    ],
    ...
]
  • driver = Required to trigger the log driver.
  • via = The Log handler class.
  • level = The minimum error level to trigger this Log Channel.
  • name = The channel name that will be stored with the Log event. Please note that if you use the stack driver the name value in the stack array is used.
  • connection = The DB connection from config/database.php to use (default: 'default').
  • collection = The DB table or collection name. (Default: log).
  • detailed = Store detailed log on Exceptions like stack-trace (default: true).
  • processors = Array of additional processors. These will add additional info into the 'extra' field in the logged data. More information about processors

More info about some of these options: https://laravel.com/docs/9.x/logging#customizing-monolog-for-channels

There are some default settings and more information about configuring the logger in the 'logtodb.php' config file. This could be copied to your project if you would like edit it with the vendor publish command.

php artisan vendor:publish --tag=config --provider="danielme85\LaravelLogToDB\ServiceProvider"

You can also change these settings in your env file.

LOG_DB_CONNECTION='default'
LOG_DB_DETAILED=false
LOG_DB_MAX=100
LOG_DB_QUEUE=false
LOG_DB_QUEUE_NAME='logToDBQueue'
LOG_DB_QUEUE_CONNECTION='default'
LOG_DB_MAX_COUNT=false
LOG_DB_MAX_HOURS=false
LOG_DB_DATETIME_FORMAT='Y-m-d H:i:s:ms'

PLEASE NOTE: Starting with v2.2.0, the datetime column will be saved as a string in the format given in 'datetime_format' in logtodb.php config file, or the LOG_DB_DATETIME_FORMAT value in your .env file.

Config priority order

There are three places you can change different options when using log-to-db:

  1. The config file: config/logtodb.php (after doing vendor:publish).
  2. Your .env file will override settings in the logtodb.php config file.
  3. The Laravel logging config file: config/logging.php. You need to add a custom array here as mentioned above, in this same array you can specify/override config settings specifically for that log channel.

Config values set in point 1 & 2 would work as default for all new log channels you add in the "channels" array for the Laravel logging configuration (config/logging.php).

Log Worker Queue

It might be a good idea to save the log events with a Queue Worker. This way your server does not have to wait for the save process to finish. You would have to configure the Laravel Queue settings and run the Queue listener. https://laravel.com/docs/6.x/queues#running-the-queue-worker

The queue can be enabled/disabled in any of the following places:

  • LOG_DB_QUEUE = true | in .env
  • queue_db_saves => true | in config/logtodb.php
  • queue => true | in the log channel config array -> config/logging.php

Usage

Since this is a custom log channel for Laravel, all "standard" ways of generating log events etc should work with the Laravel Log Facade. See https://laravel.com/docs/6.x/logging for more information.

Log::debug("This is an test DEBUG log event");
Log::info("This is an test INFO log event");
Log::notice("This is an test NOTICE log event");
Log::warning("This is an test WARNING log event");
Log::error("This is an test ERROR log event");
Log::critical("This is an test CRITICAL log event");
Log::alert("This is an test ALERT log event");
Log::emergency("This is an test EMERGENCY log event");

You can also log to specific log channels: Log::channel('database')debug("This is an test DEBUG log event");

Fetching Logs

The logging by this channel is done trough the Eloquent Model builder. LogToDB::model($channel, $connection, $collection); You can skip all function variables and the default settings from the config/logtodb.php will be used.

$model = LogToDB::model();
$model->get(); //All logs for default channel/connection

Some more examples of getting logs

$logs = LogToDB::model()->get();
$logs = LogToDB::model()->where('level_name', '=', 'INFO')->get();

When getting logs for specific channel or DB connection and collection you can either use the channel name matching config/logging.php or connection name from config/databases.php. You can also specify collection/table name if needed as the third function variable when fetching the model.

$logsFromDefault = LogDB::model()->get(); //Get the logs from the default log channel and default connection.
$logsFromChannel = LogDB::model('database')->get(); //Get logs from the 'database' log channel.
$logsFromChannel = LogDB::model('customname')->get(); //Get logs from the 'customname' log channel.
$logsFromMysql   = LogToDB::model(null, 'mysql')->get(); //Get all logs from the mysql connection (from Laravel database config)
$logsFromMongoDB = LogToDB::model(null, 'mongodb')->get(); //Get all logs from the mongodb connection (from Laravel database config)
$logsFromMysqlTable  = LogToDB::model(null, 'mysql', 'table')->get(); //Get all logs from the mysql table: 'table'

Custom Eloquent Model

Since Laravel is supposed to use static defined collection/table names, it might be better to use your own model in your app for a more solid approach. You can use your own eloquent model by referencing it in the config, then adding the trait: "LogToDbCreateObject"

SQL
namespace App\Models;

use danielme85\LaravelLogToDB\Models\LogToDbCreateObject;
use Illuminate\Database\Eloquent\Model;

class CustomLog extends Model
{
    use LogToDbCreateObject;

    protected $table = 'log';
    protected $connection = 'mysql';
    
}
MongoDB
namespace App\Models;
use danielme85\LaravelLogToDB\Models\LogToDbCreateObject;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;

class CustomLogMongo extends Eloquent
{
    use LogToDbCreateObject;

    protected $collection = 'log';
    protected $connection = 'mongodb';

}

LOG_DB_MODEL='App\Models\CustomLog'

WARNING: Fetching the model trough the dynamic Eloquent model (default behavior) have some side-effects as tables and connections are declared dynamically instead of assigned properties in the model class. Certain functions are broken like LogToDB::model->all(), while LogToDB::model->where()->get() will work as normal. Using your own models avoids these problems.

Model Closures and Observers

You can either add closures on your custom application model mentioned above, or add a model observer for the default LogToDb models.
Create a observer:

<?php
namespace App\Observers;

use danielme85\LaravelLogToDB\Models\DBLog;

class LogObserver
{
    public function created(DBLog $log)
    {
        //
    }
}

Then add to your AppServiceProvider (or another provider that calls the app boot function).

   namespace App\Providers;
   
   use App\Observers\LogObserver;
   use danielme85\LaravelLogToDB\LogToDB;
   use Illuminate\Support\ServiceProvider;
   
   class AppServiceProvider extends ServiceProvider
   {
       public function boot()
       {
           LogToDB::model()->observe(LogObserver::class);
       }
   }

Adding tables/expanding collections

The Log handler for SQL expects the following schema:

Schema::create('log', function (Blueprint $table) {
      $table->increments('id');
      $table->text('message')->nullable();
      $table->string('channel')->nullable();
      $table->integer('level')->default(0);
      $table->string('level_name', 20);
      $table->integer('unix_time');
      $table->text('datetime')->nullable();
      $table->longText('context')->nullable();
      $table->text('extra')->nullable();
      $table->timestamps();
 });

This is the migration that ships with this plugin. You can add as many tables as you want, and reference them in the 'collection' config value. Collection = table, I used the term collection as it works for both SQL/noSQL. No migrations needed for MongoDB.

No indexes are added per default, so if you fetch a lot of log results based on specific time ranges or types: it might be a good idea to add some indexes.

Log Cleanup

There are config values that you can set to specify the max number of log records to keep, or the max record age in hours.

  • logging.php channel array -> (max_records, max_hours).
  • .env file -> (LOG_DB_MAX_COUNT, LOG_DB_MAX_HOURS).

These option is set to false per default, these have to be set to desired integers before you can run the "log:delete" artisan command.

php artisan log:delete

This command will delete records based on settings described above. Add this command to your Console/kernel.php, or run manually in cron etc to enable automatic cleanup.

Manual Cleanup

There is a helper function to remove the oldest log events and keep a specified number

LogToDB::removeOldestIfMoreThan(100);

Or based on date (most be valid date/datetime supported by strtotime()) http://php.net/manual/en/function.strtotime.php

LogToDB::model()->removeOlderThan('2019-01-01');
LogToDB::model()->removeOlderThan('2019-01-01 23:00:00');

Processors

Monolog ships with a set of processors, these will generate additional data and populate the 'extra' field. I've also added a couple of example processors in this pacage under src/Processors. To enable processors you can add them to the log config array:

'database' => [
    'driver' => 'custom',
    'via' => danielme85\LaravelLogToDB\LogToDbHandler::class
    ...
    'processors' => [
        \danielme85\LaravelLogToDB\Processors\PhpVersionProcessor::class,
        Monolog\Processor\HostnameProcessor::class,
    ]

You could also create your own custom processor, make sure they implement Monolog\Processor\ProcessorInterface.

Example of custom processor
<?php

namespace App\CustomProcessors;

use Monolog\Processor\ProcessorInterface;

class PhpVersionProcessor implements ProcessorInterface {
     /**
     * @return array The processed record
     */
     public function __invoke(array $record) {
         $record['extra']['php_version'] = phpversion();
         
         return $record;
     }
}

More logging.php config examples

'default' => env('LOG_CHANNEL', 'stack'),

'channels' => [
    'stack' => [
        'driver' => 'stack',
        'channels' => ['database', 'mongodb', 'single'],
    ],
    
    'database' => [
        'driver' => 'custom',
        'via' => danielme85\LaravelLogToDB\LogToDbHandler::class,
        'level' => env('APP_LOG_LEVEL', 'debug'),
        'connection' => 'default',
        'collection' => 'log'
        'detailed' => true,
        'queue' => true
        'queue_name' => 'logQueue'
        'queue_connection' => 'redis',
        'max_records' => 1000,
        'max_hours' => 24,
    ],
    
    'mongodb' => [
        'driver' => 'custom',
        'via' => danielme85\LaravelLogToDB\LogToDbHandler::class,
        'level' => 'debug',
        'connection' => 'mongodb',
        'collection' => 'log',
        'detailed' => true,
        'queue' => true
        'queue_name' => 'logQueue'
        'queue_connection' => 'redis'
    ],
    
    'limited' => [
        'driver' => 'custom',
        'via' => danielme85\LaravelLogToDB\LogToDbHandler::class,
        'level' => 'warning',
        'detailed' => false,
        'max_rows' => 10,
        'name' => 'limited',
    ]
    
    'single' => [
        'driver' => 'single',
        'path' => storage_path('logs/laravel.log'),
        'level' => env('APP_LOG_LEVEL', 'debug'),
    ],
    //....
]

Lumen Installation

  • Create a config folder in your projects root directory (if you don't already have one), then add a logging.php config file there. Use the Laravel logging.php config file as an example/starting point. You can also add all the other "missing" config files from the Laravel config folder to your Lumen project.

  • To use these config files you have to load them in your applications bootstrap/app.php file (or add your own service provider file and load it in that same file).

You also need to make sure that all the needed basic config values for logtodb is set by either:

  • Copy over logtodb.php from the config folder of this addon,
  • or just add all your log-to-db options in your applications config/logging.php file (probably easiest). Just follow the configuration example above under the configuration section.

Since we are using Lumen we need to specify the config and service providers in the "bootstrap/app.php" file.

/*
|--------------------------------------------------------------------------
| Register Config Files
|--------------------------------------------------------------------------
|
| Now we will register the "app" configuration file. If the file exists in
| your configuration directory it will be loaded; otherwise, we'll load
| the default version. You may register other files below as needed.
|
*/

$app->configure('app');
//$app->configure('logtodb'); //if you copied over and want to use the base config from logtodb.
$app->configure('logging');

Next step is to register the service provider, either in bootstrap/app.php or in app/Provider/AppServiceProvider.

/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
|
| Here we will register all of the application's service providers which
| are used to bind services into the container. Service providers are
| totally optional, so you are not required to uncomment this line.
|
*/

// $app->register(App\Providers\AppServiceProvider::class);
// $app->register(App\Providers\AuthServiceProvider::class);
// $app->register(App\Providers\EventServiceProvider::class);
$app->register(\danielme85\LaravelLogToDB\ServiceProvider::class);

After adding the service provider you should be able to run the database migration in Lumen with:

php artisan migrate --path=vendor/danielme85/laravel-log-to-db/src/migrations/2018_08_11_003343_create_log_table.php

Please note that you need a working db connection in Lumen at this point.

And then maybe it works... ¯_(ツ)_/¯

Using worker queue to write log to db with Lumen

You would need to set up a queue driver in Lumen before you can use the queue (default is: QUEUE_CONNECTION=sync, which is basically no queue). More info about the queues in Lumen doc (they are mostly the same as Laravel). I would recommend the Redis queue driver but database should also work.

How to make Redis work in Lumen (in general).

install per command

 composer require predis/predis
 composer require illuminate/redis

OR add to composer.json

...
  "require": {
        "predis/predis": "~1.0",
        "illuminate/redis": "5.0.*",
...

Or install other alternatives to predis.

Add service provider and enable eloquent in your bootstrap/app.php file (Eloquent only needed if you use the model/model helper class to fetch new log event);


$app->withFacades();
$app->withEloquent();

$app->register(Illuminate\Redis\RedisServiceProvider::class);
if (!class_exists('Redis')) {
    class_alias('Illuminate\Support\Facades\Redis', 'Redis');
}

Now you can set your .env values to use Redis for the queue and cache if you so please:

REDIS_CLIENT=predis
QUEUE_CONNECTION=redis
CACHE_DRIVER=redis

Local Testing With Docker

There is a helper bash script called 'runLocalTestInDocker.sh', that runs the following docker commands:

docker-compose up -d mariadb mongo &&
docker-compose up php7 &&
docker-compose up php8 &&
docker-compose down

To run Docker is required, give execute rights to the script and run:

chmod +x runLocalTestInDocker.sh && 
./runLocalTestInDocker.sh

Development supported by:

laravel-log-to-db's People

Contributors

danielme85 avatar elvendor avatar jocafamaka avatar joostdebruijn avatar manriel avatar martijngastkemper avatar pravnyadv avatar rogervila avatar saeednavaro avatar saulens22 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

laravel-log-to-db's Issues

Duplicate values ​​in the log

Hello. Please tell me for what purpose intended field extra?
I have all the records contain only one text "{"file":"/home/vagrant/ay-tech/vendor/laravel/framework/src/Illuminate/Log/Logger.php","line":176,"class":"Illuminate\Log\Logger","function":"writeLog"}"
Maybe I'm doing something wrong?

I use Laravel v6

Url issue

how to get the URL on which issue occurred

Compatibility with Laravel 10.x and Monolog 3.x

This package is no longer compatible with Laravel 10.x, which is using Monolog 3.x, causing errors like this:

Declaration of danielme85\LaravelLogToDB\LogToDbCustomLoggingHandler::write(array $record): void must be compatible with Monolog\Handler\AbstractProcessingHandler::write(Monolog\LogRecord $record): void

The version constraint "illuminate/support": ">=5.6" is suggesting that it is actually compatible, which allows installing this package with Laravel 10.x.

Not Logging to database with ERROR

LOG:
[2019-10-11 09:25:44] debug.DEBUG: This is an test DEBUG log event [2019-10-11 09:25:45] debug.ERROR: Argument 1 passed to danielme85\LaravelLogToDB\Models\DBLog::setDatetimeAttribute() must be an instance of Monolog\DateTimeImmutable, instance of DateTime given, called in \vendor\laravel\framework\src\Illuminate\Database\Eloquent\Concerns\HasAttributes.php on line 615 {"userId":9,"exception":"[object] (Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Argument 1 passed to danielme85\\LaravelLogToDB\\Models\\DBLog::setDatetimeAttribute() must be an instance of Monolog\\DateTimeImmutable, instance of DateTime given, called in \\vendor\\laravel\\framework\\src\\Illuminate\\Database\\Eloquent\\Concerns\\HasAttributes.php on line 615 at \\vendor\\danielme85\\laravel-log-to-db\\src\\Models\\LogToDbCreateObject.php:115)

I just followed the main tutorial and did this:

Log::debug("This is an test DEBUG log event");

All other channels work fine but database one makes the aplication throw 500 Error

Slight doc fix

In Laravel 5.8, to get a query-able model back from the ext you have to do:

        $logs = LogToDB::model(
            null,
            'mongodb',
            'log'
        )->newModelQuery();

Else even though where() does not throw an error, it does not seem to do anything either.

Does not work correctly with Laravel Octane

Laravel Log to DB: v3.0.1
Laravel Octane: v0.2.0 (using swoole)
Laravel Framework: v8.37.0

Error:

exception: "danielme85\\LaravelLogToDB\\Models\\DBLogException"
file: "/var/www/html/vendor/danielme85/laravel-log-to-db/src/LogToDbCustomLoggingHandler.php"
line: 70
message: "Target class [config] does not exist."
trace: [{file: "/var/www/html/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php",…},…]
0: {file: "/var/www/html/vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php",…}
1: {file: "/var/www/html/vendor/monolog/monolog/src/Monolog/Logger.php", line: 317, function: "handle",…}
2: {file: "/var/www/html/vendor/monolog/monolog/src/Monolog/Logger.php", line: 539, function: "addRecord",…}
3: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Log/Logger.php", line: 174,…}
4: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Log/Logger.php", line: 87,…}
5: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Log/LogManager.php", line: 555,…}
6: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php",…}
7: {file: "/var/www/html/app/Exceptions/Handler.php", line: 39, function: "report",…}
8: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php", line: 49,…}
9: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", line: 172,…}
10: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php",…}
11: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Session/Middleware/StartSession.php",…}
12: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", line: 167,…}
13: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php",…}
14: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", line: 167,…}
15: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", line: 103,…}
16: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php", line: 697,…}
17: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php", line: 672,…}
18: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php", line: 636,…}
19: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Routing/Router.php", line: 625,…}
20: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php", line: 166,…}
21: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", line: 128,…}
22: {file: "/var/www/html/vendor/barryvdh/laravel-debugbar/src/Middleware/InjectDebugbar.php", line: 60,…}
23: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", line: 167,…}
24: {,…}
25: {,…}
26: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", line: 167,…}
27: {,…}
28: {,…}
29: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", line: 167,…}
30: {,…}
31: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", line: 167,…}
32: {,…}
33: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", line: 167,…}
34: {file: "/var/www/html/vendor/fideloper/proxy/src/TrustProxies.php", line: 57,…}
35: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", line: 167,…}
36: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php", line: 103,…}
37: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php", line: 141,…}
38: {file: "/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php", line: 110,…}
39: {file: "/var/www/html/vendor/laravel/octane/src/ApplicationGateway.php", line: 36, function: "handle",…}
40: {file: "/var/www/html/vendor/laravel/octane/src/Worker.php", line: 92, function: "handle",…}
41: {file: "/var/www/html/vendor/laravel/octane/bin/swoole-server", line: 119, function: "handle",…}
42: {function: "{closure}"}
43: {file: "/var/www/html/vendor/laravel/octane/bin/swoole-server", line: 169, function: "start",…}

My guess is that it has to do something with how config file is loaded - it is different in Octane https://github.com/laravel/octane#dependency-injection--octane

Log Cleaner does not read collection setting

Hello @danielme85

I observed a bug. In my logging configuration, I set the collection instance to be something different from the default log. However when I try to prune using the log:delete command, it keeps failing with an error.

   Illuminate\Database\QueryException 
  SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.log' doesn't exist (SQL: select count(*) as aggregate from `log`)

I tried to look in the source and noticed that in LogCleanerUpper.php, both calls to the LogToDb::model() method seem to be outdated.

The LogToDb model has a signature of
public static function model(string $channel = null, string $connection = 'default', string $collection = null), but both calls
are done this way LogToDB::model($connection, $collection).

This makes the collection perpetually null and therefore falls back to default.

Doing this fixes the error for me LogToDB::model(null, $connection, $collection) but this may not be what you'd prefer.

Kindly look into it and thanks for the great work.

Laravel 6. Serialization of 'Closure' is not allowed

Hello. Log entry does not work if there are errors in the view. This leads to an error:

Serialization of 'Closure' is not allowed {"userId":1,"exception":"[object] (danielme85\LaravelLogToDB\Models\DBLogException(code: 0): Serialization of 'Closure' is not allowed at /home/.../danielme85/laravel-log-to-db/src/LogToDbCustomLoggingHandler.php:70)

Missing commas on example of config

In your example of config logging.channels.database you are missing commas on entries: queue, queue_name, queue_connection.

'database' => [
    'driver' => 'custom',
    'via' => danielme85\LaravelLogToDB\LogToDbHandler::class,
    'level' => env('APP_LOG_LEVEL', 'debug'),
    'name' => 'My DB Log',
    'connection' => 'default',
    'collection' => 'log',
    'detailed' => true,
    'queue' => false
    'queue_name' => ''
    'queue_connection' => ''
]

Add Lumen support

I'm gonna try to add some better lumen support, this addon has never been properly tested with Lumen and would probably need some tweaks to work and make installation easier.

  • Test practical use in Lumen.
  • Make tweaks as needed.
  • Add Lumen install instructions to readme.

Should make it easier and avoid confusion as: #23

"Cleanup" functions not working when using mongoDB

Functions: 'removeOlderThan' and 'removeOldestIfMoreThan' does not work as intended when using mongodb. Currently functionality relies on 'id' being present in the DB, since it don't use migration to create mongodb collection it's '_id' per default.

Change 'then' to 'than'

There are two methods with typo in them: 'removeOldestIfMoreThen' and 'removeOlderThen'. 'Then' should be replaced by 'Than' to be correct English sentence. Or, at least, this issue should stay here to inform others about this potential issue in otherwise great package.

ModelNotFoundException when using queue

Hello,

I am getting this particular message when putting the log into the queue. I followed the installation guide to a T - am I missing something? Below is the stack trace. If i don't put it into the queue everything works.

Illuminate\Database\Eloquent\ModelNotFoundException: No query results for model [danielme85\LaravelLogToDB\Models\DBLog]. in /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:452 Stack trace: #0 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Queue/SerializesAndRestoresModelIdentifiers.php(85): Illuminate\Database\Eloquent\Builder->firstOrFail() #1 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Queue/SerializesAndRestoresModelIdentifiers.php(55): danielme85\LaravelLogToDB\Jobs\SaveNewLogEvent->restoreModel(Object(Illuminate\Contracts\Database\ModelIdentifier)) #2 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Queue/SerializesModels.php(45): danielme85\LaravelLogToDB\Jobs\SaveNewLogEvent->getRestoredPropertyValue(Object(Illuminate\Contracts\Database\ModelIdentifier)) #3 [internal function]: danielme85\LaravelLogToDB\Jobs\SaveNewLogEvent->__wakeup() #4 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Queue/CallQueuedHandler.php(42): unserialize('O:46:"danielme8...') #5 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Queue/Jobs/Job.php(83): Illuminate\Queue\CallQueuedHandler->call(Object(Illuminate\Queue\Jobs\RedisJob), Array) #6 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(327): Illuminate\Queue\Jobs\Job->fire() #7 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(277): Illuminate\Queue\Worker->process('redis', Object(Illuminate\Queue\Jobs\RedisJob), Object(Illuminate\Queue\WorkerOptions)) #8 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Queue/Worker.php(118): Illuminate\Queue\Worker->runJob(Object(Illuminate\Queue\Jobs\RedisJob), 'redis', Object(Illuminate\Queue\WorkerOptions)) #9 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(102): Illuminate\Queue\Worker->daemon('redis', 'default', Object(Illuminate\Queue\WorkerOptions)) #10 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Queue/Console/WorkCommand.php(86): Illuminate\Queue\Console\WorkCommand->runWorker('redis', 'default') #11 [internal function]: Illuminate\Queue\Console\WorkCommand->handle() #12 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(29): call_user_func_array(Array, Array) #13 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(87): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}() #14 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(31): Illuminate\Container\BoundMethod::callBoundMethod(Object(Illuminate\Foundation\Application), Array, Object(Closure)) #15 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Container/Container.php(572): Illuminate\Container\BoundMethod::call(Object(Illuminate\Foundation\Application), Array, Array, NULL) #16 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Console/Command.php(183): Illuminate\Container\Container->call(Array) #17 /home/vagrant/b2b/vendor/symfony/console/Command/Command.php(255): Illuminate\Console\Command->execute(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle)) #18 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Console/Command.php(170): Symfony\Component\Console\Command\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Illuminate\Console\OutputStyle)) #19 /home/vagrant/b2b/vendor/symfony/console/Application.php(901): Illuminate\Console\Command->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #20 /home/vagrant/b2b/vendor/symfony/console/Application.php(262): Symfony\Component\Console\Application->doRunCommand(Object(Illuminate\Queue\Console\WorkCommand), Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #21 /home/vagrant/b2b/vendor/symfony/console/Application.php(145): Symfony\Component\Console\Application->doRun(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #22 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Console/Application.php(89): Symfony\Component\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #23 /home/vagrant/b2b/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php(122): Illuminate\Console\Application->run(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #24 /home/vagrant/b2b/artisan(37): Illuminate\Foundation\Console\Kernel->handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput)) #25 {main}

Release for Laravel 11

Hi Daniel, first of all, great work with this package - thanks for that!
Is there a chance to get a release to packagist with the changes you applied a couple of weeks ago to support Laravel 11? By now, the package prevents updating to the latest and greatest. That would be awesome! 🙂

\Log::error not work

image

image

image

it write to file, but not write to database

database log is system error, \Log::error("something") not work

Array to string conversion on error logging

Good day and great package. I've been using this package for a while now and it's been fabulous.

I ran into a bug and can't seem to figure out what is wrong. I am trying to log validation errors to the database. I have an ErrLog class to handle that.

public function report() { ErrLog::logValidationErrors($this->validator, $this->validation_class); }

And in ErrLog I have this

static function logValidationErrors(Validator $validator, FormRequest $validation_class) { if (DB::transactionLevel() > 0) { Db::rollBack(); } Log::error('hello', ['id' => 1]); // Log::error(get_class($validation_class) . ' validation failed.', ['data' => $validator->getData(), 'errors' => $validator->errors()->all(), get_class($validation_class) . ' validation failed.', 'context' => '']); }
The bug is this: As long as I have an array in the context parameter I get an Array to String conversion error.

If I remove the context entirely, it works, but if I supply any other parameter to context, the exception triggers a required array for parameter 2 error.

My composer file has and I have run composer update a couple of times over the past 2 days.

"danielme85/laravel-log-to-db": "^2.3", "laravel/framework": "^7.0", "laravel/tinker": "^2.0", "laravel/ui": "^2.0",

What could be wrong?

The error information is

`
danielme85\LaravelLogToDB\Models\DBLogException
Array to string conversion

vendor/danielme85/laravel-log-to-db/src/LogToDbCustomLoggingHandler.php:73

protected function write(array $record): void

{

if (!empty($record)) {

  if (

    !empty($record['context']['exception']) &&

    get_class($record['context']['exception']) === DBLogException::class

  ) {

    //Do nothing if empty log record or an error Exception from itself.

  } else {

    try {

      $log = new LogToDB($this->config);

      $log->newFromMonolog($record);

    } catch (DBLogException $e) {

      //do nothing if exception of self

    } catch (\Exception $e) {

      //convert any runtime Exception while logging to a special class so we can avoid our own

      //exceptions for 99% less infinite loops!

      throw new DBLogException($e->getMessage()); // This is line 73

    }

  }

}

`

Here is a link to the flare error if necessary.

https://flareapp.io/share/J7oDNG58

Thanks again for a wonderful package

Error on Lumen 9.1.2 and PHP 8.1

Lumen v9.1.2
PHP v8.1

Hi there, I am getting the following error when trying to register the service provider in app.php
So after adding: $app->register(\danielme85\LaravelLogToDB\ServiceProvider::class); to app.php here is the eror that I am getting:

www-data@c2bfa1bae2d0:~/html$ vendor/bin/phpunit 
PHPUnit 9.5.25 #StandWithUkraine

.PHP Fatal error:  Cannot redeclare danielme85\LaravelLogToDB\config_path() (previously declared in /app/vendor/danielme85/laravel-log-to-db/src/ServiceProvider.php:31) in /app/vendor/danielme85/laravel-log-to-db/src/ServiceProvider.php on line 31
PHP Stack trace:
PHP   1. {main}() /app/vendor/bin/phpunit:0
PHP   2. include() /app/vendor/bin/phpunit:123
PHP   3. PHPUnit\TextUI\Command::main($exit = *uninitialized*) /app/vendor/phpunit/phpunit/phpunit:98
PHP   4. PHPUnit\TextUI\Command->run($argv = [0 => 'vendor/bin/phpunit'], $exit = TRUE) /app/vendor/phpunit/phpunit/src/TextUI/Command.php:97

If queue or database is unavailable, emergency logging should be used

When using this log channel with queueing and the queue is unavailable (e.g. Redis is not running or the database is unavailable), I would expect that errors occuring at that moment will be logged to the emergency channel. However, I don't see those errors logged anywhere. Maybe it's a configuration thing, however - in that case it would be nice to add something about it in the documentation.

Use database loging as optional?

Hello,

Thank you for the package. I'm not sure, where to ask, so i will try to do it here?

I want to log data to database only on specific channels. Is it possible?

I have tried:

\Log::channel('facebook')->debug('Debuging data:'.print_r($postData, true));

And my logging.php looks like this:

// Facebook 'facebook' => [ 'driver' => 'database', 'level' => 'debug', ],

But it doesn't work with database, it works only with default laravel logger. Probably i missed something?

Thank you.

IntrospectionProcessor __invoke Doesn't Hit With the Stack Logging Channel

Hello,

First off, thank you for this awesome package - it is saving me a lot of work. I am having to customize it to our needs, but it works really well to begin with.

I have stumbled across a problem, and this is tested on a fresh install to assure that it is not my mistake.

The problem is that when you turn on the 'stack' channel for logging, the IntrospectionProcessor __invoke never gets hit, causing all of the logs to exclude the IntrospectionProcessor (file, class, etc..).

It seems that it tries to hit the local channels, before the database channel. After that, it uses the formatting for the local channel instead of the formatting for the DB logger. Not sure if this could be overridden - if that's the case.

Am I missing something here?

Internal migration

Package have internal migration included.

It is hard registered inside the Serivce Provider and have own timestamp: 2018_08_11_003343_create_log_table
This leads to behavior that breaks normal flow of artisan migrate command in case the log table migration already exists with modified structure or should be created by migration leaded after that.
For example of modification: if the table needs to be separated to some kind of partitions, but it required to be exists before some previous migrations by the current migration's timestamp.

Current behavior force to do the manual per-file migration to avoid this problem.

I see several ways to fix this behavior:

  1. Simplest solution: wrap migration by if (Schema::hasTable(...) { ... }. That is easiest but not the better way, 'cause it hides the migration from a dev and imposes some restrictions.

  2. Better solution:

  • 2.1. Remove the registration of the migration from the Service Provider

  • 2.2. Add another one directive like directive with config to publishes a copy of the migration to common migrations directory on the normal laravel structire to allow modify it by dev's needs.

  • 2.3. Rename migration to give it inert timestamp 0000_00_00_000000_create_log_table like it doing some of built-in migration of the framework. This kind of name of migrations should make it started 1st and when you publish it, it will appear at the beginning of the migrations list, that allow devs to catch sight of the migration and rename it giving timestamp they need or leave it as is.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.