Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@
"psr-4": {
"RunOpenCode\\Component\\Bitmask\\": "src/RunOpenCode/Component/Bitmask/src/",
"RunOpenCode\\Component\\Dataset\\": "src/RunOpenCode/Component/Dataset/src/",
"RunOpenCode\\Component\\Logger\\": "src/RunOpenCode/Component/Logger/src/",
"RunOpenCode\\Component\\Metadata\\": "src/RunOpenCode/Component/Metadata/src/",
"RunOpenCode\\Component\\Query\\": "src/RunOpenCode/Component/Query/src/",
"RunOpenCode\\Bundle\\LoggerBundle\\": "src/RunOpenCode/Bundle/LoggerBundle/src/",
"RunOpenCode\\Bundle\\QueryBundle\\": "src/RunOpenCode/Bundle/QueryBundle/src/",
"RunOpenCode\\Bundle\\MetadataBundle\\": "src/RunOpenCode/Bundle/MetadataBundle/src/",
"Monorepo\\": "monorepo/"
Expand All @@ -54,8 +56,10 @@
"psr-4": {
"RunOpenCode\\Component\\Bitmask\\Tests\\": "src/RunOpenCode/Component/Bitmask/tests/",
"RunOpenCode\\Component\\Dataset\\Tests\\": "src/RunOpenCode/Component/Dataset/tests/",
"RunOpenCode\\Component\\Logger\\Tests\\": "src/RunOpenCode/Component/Logger/tests/",
"RunOpenCode\\Component\\Metadata\\Tests\\": "src/RunOpenCode/Component/Metadata/tests/",
"RunOpenCode\\Component\\Query\\Tests\\": "src/RunOpenCode/Component/Query/tests/",
"RunOpenCode\\Bundle\\LoggerBundle\\Tests\\": "src/RunOpenCode/Bundle/LoggerBundle/tests/",
"RunOpenCode\\Bundle\\QueryBundle\\Tests\\": "src/RunOpenCode/Bundle/QueryBundle/tests/",
"RunOpenCode\\Bundle\\MetadataBundle\\Tests\\": "src/RunOpenCode/Bundle/MetadataBundle/tests/"
}
Expand All @@ -66,7 +70,6 @@
"phpstan": "XDEBUG_MODE=off vendor/bin/phpstan analyse --memory-limit=-1",
"phpcs": "XDEBUG_MODE=off vendor/bin/php-cs-fixer fix --diff --verbose --show-progress=dots --allow-risky=yes",
"deps": "bin/deps",
"phpmd": "XDEBUG_MODE=off vendor/bin/phpmd src text phpmd.xml | tee build/phpmd/phpmd.txt & vendor/bin/phpmd src xml phpmd.xml --reportfile build/phpmd/phpmd.xml ; vendor/bin/phpmd src html phpmd.xml --reportfile build/phpmd/phpmd.html",
"phpmetrics": "phpmetrics --report-html=build/metrics src/",
"rector": "XDEBUG_MODE=off vendor/bin/rector process --ansi",
"infection": "infection --threads=max"
Expand Down
1 change: 1 addition & 0 deletions docs/source/bundles/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ Table of Contents
:maxdepth: 2
:titlesonly:

logger-bundle/index
metadata-bundle/index

177 changes: 177 additions & 0 deletions docs/source/bundles/logger-bundle/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
=============
Logger Bundle
=============

The Logger Bundle provides seamless integration of the Logger component with
the Symfony framework. This bundle automatically configures the Logger as a
service and provides configuration options for customizing its behavior.

The Logger component is a decorator for PSR-3 logger implementations that adds
convenience methods for exception logging and context enrichment. See the
:doc:`../../components/logger/index` for details about the Logger component
itself.

Installation
------------

To use the Logger component in a Symfony application, install the bundle:

.. code-block:: console

composer require runopencode/logger-bundle

The bundle will be automatically registered in your ``config/bundles.php`` if
you're using Symfony Flex.

Configuration
-------------

The bundle provides several configuration options that can be set in your
``config/packages/runopencode_logger.yaml`` file:

.. code-block:: yaml

runopencode_logger:
debug: '%kernel.debug%'
default_log_level: 'error'

Configuration options
~~~~~~~~~~~~~~~~~~~~~

* ``debug`` (boolean, default: ``false``): Enable debug mode. When enabled, the
``exception()`` method will throw exceptions after logging them. This is
useful during development. Typically set to ``%kernel.debug%`` to match
Symfony's debug mode.

* ``default_log_level`` (string, default: ``'critical'``): The default log level
used for exception logging when no level is explicitly specified. Valid values
are: ``emergency``, ``alert``, ``critical``, ``error``, ``warning``,
``notice``, ``info``, ``debug``.

Using the Logger service
-------------------------

Once the bundle is installed and configured, the Logger service is automatically
available for dependency injection. Inject it using the interface:

.. code-block:: php
:linenos:

<?php

declare(strict_types=1);

namespace App\Service;

use RunOpenCode\Component\Logger\Contract\LoggerInterface;

final readonly class UserService
{
public function __construct(private LoggerInterface $logger)
{
// noop.
}

public function registerUser(array $userData): User
{
try {
$user = $this->repository->create($userData);
$this->mailer->sendWelcomeEmail($user);

return $user;
} catch (\Throwable $exception) {
$this->logger->exception(
$exception,
'User registration failed',
['email' => $userData['email'] ?? 'unknown']
);
// ...
}
}
}

The Logger is automatically configured with Symfony's default logger (the
``logger`` service).

