Làm cách nào để tạo tệp Nhật ký tùy chỉnh trong Magento 2?


57

Trong Magento 1, thông thường phân đoạn nhật ký thành các tệp khác nhau (để tách nhật ký cho phương thức thanh toán, v.v.). Điều đó dễ như thay đổi $filetham số của Mage::log.

Magento 2 đã thay đổi để sử dụng Monolog.

Dường như Monolog (hoặc Magento2 triển khai nó) phân đoạn tất cả các bản ghi cho toàn bộ khung cho người xử lý theo mức độ nghiêm trọng. Có một vài trình xử lý ghi vào tệp:

\Magento\Framework\Logger\Handler\Debug, \Magento\Framework\Logger\Handler\Exception,\Magento\Framework\Logger\Handler\System

Đăng nhập vào các tệp tương ứng trong var / log như trong Magento 1.

Tôi có thể thêm một trình xử lý cho một mức độ nghiêm trọng cụ thể (IE, viết thông báo cho var/log/notice.log). Mở rộng \Magento\Framework\Logger\Handler\Basevà đăng ký xử lý di.xml.

Bài viết này mô tả quá trình đó: http://semaphoresoftware.kinja.com/how-to-create-a-custom-log-in-magento-2-1704130912

Nhưng làm thế nào để tôi viết về tất cả các bản ghi (không chỉ một mức độ nghiêm trọng) cho một lớp (không phải tất cả Magento) vào tệp mà tôi chọn?

Có vẻ như tôi sẽ phải tạo phiên bản của riêng mình Magento\Framework\Logger\Monolog, nhưng sau đó làm thế nào để mọi thứ khớp với nhau để nó thực sự hoạt động?

Nếu đây là một không lớn trong Magento 2, thì đâu là sự thay thế? Tôi muốn một cái gì đó để tách các bản ghi cho phần mở rộng này cho mục đích gỡ lỗi nó khi cần thiết trên các trang web của khách hàng. Có thông tin đó được ghi vào system.log, exe.log, v.v. và lộn xộn với nhật ký của mọi mô-đun khác là không thực tế.

Câu trả lời:


99

Bạn không cần tùy chỉnh hoặc cố gắng mở rộng đăng nhập của Magento2. Như bạn đã nói, nó sử dụng Monolog chỉ với một chút tùy chỉnh. Nó là đủ để viết logger của riêng bạn mở rộng Monolog với rất ít nỗ lực.

Giả sử mô-đun của bạn nằm trong YourNamespace/YourModule:

1) Viết lớp Logger trong Logger/Logger.php:

<?php
namespace YourNamespace\YourModule\Logger;

class Logger extends \Monolog\Logger
{
}

2) Viết lớp Handler trong Logger/Handler.php:

<?php
namespace YourNamespace\YourModule\Logger;

use Monolog\Logger;

class Handler extends \Magento\Framework\Logger\Handler\Base
{
    /**
     * Logging level
     * @var int
     */
    protected $loggerType = Logger::INFO;

    /**
     * File name
     * @var string
     */
    protected $fileName = '/var/log/myfilename.log';
}

Lưu ý: Đây là bước duy nhất sử dụng mã Magento. \Magento\Framework\Logger\Handler\Basemở rộng Monolog's StreamHandlervà ví dụ: thêm thuộc tính $ fileName với đường dẫn cơ sở Magento.

3) Đăng ký Logger trong Dependency Injection etc/di.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <type name="YourNamespace\YourModule\Logger\Handler">
        <arguments>
            <argument name="filesystem" xsi:type="object">Magento\Framework\Filesystem\Driver\File</argument>
        </arguments>
    </type>
    <type name="YourNamespace\YourModule\Logger\Logger">
        <arguments>
            <argument name="name" xsi:type="string">myLoggerName</argument>
            <argument name="handlers"  xsi:type="array">
                <item name="system" xsi:type="object">YourNamespace\YourModule\Logger\Handler</item>
            </argument>
        </arguments>
    </type>
