Skip to content

Commit 41c9a49

Browse files
committed
Deprecate "mongo" handler type in favor of new "mongodb" syntax
Define a new "mongodb" handler type. It accepts an "id" reference like the old "mongo" type; however, "uri" instead of a single "host" and "port". The "uri" option is more flexible. Additionally, the "username" and "password" options have been renamed and are no longer used to modify the connection string directly ("mongo" never applied URL encoding). Instead, the options are set in the URI options array, which does not require encoding. The "mongodb" never requires a password, as a username alone is valid for some auth mechanisms. Lastly, a "monolog-bundle" app name is specified when the bundle constructs a MongoDB\Client instance for both "mongo" and "mongodb" handler syntax.
1 parent c6b64c3 commit 41c9a49

File tree

8 files changed

+273
-1
lines changed

8 files changed

+273
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
* Add `hosts` configuration for `elastica` handler
1818
* Add `enabled` option to `handlers` configuration
1919
* Add `priority` field to `processor` tag
20+
* Add `mongodb` handler and deprecate `mongo`
2021

2122
## 3.10.0 (2023-11-06)
2223

config/schema/monolog-1.0.xsd

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<xsd:element name="channels" type="channels" minOccurs="0" maxOccurs="1" />
2222
<xsd:element name="publisher" type="publisher" minOccurs="0" maxOccurs="1" />
2323
<xsd:element name="mongo" type="mongo" minOccurs="0" maxOccurs="1" />
24+
<xsd:element name="mongodb" type="mongodb" minOccurs="0" maxOccurs="1" />
2425
<xsd:element name="elasticsearch" type="elasticsearch" minOccurs="0" maxOccurs="1" />
2526
<xsd:element name="config" type="xsd:anyType" minOccurs="0" maxOccurs="1" />
2627
<xsd:element name="excluded-404" type="xsd:string" minOccurs="0" maxOccurs="unbounded" />
@@ -163,6 +164,15 @@
163164
<xsd:attribute name="collection" type="xsd:string" />
164165
</xsd:complexType>
165166

167+
<xsd:complexType name="mongodb">
168+
<xsd:attribute name="id" type="xsd:string" />
169+
<xsd:attribute name="uri" type="xsd:string" />
170+
<xsd:attribute name="username" type="xsd:string" />
171+
<xsd:attribute name="password" type="xsd:string" />
172+
<xsd:attribute name="database" type="xsd:string" />
173+
<xsd:attribute name="collection" type="xsd:string" />
174+
</xsd:complexType>
175+
166176
<xsd:complexType name="redis">
167177
<xsd:attribute name="id" type="xsd:string" />
168178
<xsd:attribute name="host" type="xsd:string" />

src/DependencyInjection/Configuration.php

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,17 @@
9090
* - [level]: level name or int value, defaults to DEBUG
9191
* - [bubble]: bool, defaults to true
9292
*
93+
* - mongodb:
94+
* - mongodb:
95+
* - id: optional if uri is given
96+
* - uri: MongoDB connection string, optional if id is given
97+
* - [username]: Username for database authentication
98+
* - [password]: Password for database authentication
99+
* - [database]: Database to which logs are written (not used for auth), defaults to "monolog"
100+
* - [collection]: Collection to which logs are written, defaults to "logs"
101+
* - [level]: level name or int value, defaults to DEBUG
102+
* - [bubble]: bool, defaults to true
103+
*
93104
* - elastic_search:
94105
* - elasticsearch:
95106
* - id: optional if host is given
@@ -648,6 +659,7 @@ public function getConfigTreeBuilder(): TreeBuilder
648659

649660
$this->addGelfSection($handlerNode);
650661
$this->addMongoSection($handlerNode);
662+
$this->addMongoDBSection($handlerNode);
651663
$this->addElasticsearchSection($handlerNode);
652664
$this->addRedisSection($handlerNode);
653665
$this->addPredisSection($handlerNode);
@@ -891,7 +903,40 @@ private function addMongoSection(ArrayNodeDefinition $handlerNode)
891903
->end()
892904
->validate()
893905
->ifTrue(function ($v) { return 'mongo' === $v['type'] && !isset($v['mongo']); })
894-
->thenInvalid('The mongo configuration has to be specified to use a MongoHandler')
906+
->thenInvalid('The mongo configuration has to be specified to use a MongoDBHandler')
907+
->end()
908+
;
909+
}
910+
911+
private function addMongoDBSection(ArrayNodeDefinition $handlerNode)
912+
{
913+
$handlerNode
914+
->children()
915+
->arrayNode('mongodb')
916+
->canBeUnset()
917+
->beforeNormalization()
918+
->ifString()
919+
->then(function ($v) { return ['id' => $v]; })
920+
->end()
921+
->children()
922+
->scalarNode('id')->end()
923+
->scalarNode('uri')->end()
924+
->scalarNode('username')->end()
925+
->scalarNode('password')->end()
926+
->scalarNode('database')->defaultValue('monolog')->end()
927+
->scalarNode('collection')->defaultValue('logs')->end()
928+
->end()
929+
->validate()
930+
->ifTrue(function ($v) {
931+
return !isset($v['id']) && !isset($v['uri']);
932+
})
933+
->thenInvalid('What must be set is either the uri or the id.')
934+
->end()
935+
->end()
936+
->end()
937+
->validate()
938+
->ifTrue(function ($v) { return 'mongodb' === $v['type'] && !isset($v['mongodb']); })
939+
->thenInvalid('The mongodb configuration has to be specified to use a MongoDBHandler')
895940
->end()
896941
;
897942
}

