# 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'
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://framework.deep-web-solutions.com/foundations-module/utilities/handlers-and-services/logging-service.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