</config>

Lưu ý: Điều này không bắt buộc, nhưng cho phép DI truyền các đối số cụ thể cho hàm tạo. Nếu bạn không làm bước này, thì bạn cần điều chỉnh hàm tạo để đặt trình xử lý.

4) Sử dụng bộ ghi trong các lớp Magento của bạn:

Điều này được thực hiện bởi Dependency Injection. Dưới đây bạn sẽ tìm thấy một lớp giả chỉ viết một mục nhật ký:

<?php
namespace YourNamespace\YourModule\Model;

class MyModel
{
    /**
     * Logging instance
     * @var \YourNamespace\YourModule\Logger\Logger
     */
    protected $_logger;

    /**
     * Constructor
     * @param \YourNamespace\YourModule\Logger\Logger $logger
     */
    public function __construct(
        \YourNamespace\YourModule\Logger\Logger $logger
    ) {
        $this->_logger = $logger;
    }

    public function doSomething()
    {
        $this->_logger->info('I did something');
    }
}

2
Tôi đã hỏi một cái gì đó tương tự như một trong những kiến ​​trúc sư vào ngày khác, vì vậy cảm ơn vì ví dụ này! Tôi đã tự hỏi về việc thêm hỗ trợ dựa trên tên lớp để khung DI có thể đưa bộ ghi "đúng" vào các lớp khác nhau và có các công tắc trong Quản trị viên để bật / tắt cờ mà không thay đổi mã như thế này. Làm thế nào hữu ích loại chức năng này sẽ được cho mọi người?
Alan Kent

1
Manoj, nếu mẫu mà bạn đang giới thiệu có một lớp khối với logger thì bạn có thể viết một phương thức công khai sau đó chuyển thông điệp đến logger. Ví dụ của bạn sẽ không hoạt động vì _logger được bảo vệ nếu nó tồn tại hoàn toàn
halk

3
Theo tôi, cách tiếp cận hiện tại là một bước lùi so với những gì M1 đã có. Ghi nhật ký cũng phải là một công cụ dành cho nhà phát triển, nó không chỉ có nghĩa là để giám sát một ứng dụng trực tiếp. Tôi có thể thấy một thư viện đơn giản hóa đa mục đích tùy chọn có thể được tạo ra như thế nào để được sử dụng trong quá trình phát triển, vượt qua việc triển khai hiện tại và sau đó được thay thế cho sử dụng sản xuất
barbazul

2
@AlanKent Tôi đồng ý với barbazul ở đây - khả năng dễ dàng đăng nhập vào bất kỳ tệp nào bạn muốn, chỉ định cấp độ nhanh chóng trong M1 là tuyệt vời. Điều này không linh hoạt (năng động) mà là một sự xấu hổ. Sẽ rất tốt nếu có tên tệp làm tham số cho các cuộc gọi logger mặc định. Cảm ơn vì câu trả lời!
Robbie Averill

2
Đối với tôi, nó luôn lấy /var/log/system.log, bất kỳ ý tưởng nào tại sao?
MagePologistso

20

Chúng tôi có thể đăng nhập dữ liệu trong tập tin như thế này.

$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/templog.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);

$logger->info("Info". $product->getSku() . "----- Id  ". $product->getId() );
$logger->info("preorder qty ". $product->getPreorderQty());

2
việc này thật nhanh chóng và dễ dàng
PMB

9

Cách đơn giản nhất có thể:

$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/test.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info('Your text message');

6

Ngoài câu trả lời của Halk và Pradeep Kumar: Nếu thực sự mối quan tâm duy nhất của bạn là đăng nhập vào một tệp khác, có một cách dễ dàng hơn một chút. Đặc biệt nếu bạn muốn kết hợp điều đó với nhiều mô-đun hoặc nếu bạn muốn các tệp nhật ký khác nhau trong mô-đun của mình. Với phương pháp này, bạn không phải tạo trình xử lý tùy chỉnh.

