Closed Tarasovych closed 6 years ago
2 path_to_my_project\vendor\monolog\monolog\src\Monolog\Handler\MongoDBHandler.php(46): MongoDB\Collection->insertOne('[2018-08-09 22:...')
I believe here we see the problem: a string is passed which looks like from the default line formatter, but insertOne
expects either an array or an string.
I don't see a formatter in your configuration, please see if this works:
'formatter' => \Monolog\Formatter\MongoDBFormatter::class,
@mfn thank you! Didn't know that formatter is required. I'm done with clearing config cache.
But now I'm trying to log something and I get
Class 'MongoDate' not found in .../vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php on line 103
phpinfo()
:
MongoDB support => enabled
MongoDB extension version => 1.5.0
MongoDB extension stability => stable
libbson bundled version => 1.11.0
libmongoc bundled version => 1.11.0
libmongoc SSL => enabled
libmongoc SSL library => OpenSSL
libmongoc crypto => enabled
libmongoc crypto library => libcrypto
libmongoc crypto system profile => disabled
libmongoc SASL => enabled
libmongoc ICU => disabled
libmongoc compression => disabled
It seems that \MongoDate
is something outdated/older, define by the "PECL mongo" extension, see the warning on http://php.net/manual/en/class.mongodate.php
This extension that defines this class is deprecated. Instead, the MongoDB extension should be used. Alternatives to this class include: MongoDB\BSON\UTCDateTime
The referenced class OTOH MongoDB\BSON\UTCDateTime
is from the "mongodb" extension you're using => http://php.net/manual/en/class.mongodb-bson-utcdatetime.php
It seems that \Monolog\Handler\MongoDBHandler::__construct
is prepared to handle different mongodb clients, but \Monolog\Formatter\MongoDBFormatter
only works with "PECL mongo".
For you to move forward, my advice is to simply copy that MongoDBFormatter
into your application and adapt it.
I found your Monolog issue that you created about this problem, so maybe you can figure out what's with the formatter and maybe contribute back a version working with both clients.
Oh, I just found out: Monologs master has an updated version: https://github.com/Seldaek/monolog/blob/master/src/Monolog/Formatter/MongoDBFormatter.php
But it's a different version in the latest release (1.23.0).
Monologs last release was >1 year ago and a lot has happened since then. I guess the 1.x version is maintenance only (it contains the version you're using, see https://github.com/Seldaek/monolog/blob/1.x/src/Monolog/Formatter/MongoDBFormatter.php ) and at somepoint there will probably a 2.x release with the version you need.
In this case: see if you can directly copy over that version into your project and work with that.
@mfn thank you a lot! So I
\MongoDate($value->getTimestamp())
to UTCDateTime($value->getTimestamp())
And it worked!
Maybe it's reasonable to have newer version inside https://github.com/laravel/framework/blob/5.6/composer.json#L25
@Tarasovych there is no newer release of Monolog with what you need, so there's nothing to do for Laravel.
Please close the issue.
I got one more error connected with this. So my logging.php
:
'mongo' => [
'driver' => 'monolog',
'handler' => \Monolog\Handler\MongoDBHandler::class,
'handler_with' => [
'mongo' => new MongoDB\Client(), // MongoDB\Client()::class doesn't work
'database' => 'logs',
'collection' => 'prod'
],
'formatter' => App\MongoDBFormatter::class
]
I can't execute php artisan config:cache
. It returns
LogicException : Your configuration files are not serializable.
Exception trace:
1 Error::("Call to undefined method MongoDB\Driver\Manager::__set_state()")
...\bootstrap\cache\config.php:445
2 require()
...\vendor\laravel\framework\src\Illuminate\Foundation\Console\ConfigCacheCommand.php:64
I can run php artisan config:clear
, and I can log in MongoDB by the way.
P. S. I've also tried
'mongo' => [
'manager' => MongoDB\Driver\Manager::class,
'uri' => 'mongodb://localhost:27017',
'typeMap' => [
'array' => MongoDB\Model\BSONArray::class,
'document' => MongoDB\Model\BSONDocument::class,
'root' => MongoDB\Model\BSONDocument::class
],
'writeConcern' => MongoDB\Driver\WriteConcern::class
],
without any success.
I understand why I got "not serializable", but that config works... What to do now?
Instead of
'mongo' => new MongoDB\Client(), // MongoDB\Client()::class doesn't work
did you try
'mongo' => new MongoDB\Client::class,
(no parenthesis)
@mfn IDE doesn't allow me to do that)
syntax error, unexpected 'class' (T_CLASS), expecting variable (T_VARIABLE) or '$'
Sorry, typo:
'mongo' => MongoDB\Client::class,
(no new
)
@mfn I tried that, doesn't work.
P. S. I meant, there is no problem with config serialization, but nothing logs into mongo.
I've also tried to call different methods from MongoDB\Client
. Like 'mongo' => (string)(new MongoDB\Client()->...)
in hope it will work, but no success. If I know what actually mongo
might be for success logging - connection URL or something other.
I think I now understand the issue better.
You're creating driver=monolog
which calls \Illuminate\Log\LogManager::createMonologDriver
and creates a MongoDBHandler
instance and and passes handler_with
as its arguments.
The problem is: the arguments are passed literally, that's why the first argument, which is only class string reference to MongoDB\Client
, is passed literally to the MongoDBHandler
=> there's nothing "in between" which understands this needs to be an actual instance of MongoDB\Client
(that's why in your examples it works with new
in the config but has the other issue with caching the config).
I think what you want to achieve is not possible directly with the driver=monolog
adapter ATM because of how MongoDBHandler
expects its argument.
What you need is more flexibility and therefore I suggest you create a custom
driver like this:
'mongo' => [
'driver' => 'custom',
'via' => YourOwnMongodbAdapter::class,
'name' => 'default',
'database' => 'logs',
'collection' => 'test',
],
(see also https://laravel.com/docs/5.6/logging#creating-channels-via-factories )
Then YourOwnMongodbAdapter::__invoke
receives your $config
array and you can create the Monolog driver the way you need it; untested but it should something similar to this:
<?php
use Monolog\Handler\MongoDBHandler;
class YourOwnMongodbAdapter
{
public function __invoke(array $config)
{
$handler = new MongoDBHandler(
new MongoDB\Client(),
$config['database'],
$config['collection']
);
$handler->setFormatter(new \App\MongoDBFormatter);
return new Monolog\Logger(
$config['name'],
[$handler]
);
}
}
@mfn thanks! Now I can execute php artisan config:cache
without errors, but when logging, I got
Your configuration files are not serializable.
yet in Mongo.
Update: ^ that was my miss, because of date format issue. So, it works!
Also I get 1970 year using UTCDateTime class for formatting data, but this is another question...
So I went from
protected function formatDate(\DateTime $value, $nestingLevel)
{
return new UTCDateTime($value->getTimestamp());
}
to
protected function formatDate(\DateTime $value, $nestingLevel)
{
return $value;
}
and I have correct date.
you can also try this : https://github.com/Amirhb/laravel-mongodb-log tell me if you needed any update. doc: https://packagist.org/packages/amirhb/laravel-mongodb-log
You can register the mongo client in service provider and live the $mongodb value empty:
Laravel 9.x
// AppServiceProvider.php
// register function
$this->app->when(\Monolog\Handler\MongoDBHandler::class)
->needs('$mongodb')
->give(app(\MongoDB\Client::class));
// logging.php
'mongo' => [
'driver' => 'monolog',
'handler' => \Monolog\Handler\MongoDBHandler::class,
'formatter' =>\Monolog\Formatter\MongoDBFormatter::class,
'with' => [
'database' => 'logs',
// 'mongo' => new MongoDB\Client(), <-- Remove this key
'collection' => 'prod',
],
]
Description:
My
config/logging.php
:My
.env
:LOG_CHANNEL=stack
.I'm sure that MongoDB database
logs
exists,test
collection too.I'm trying to execute
php artisan config:cache
, I get an error:What's wrong? I guess, my config was amde accordingly to documentation.
What I've tried so far:
same error.