php процессор по удалению данных в контексте логов monolog

Нужно добавить процессор для логгера monolog.

Который будет удалять из контекста данные по определенному ключу.

В логи на разных страницах записываются все данные, которые прилетают из запроса. Иногда в них появляются авторизационные данные.

Массив с контекстом может быть любой вложенности т.е. многомерный. Как мне его обойти и сделать unset по определенному ключу. Или просто его обнулить. Например по ключу USER_PASSWORD.

Пример массива:

Array
(
    [message] => logging
    [context] => Array
        (
            [request] => Array
                (
                    [AUTH_FORM] => Y
                    [TYPE] => AUTH
                    [backurl] => /office/
                    [USER_LOGIN] => login
                    [USER_PASSWORD] => password
                    [Login] => ВОЙТИ
                 )
  
            )
    
        [level] => 200
        [level_name] => INFO
        [channel] => app
        [datetime] => DateTime Object
            (
                [date] => 2022-06-21 20:14:13.446691
                [timezone_type] => 3
                [timezone] => Europe/Moscow
            )
    
        [extra] => Array
            (
            )
)

Ответы (1 шт):

Автор решения: Соколов Данил

Одно из решений:

<?php

declare(strict_types=1);

namespace App\Log;

use Monolog\Processor\ProcessorInterface;

/**
 * Удаляет пользовательские пароли
 */
class PasswordCutterProcessor implements ProcessorInterface
{
    private const EXCLUDED_KEYS = ['USER_PASSWORD'];

    public function __invoke(array $records): array
    {
        return $this->cut($records);
    }

    /**
     * Рекурсивно обходит контекст логов и удаляет конфиденциальную информацию по ключу
     *
     * @param array $records
     *
     * @return array
     */
    private function cut(array $records): array
    {
        foreach ($records as $key => $value) {
            if (in_array($key, self::EXCLUDED_KEYS, true)) {
                unset($records[$key]);
            }

            if (is_array($value)) {
                $records[$key] = $this->cut($value);

                /** Очистка пустых массивов */
                if (count($records[$key]) === 0) {
                    unset($records[$key]);
                }
            }
        }

        return $records;
    }
}
→ Ссылка