Giả sử mô-đun của bạn nằm trong MyNamespace/MyModulevà lớp mà bạn muốn đăng nhập vào một tệp tùy chỉnh, được gọi MyClass. Nếu hàm tạo của lớp đã tiêm \Psr\Log\LoggerInterfacebỏ qua bước 2). Nếu không, bạn cần phải tiêm nó vào hàm tạo:

1) Tiêm LoggerInterface trong lớp của bạn MyClass.php:

<?php

namespace MyNamespace\MyModule;

use Psr\Log\LoggerInterface;

class MyClass
{
    /**
     * @var \Psr\Log\LoggerInterface
     */
    protected $logger;

    public function __construct(
        LoggerInterface $logger
    ) {
        $this->logger = $logger;
    }
}

Nếu bạn mở rộng một lớp đã bao gồm một logger (như \Magento\Framework\App\Helper\AbstractHelper), bạn cũng có thể ghi đè lên thành viên đó (thường $_logger) thay vì sử dụng một lớp riêng biệt. Đơn giản chỉ cần thêm $this->_logger = $logger sau khi chỉ thị cha mẹ xây dựng.

<?php

namespace MyNamespace\MyModule;

use Magento\Framework\App\Helper\Context;
use Psr\Log\LoggerInterface;

class MyClass extends \Magento\Framework\App\Helper\AbstractHelper
{
    public function __construct(
        Context $context,
        LoggerInterface $logger
    ) {
        parent::__construct(
            $context
        );

        $this->_logger = $logger;
    }
}

2) Cấu hình logger thông qua tiêm phụ thuộc etc/di.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <virtualType name="MyNamespace\MyModule\Logger\Handler" type="Magento\Framework\Logger\Handler\Base">
        <arguments>
            <argument name="filesystem" xsi:type="object">Magento\Framework\Filesystem\Driver\File</argument>
            <argument name="fileName" xsi:type="string">/var/log/mymodule.log</argument>
        </arguments>
    </virtualType>
    <virtualType name="MyNamespace\MyModule\Logger\Logger" type="Magento\Framework\Logger\Monolog">
        <arguments>
            <argument name="name" xsi:type="string">MyModule Logger</argument>
            <argument name="handlers" xsi:type="array">
                <item name="system" xsi:type="object">MyNamespace\MyModule\Logger\Handler</item>
            </argument>
        </arguments>
    </virtualType>

    <type name="MyNamespace\MyModule\MyClass">
        <arguments>
            <argument name="logger" xsi:type="object">MyNamespace\MyModule\Logger\Logger</argument>
        </arguments>
    </type>
</config>

Điều này sẽ đăng nhập mọi thứ để /var/log/mymodule.log.

Nếu bạn cần đăng nhập vào một tệp khác cho một lớp khác, bạn có thể chỉ cần tạo một trình ghi nhật ký ảo khác với một trình xử lý ảo khác và đưa nó vào lớp đó.


5

Nếu bạn chỉ cần nó trong lớp duy nhất của bạn:

public function __construct(\Psr\Log\LoggerInterface $logger, \Magento\Framework\App\Filesystem\DirectoryList $dir) 
{
    $this->logger = $logger;
    $this->dir = $dir;

    $this->logger->pushHandler(new \Monolog\Handler\StreamHandler($this->dir->getRoot().'/var/log/custom.log'));
}

PushHandler không được hiển thị phương thức trên giao diện và việc triển khai dường như không hoạt động ...
George

Phiên bản Magento của bạn?
mshakeel

Magento CE 2.2.0
George

Tôi sẽ thử nó trên CE 2.2.0 và lấy lại cho bạn. Tôi đã sử dụng nó vào ngày 2.1
mshakeel

2