src/DependencyInjection/MonologExtension.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
265265
break;
266266

267267
case 'mongo':
268+
trigger_deprecation('symfony/monolog-bundle', '3.11', 'The "mongo" handler type is deprecated in MonologBundle since version 3.11.0, use the "mongodb" type instead.');
269+
268270
if (isset($handler['mongo']['id'])) {
269271
$client = new Reference($handler['mongo']['id']);
270272
} else {
@@ -278,6 +280,7 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
278280

279281
$client = new Definition('MongoDB\Client', [
280282
$server,
283+
['appname' => 'monolog-bundle'],
281284
]);
282285

283286
$client->setPublic(false);
@@ -292,6 +295,37 @@ private function buildHandler(ContainerBuilder $container, $name, array $handler
292295
]);
293296
break;
294297

298+
case 'mongodb':
299+
if (isset($handler['mongodb']['id'])) {
300+
$client = new Reference($handler['mongodb']['id']);
301+
} else {
302+
$uriOptions = ['appname' => 'monolog-bundle'];
303+
304+
if (isset($handler['mongodb']['username'])) {
305+
$uriOptions['username'] = $handler['mongodb']['username'];
306+
}
307+
308+
if (isset($handler['mongodb']['password'])) {
309+
$uriOptions['password'] = $handler['mongodb']['password'];
310+
}
311+
312+
$client = new Definition('MongoDB\Client', [
313+
$handler['mongodb']['uri'],
314+
$uriOptions,
315+
]);
316+
317+
$client->setPublic(false);
318+
}
319+
320+
$definition->setArguments([
321+
$client,
322+
$handler['mongodb']['database'],
323+
$handler['mongodb']['collection'],
324+
$handler['level'],
325+
$handler['bubble'],
326+
]);
327+
break;
328+
295329
case 'elasticsearch':
296330
trigger_deprecation('symfony/monolog-bundle', '3.8', 'The "elasticsearch" handler type is deprecated in MonologBundle since version 3.8.0, use the "elastica" type instead, or switch to the official Elastic client using the "elastic_search" type.');
297331
// no break
@@ -1021,6 +1055,7 @@ private function getHandlerClassByType($handlerType)
10211055
'fingers_crossed' => 'Monolog\Handler\FingersCrossedHandler',
10221056
'filter' => 'Monolog\Handler\FilterHandler',
10231057
'mongo' => 'Monolog\Handler\MongoDBHandler',
1058+
'mongodb' => 'Monolog\Handler\MongoDBHandler',
10241059
'elasticsearch' => 'Monolog\Handler\ElasticSearchHandler',
10251060
'telegram' => 'Monolog\Handler\TelegramBotHandler',
10261061
'server_log' => 'Symfony\Bridge\Monolog\Handler\ServerLogHandler',

tests/DependencyInjection/FixtureMonologExtensionTestCase.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bundle\MonologBundle\Tests\DependencyInjection;
1313

1414
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
15+
use Monolog\Handler\MongoDBHandler;
1516
use Monolog\Handler\NoopHandler;
1617
use Monolog\Handler\NullHandler;
1718
use Monolog\Processor\PsrLogMessageProcessor;
@@ -332,6 +333,19 @@ public function testEnabledHandleOption()
332333
$this->assertFalse($container->hasDefinition('monolog.handler.disabled'));
333334
}
334335

