> For the complete documentation index, see [llms.txt](https://framework.deep-web-solutions.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://framework.deep-web-solutions.com/foundations-module/utilities/handlers-and-services/logging-service.md).

# Logging Service

The [logging service](https://github.com/deep-web-solutions/wordpress-framework-foundations/tree/master/src/includes/Logging) is the only example of a service provided in the foundations module. That's because we believe that every plugin should use logging (hence also why every service is forced to implement the [`LoggingServiceAwareInterface`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Logging/LoggingServiceAwareInterface.php) interface).

In short, the logging service is a multi-handler service that accepts any handler implementing the [`LoggingHandlerInterface`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Logging/LoggingHandlerInterface.php) interface. It's expected to provide the service with two handlers, one with the ID *framework* and one with the ID *plugin*.&#x20;

By default, the logging service attempts to log using the *plugin* handler, whereas messages logged by framework modules will always use the *framework* handler. In order to include sensitive data in the log messages, you need to instantiate the service with the second parameter set to `true`.

{% hint style="danger" %}
The logging service doesn't understand what data is of sensitive nature and which is not. It's your responsibility to mark it accordingly when composing the logged message.
{% endhint %}

{% hint style="info" %}
If you want to disable logging for your plugin, it's enough to not register the two aforementioned handlers. The service will simply default to using the [NullLogger](https://github.com/php-fig/log/blob/master/Psr/Log/NullLogger.php).
{% endhint %}

The [default logging handler](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Logging/LoggingHandler.php) requires an ID and a [PSR-3](https://www.php-fig.org/psr/psr-3/) logger. We recommend using [Monolog](https://packagist.org/packages/monolog/monolog) for your PSR-3 logger needs, but if you're building a WooCommerce plugin, please be aware that the [WooCommerce module](https://packagist.org/packages/deep-web-solutions/wp-framework-woocommerce) provides a handler compatible with the WooCommerce logger.

Here is a simple example for instantiating the logging service using Monolog loggers:

```php
<?php

namespace DeepWebSolutions\Plugins\MyTestPlugin;

use DeepWebSolutions\Framework\Foundations\Logging\LoggingHandler;
use DeepWebSolutions\Framework\Foundations\Logging\LoggingService;
use DeepWebSolutions\Framework\Helpers\WordPress\Request;

use Monolog\Handler\RotatingFileHandler as MonologRotatingFileHandler;
use Monolog\Logger as MonologLogger;

use function DeepWebSolutions\Framework\dws_wp_framework_get_temp_dir_path;


$min_log_level = Request::has_debug() ? MonologLogger::DEBUG : MonologLogger::ERROR;
$logs_path     = dws_wp_framework_get_temp_dir_path() . 'my-test-plugin' . DIRECTORY_SEPARATOR;

$monolog_handler = new MonologRotatingFileHandler( $logs_path . 'errors.log', 30, $min_log_level );
$dws_handlers    = array(
    new LoggingHandler( 'framework', new MonologLogger( 'framework', array( $monolog_handler ) ) ),
    new LoggingHandler( 'plugin', new MonologLogger( 'plugin', array( $monolog_handler ) ) ),
);

$plugin_instance     = dws_test_plugin_instance();
$dws_logging_service = new LoggingService( $plugin_instance, $dws_handlers, Request::has_debug() );

```

The logging service provides two public methods:

* `log_event` -- returns an instance of the [`LogMessageBuilder`](https://github.com/deep-web-solutions/wordpress-framework-foundations/blob/master/src/includes/Logging/LogMessageBuilder.php) class which can be further configured to perform other actions before logging the message.
* `log_event_and_finalize` -- shortcut for calling the `log_event` method and finalizing the message.

Instances of the `LogMessageBuilder` class need to have the finalize method called on them for the message to be logged and the other actions performed as well.

{% hint style="warning" %}
If you don't call `finalize` on `LogMessageBuilder` objects, the message will never be logged!
{% endhint %}

A few things that the message builder can do:

* If the service is configured to ignore sensitive content, it removes all the text wrapped in `<sensitive></sensitive>` tags.
* It can log the message using WordPress' [`_doing_it_wrong`](https://developer.wordpress.org/reference/functions/_doing_it_wrong/) as well.
* By default, it returns `null` when calling `finalize`, but it can be configured to return the logged message wrapped in an exception or a given throwable object.

And here are examples on how to use the message builder (we'll assume the logging service instantiated above is present in this context as well):

```php
<?php

use DeepWebSolutions\Framework\Foundations\Exceptions\NotFoundException;
use Psr\Log\LogLevel;

// The following two lines are EQUIVALENT.
$dws_logging_service->log_event( 'Error happened' )
                ->set_log_level( LogLevel::DEBUG )
                ->finalize();

$dws_logging_service->log_event_and_finalize( 'Error happened' );

// This message will be logged with WP too.
$dws_logging_service->log_event( 'Error happened in function' )
                ->doing_it_wrong( 'my_awesome_func', '1.3.5' )
                ->finalize();

// This message will return an exception.
$exception = $dws_logging_service->log_event_and_finalize( 'Property A not found' )
                ->return_exception( NotFoundException::class )
                ->finalize();
echo get_class( $exception ); // echoes 'NotFoundException'
echo $exception->getMessage(); // echoes 'Property A not found'
```