Hãy thử mô-đun " Praxigento / mage2_ext_logging ". Mô-đun này thêm hỗ trợ "Monolog Cascade" cho Magento 2. "Monolog Cascade" cho phép bạn định cấu hình đầu ra đăng nhập với tệp cấu hình duy nhất. Bạn có thể in nhật ký của mình ra các tệp, cơ sở dữ liệu khác nhau, gửi thông báo qua email và vv mà không cần sửa đổi mã của riêng bạn.

Đây là một mẫu của tệp cấu hình ('var / log / log.yaml' theo mặc định):

disable_existing_loggers: true
formatters:
    dashed:
        class: Monolog\Formatter\LineFormatter
        format: "%datetime%-%channel%.%level_name% - %message%\n"
handlers:
    debug:
        class: Monolog\Handler\StreamHandler
        level: DEBUG
        formatter: dashed
        stream: /.../var/log/cascade_debug.log
    system:
        class: Monolog\Handler\StreamHandler
        level: INFO
        formatter: dashed
        stream: /.../var/log/cascade_system.log
    exception:
        class: Monolog\Handler\StreamHandler
        level: EMERGENCY
        formatter: dashed
        stream: /.../log/cascade_exception.log
processors:
    web_processor:
        class: Monolog\Processor\WebProcessor
loggers:
    main:
        handlers: [debug, system, exception]
        processors: [web_processor]

1

Nếu không có thay đổi logic và chỉ cần thay đổi tên tệp nhật ký tùy chỉnh thì không cần tạo lớp logger tùy chỉnh cũng chỉ cần làm theo các bước dưới đây

1. trong di.xml

 <type name="Magento\Framework\Logger\Monolog">
        <arguments>
            <argument name="name" xsi:type="string">test</argument>
            <argument name="handlers"  xsi:type="array">
                <item name="test" xsi:type="object">NAME_SPACE\Test\Model\Logger\Handler\Debug</item>
            </argument>
        </arguments>
    </type>

2. Xử lý

<?php
/**
 * Copyright © 2017 Alshaya, LLC. All rights reserved.
 * See LICENSE.txt for license details.
 *
 */
namespace NAME_SPACE\Test\Model\Logger\Handler;

use Magento\Framework\Logger\Handler\Base;

/**
 * Log handler for reports
 */
class Debug extends Base
{
    /**
     * @var string
     */
    protected $fileName = '/var/log/test.log';
}

bất cứ khi nào bạn cần để ghi nhật ký dữ liệu bạn cần gọi nhật ký PSR mặc định
đó là

<?php
/**
 *
 * Copyright © 2013-2017 Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace NAME_SPACE\Test\Controller\Index;

use Psr\Log\LoggerInterface;
class Index extends \Magento\Framework\App\Action\Action
{


    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * Show Contact Us page
     *
     * @return void
     */


    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        LoggerInterface $logger
    ) {
        parent::__construct($context);
        $this->logger = $logger;
    }


    public function execute()
    {
        $this->logger->critical((string) 'Test');
        $this->_view->loadLayout();
        $this->_view->renderLayout();
    }
}

vì vậy, ví dụ trên sẽ ghi nhật ký tất cả dữ liệu gỡ lỗi vào test.log nếu bạn cần thay đổi hệ thống, bạn có thể thêm dòng dưới đây vào di.xml


0

Tôi đã thử mã bên dưới logger này trong mô-đun của bên thứ ba nơi tôi muốn lấy thông tin nhật ký ở đó tôi đã đặt và đưa chúng vào tệp custom.log, kiểm tra mã này, bạn chắc chắn nhận được nhật ký vào tệp nhật ký tùy chỉnh của mình.

$writer = new \Zend\Log\Writer\Stream(BP . '/var/log/custom.log');
$logger = new \Zend\Log\Logger();
$logger->addWriter($writer);
$logger->info('Your log details: ' .$variable);

Nếu bạn cần thêm thông tin bình luận ở đây, tôi sẽ trả lời. Cảm ơn bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.