336+
public function testMongoDB()
337+
{
338+
$container = $this->getContainer('mongodb');
339+
340+
$this->assertTrue($container->hasDefinition('monolog.handler.mongodb'));
341+
$handler = $container->getDefinition('monolog.handler.mongodb');
342+
$this->assertDICDefinitionClass($handler, MongoDBHandler::class);
343+
$client = $handler->getArgument(0);
344+
$this->assertDICDefinitionClass($client, 'MongoDB\Client');
345+
$this->assertDICConstructorArguments($client, ['mongodb://localhost:27018', ['appname' => 'monolog-bundle', 'username' => 'username', 'password' => 'password']]);
346+
$this->assertDICConstructorArguments($handler, [$client, 'db', 'coll', 'DEBUG', true]);
347+
}
348+
335349
protected function getContainer($fixture)
336350
{
337351
$container = new ContainerBuilder();
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" ?>
2+
3+
<srv:container xmlns="http://symfony.com/schema/dic/monolog"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xmlns:srv="http://symfony.com/schema/dic/services"
6+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
7+
http://symfony.com/schema/dic/monolog http://symfony.com/schema/dic/monolog/monolog-1.0.xsd">
8+
9+
<config>
10+
<handler name="mongodb" type="mongodb">
11+
<mongodb uri="mongodb://localhost:27018" username="username" password="password" database="db" collection="coll" />
12+
</handler>
13+
</config>
14+
</srv:container>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
monolog:
2+
handlers:
3+
mongodb:
4+
type: mongodb
5+
mongodb:
6+
uri: "mongodb://localhost:27018"
7+
username: username
8+
password: password
9+
database: db
10+
collection: coll

tests/DependencyInjection/MonologExtensionTest.php

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Monolog\Handler\ElasticaHandler;
1717
use Monolog\Handler\ElasticsearchHandler;
1818
use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
19+
use Monolog\Handler\MongoDBHandler;
1920
use Monolog\Handler\RollbarHandler;
2021
use Monolog\Logger;
2122
use Monolog\Processor\UidProcessor;
@@ -932,6 +933,148 @@ public function testElasticsearchAndElasticaHandlers()
932933
$this->assertSame(['hosts' => ['es:9200'], 'transport' => 'Http'], $elasticaClient->getArgument(0));
933934
}
934935