Automatic context provider registration
----------------------------------------

One of the most powerful features of the bundle is automatic registration of
context providers. Any service that implements ``LoggerContextInterface`` is
automatically detected and injected into the Logger.

Creating a context provider
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Simply create a service that implements the interface:

.. code-block:: php
:linenos:

<?php

declare(strict_types=1);

namespace App\Logger\Context;

use RunOpenCode\Component\Logger\Contract\LoggerContextInterface;
use Symfony\Component\HttpFoundation\RequestStack;

final readonly class RequestContextProvider implements LoggerContextInterface
{
public function __construct(private RequestStack $requestStack)
{
// noop.
}

public function get(array $current): array
{
$request = $this->requestStack->getCurrentRequest();

if (null === $request) {
return [];
}

return [
'request_id' => $request->headers->get('X-Request-ID') ?? uniqid(),
'request_uri' => $request->getRequestUri(),
'request_method' => $request->getMethod(),
'user_agent' => $request->headers->get('User-Agent'),
];
}
}

If you have services autoconfiguration enabled (which is the default in Symfony),
this service will be automatically registered and tagged with
``runopencode.logger.context_provider``. No additional configuration is needed!

Manual registration
~~~~~~~~~~~~~~~~~~~

If you're not using autoconfiguration or want to explicitly register a context
provider, you can do so in your services configuration:

.. code-block:: yaml

services:
App\Logger\Context\RequestContextProvider:
tags:
- { name: 'runopencode.logger.context_provider' }

Best practices
--------------

1. **Use the interface**: Always inject ``LoggerInterface`` from the Logger
component, not the concrete ``Logger`` class or PSR-3's ``LoggerInterface``.

2. **Configure per environment**: Use different configuration files for dev,
test, and prod environments to adjust debug mode and log levels.

3. **Create focused context providers**: Each context provider should have a
single responsibility (e.g., one for request data, one for user data, etc.).

4. **Keep providers lightweight**: Context providers are called on every log
entry, so avoid expensive operations.

See the :doc:`../../components/logger/context-providers` documentation for more
information about creating and using context providers.
1 change: 1 addition & 0 deletions docs/source/components/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ Table of Contents
:titlesonly:

dataset/index
logger/index
metadata/index
query/index
Loading