936+
/** @group legacy */
937+
public function testMongo()
938+
{
939+
$this->expectDeprecation('Since symfony/monolog-bundle 3.11: The "mongo" handler type is deprecated in MonologBundle since version 3.11.0, use the "mongodb" type instead.');
940+
941+
$container = new ContainerBuilder();
942+
$container->setDefinition('mongodb.client', new Definition('MongoDB\Client'));
943+
944+
$config = [[
945+
'handlers' => [
946+
'mongo_with_id' => [
947+
'type' => 'mongo',
948+
'mongo' => ['id' => 'mongodb.client'],
949+
],
950+
'mongo_with_string_id' => [
951+
'type' => 'mongo',
952+
'mongo' => 'mongodb.client',
953+
],
954+
'mongo_with_host' => [
955+
'type' => 'mongo',
956+
'mongo' => [
957+
'host' => 'localhost',
958+
'port' => '27018',
959+
'user' => 'username',
960+
'pass' => 'password',
961+
'database' => 'db',
962+
'collection' => 'coll',
963+
],
964+
],
965+
'mongo_with_host_and_default_args' => [
966+
'type' => 'mongo',
967+
'mongo' => [
968+
'host' => 'localhost',
969+
],
970+
],
971+
],
972+
]];
973+
974+
$extension = new MonologExtension();
975+
$extension->load($config, $container);
976+
977+
$this->assertTrue($container->hasDefinition('monolog.handler.mongo_with_id'));
978+
$this->assertTrue($container->hasDefinition('monolog.handler.mongo_with_string_id'));
979+
$this->assertTrue($container->hasDefinition('monolog.handler.mongo_with_host'));
980+
$this->assertTrue($container->hasDefinition('monolog.handler.mongo_with_host_and_default_args'));
981+
982+
// MongoDB handler should receive the mongodb.client as first argument
983+
$handler = $container->getDefinition('monolog.handler.mongo_with_id');
984+
$this->assertDICDefinitionClass($handler, MongoDBHandler::class);
985+
$this->assertDICConstructorArguments($handler, [new Reference('mongodb.client'), 'monolog', 'logs', 'DEBUG', true]);
986+
987+
// MongoDB handler should receive the mongodb.client as first argument
988+
$handler = $container->getDefinition('monolog.handler.mongo_with_string_id');
989+
$this->assertDICDefinitionClass($handler, MongoDBHandler::class);
990+
$this->assertDICConstructorArguments($handler, [new Reference('mongodb.client'), 'monolog', 'logs', 'DEBUG', true]);
991+
992+
// MongoDB handler with host and arguments
993+
$handler = $container->getDefinition('monolog.handler.mongo_with_host');
994+
$this->assertDICDefinitionClass($handler, MongoDBHandler::class);
995+
$client = $handler->getArgument(0);
996+
$this->assertDICDefinitionClass($client, 'MongoDB\Client');
997+
$this->assertDICConstructorArguments($client, ['mongodb://username:password@localhost:27018', ['appname' => 'monolog-bundle']]);
998+
$this->assertDICConstructorArguments($handler, [$client, 'db', 'coll', 'DEBUG', true]);
999+
1000+
// MongoDB handler with host and default arguments
1001+
$handler = $container->getDefinition('monolog.handler.mongo_with_host_and_default_args');
1002+
$this->assertDICDefinitionClass($handler, MongoDBHandler::class);
1003+
$client = $handler->getArgument(0);
1004+
$this->assertDICDefinitionClass($client, 'MongoDB\Client');
1005+
$this->assertDICConstructorArguments($client, ['mongodb://localhost:27017', ['appname' => 'monolog-bundle']]);
1006+
$this->assertDICConstructorArguments($handler, [$client, 'monolog', 'logs', 'DEBUG', true]);
1007+
}
1008+
1009+
public function testMongoDB()
1010+
{
1011+
$container = new ContainerBuilder();
1012+
$container->setDefinition('mongodb.client', new Definition('MongoDB\Client'));
1013+
1014+
$config = [[
1015+
'handlers' => [
1016+
'mongodb_with_id' => [
1017+
'type' => 'mongodb',
1018+
'mongodb' => ['id' => 'mongodb.client'],
1019+
],
1020+
'mongodb_with_string_id' => [
1021+
'type' => 'mongodb',
1022+
'mongodb' => 'mongodb.client',
1023+
],
1024+
'mongodb_with_uri' => [
1025+
'type' => 'mongodb',
1026+
'mongodb' => [
1027+
'uri' => 'mongodb://localhost:27018',
1028+
'username' => 'username',
1029+
'password' => 'password',
1030+
'database' => 'db',
1031+
'collection' => 'coll',
1032+
],
1033+
],
1034+
'mongodb_with_uri_and_default_args' => [
1035+
'type' => 'mongodb',
1036+
'mongodb' => [
1037+
'uri' => 'mongodb://localhost:27018',
1038+
],
1039+
],
1040+
],
1041+
]];
1042+
1043+
$extension = new MonologExtension();
1044+
$extension->load($config, $container);
1045+
1046+
$this->assertTrue($container->hasDefinition('monolog.handler.mongodb_with_id'));
1047+
$this->assertTrue($container->hasDefinition('monolog.handler.mongodb_with_string_id'));
1048+
$this->assertTrue($container->hasDefinition('monolog.handler.mongodb_with_uri'));
1049+
$this->assertTrue($container->hasDefinition('monolog.handler.mongodb_with_uri_and_default_args'));
1050+
1051+
// MongoDB handler should receive the mongodb.client as first argument
1052+
$handler = $container->getDefinition('monolog.handler.mongodb_with_id');
1053+
$this->assertDICDefinitionClass($handler, MongoDBHandler::class);
1054+
$this->assertDICConstructorArguments($handler, [new Reference('mongodb.client'), 'monolog', 'logs', 'DEBUG', true]);
1055+
1056+
// MongoDB handler should receive the mongodb.client as first argument
1057+
$handler = $container->getDefinition('monolog.handler.mongodb_with_string_id');
1058+
$this->assertDICDefinitionClass($handler, MongoDBHandler::class);
1059+
$this->assertDICConstructorArguments($handler, [new Reference('mongodb.client'), 'monolog', 'logs', 'DEBUG', true]);
1060+
1061+
// MongoDB handler with arguments
1062+
$handler = $container->getDefinition('monolog.handler.mongodb_with_uri');
1063+
$this->assertDICDefinitionClass($handler, MongoDBHandler::class);
1064+
$client = $handler->getArgument(0);
1065+
$this->assertDICDefinitionClass($client, 'MongoDB\Client');
1066+
$this->assertDICConstructorArguments($client, ['mongodb://localhost:27018', ['appname' => 'monolog-bundle', 'username' => 'username', 'password' => 'password']]);
1067+
$this->assertDICConstructorArguments($handler, [$client, 'db', 'coll', 'DEBUG', true]);
1068+
1069+
// MongoDB handler with host and default arguments
1070+
$handler = $container->getDefinition('monolog.handler.mongodb_with_uri_and_default_args');
1071+
$this->assertDICDefinitionClass($handler, MongoDBHandler::class);
1072+
$client = $handler->getArgument(0);
1073+
$this->assertDICDefinitionClass($client, 'MongoDB\Client');
1074+
$this->assertDICConstructorArguments($client, ['mongodb://localhost:27018', ['appname' => 'monolog-bundle']]);
1075+
$this->assertDICConstructorArguments($handler, [$client, 'monolog', 'logs', 'DEBUG', true]);
1076+
}
1077+
9351078
protected function getContainer(array $config = [], array $thirdPartyDefinitions = []): ContainerBuilder
9361079
{
9371080
$container = new ContainerBuilder(new EnvPlaceholderParameterBag());

0 commit comments

Comments
 (0)