วิธีสร้างไฟล์บันทึกที่กำหนดเองใน Magento 2


57

ใน Magento 1 เป็นเรื่องปกติที่จะแบ่งเซ็กเมนต์บันทึกเป็นไฟล์ต่าง ๆ (เพื่อแยกบันทึกสำหรับวิธีการชำระเงิน ฯลฯ ) นั่นเป็นเรื่องง่ายเหมือนการเปลี่ยนพารามิเตอร์ของ$fileMage::log

Magento 2 ได้เปลี่ยนไปใช้ Monolog

ปรากฏว่า Monolog (หรือการใช้งานของ Magento2) จัดกลุ่มบันทึกทั้งหมดสำหรับกรอบทั้งหมดเพื่อจัดการโดยความรุนแรง มีตัวจัดการสองสามตัวที่เขียนไปยังไฟล์:

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

การบันทึกไฟล์ตามลำดับในvar / logเช่นเดียวกับ Magento 1

ฉันสามารถเพิ่มตัวจัดการสำหรับความรุนแรงโดยเฉพาะ (IE, เขียนประกาศvar/log/notice.log) ขยายและลงทะเบียนในการจัดการ\Magento\Framework\Logger\Handler\Basedi.xml

บทความนี้อธิบายกระบวนการอย่างคร่าว ๆ : http://semaphoresoftware.kinja.com/how-to-create-a-custom-log-in-magento-2-1704130912

แต่ฉันจะไปเกี่ยวกับการเขียนบันทึกทั้งหมด (ไม่เพียงแค่ความรุนแรงเพียงอย่างเดียว) สำหรับหนึ่งคลาส (ไม่ใช่ Magento ทั้งหมด) ไปยังไฟล์ที่ฉันเลือกได้อย่างไร

ดูเหมือนว่าฉันจะต้องสร้างเวอร์ชันของตัวเองMagento\Framework\Logger\Monologแต่แล้วทุกอย่างเข้ากันได้อย่างไรเพื่อให้ใช้งานได้จริง

หากนี่เป็นเกม no-no ที่ยิ่งใหญ่ใน Magento 2 แล้วทางเลือกคืออะไร? ฉันต้องการบางสิ่งบางอย่างเพื่อแยกบันทึกสำหรับส่วนขยายนี้เพื่อจุดประสงค์ในการดีบั๊กเมื่อจำเป็นในเว็บไซต์ของลูกค้า การมีข้อมูลนั้นถูกเขียนไปยัง system.log, exception.log และอื่น ๆ ที่มีการบันทึกในโมดูลอื่น ๆ นั้นไม่สามารถนำไปใช้ได้จริง

คำตอบ:


99

คุณไม่จำเป็นต้องปรับแต่งเองหรือพยายามขยายการบันทึกของ Magento2 อย่างที่คุณบอกว่ามันใช้ Monolog ด้วยการปรับแต่งเล็กน้อยเท่านั้น มันก็เพียงพอแล้วที่จะเขียนคนตัดไม้ของคุณเองขยาย Monolog ด้วยความพยายามน้อยมาก

สมมติว่าโมดูลของคุณอยู่ในYourNamespace/YourModule:

1) เขียนคลาส Logger ในLogger/Logger.php:

<?php
namespace YourNamespace\YourModule\Logger;

class Logger extends \Monolog\Logger
{
}

2) เขียนคลาส Handler ใน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';
}

หมายเหตุ: นี่เป็นขั้นตอนเดียวที่ใช้รหัสวีโอไอพี \Magento\Framework\Logger\Handler\Baseขยาย Monolog's StreamHandlerและเช่นเพิ่มแอตทริบิวต์ $ fileName ด้วยพา ธ ฐาน Magento

3) ลงทะเบียน Logger ในการฉีดพึ่งพา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>

หมายเหตุ: สิ่งนี้ไม่จำเป็นอย่างเคร่งครัด แต่อนุญาตให้ DI ส่งอาร์กิวเมนต์เฉพาะไปยังตัวสร้าง หากคุณไม่ทำตามขั้นตอนนี้คุณต้องปรับ Constructor เพื่อตั้งค่าตัวจัดการ

4) ใช้ตัวบันทึกในคลาส Magento ของคุณ:

สิ่งนี้ทำได้โดยการพึ่งพาการฉีด ด้านล่างคุณจะพบคลาส dummy ซึ่งเขียนรายการบันทึกเท่านั้น:

<?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
ฉันถามสิ่งที่คล้ายกับสถาปนิกคนหนึ่งในวันก่อนดังนั้นขอขอบคุณสำหรับตัวอย่างนี้! ฉันสงสัยเกี่ยวกับการเพิ่มการสนับสนุนตามชื่อคลาสดังนั้น DI Framework สามารถแทรกตัวบันทึก "ขวา" ไปยังคลาสอื่นและมีสวิตช์ใน Admin เพื่อเปิด / ปิดแฟล็กโดยไม่ต้องมีการเปลี่ยนแปลงโค้ดในลักษณะนี้ การทำงานแบบนี้มีประโยชน์ต่อผู้คนอย่างไร
Alan Kent

1
มาโนจถ้าเทมเพลตที่คุณอ้างถึงมีคลาสบล็อกที่มีคนตัดไม้คุณสามารถเขียนวิธีสาธารณะซึ่งจะส่งข้อความไปยังคนตัดไม้ ตัวอย่างของคุณจะไม่ทำงานเนื่องจาก _logger ได้รับการปกป้องหากมีอยู่จริง
halk

3
ในความคิดของฉันวิธีการในปัจจุบันเป็นขั้นตอนกลับจากสิ่งที่ M1 มี การบันทึกควรเป็นเครื่องมือสำหรับนักพัฒนาซึ่งไม่ได้มีไว้สำหรับการตรวจสอบแอปพลิเคชันที่ใช้งานจริงเท่านั้น ฉันสามารถดูได้ว่าสามารถสร้างไลบรารีแบบง่ายเอนกประสงค์ซึ่งเป็นทางเลือกสำหรับการใช้ในการพัฒนาเกี่ยวกับการนำไปปฏิบัติในปัจจุบันแล้วนำไปใช้แทนการผลิตได้
barbazul

2
@ AlanKent ฉันเห็นด้วยกับ barbazul ที่นี่ - ความสามารถในการเข้าสู่ไฟล์ที่คุณต้องการได้อย่างง่ายดายระบุระดับอย่างรวดเร็วใน M1 นั้นยอดเยี่ยม นี่ไม่ใช่ความยืดหยุ่น (แบบไดนามิก) ซึ่งเป็นความอัปยศ จะเป็นการดีถ้ามีชื่อไฟล์เป็นพารามิเตอร์สำหรับการเรียกตัวบันทึกค่าเริ่มต้น ขอบคุณสำหรับคำตอบ!
Robbie Averill

2
สำหรับฉันแล้วการใช้ /var/log/system.log ความคิดอะไรอยู่เสมอ
MagePsycho

20

เราสามารถบันทึกข้อมูลในไฟล์เช่นนี้

$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
นี่เป็นเรื่องง่ายและรวดเร็ว
PMB

9

วิธีที่ง่ายที่สุดที่เป็นไปได้:

$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

นอกเหนือจากคำตอบของ Halk และ Pradeep Kumar: หากข้อกังวลเดียวของคุณคือการเข้าสู่ไฟล์ที่แตกต่างนั่นเป็นวิธีที่ง่ายกว่าเล็กน้อย โดยเฉพาะอย่างยิ่งถ้าคุณต้องการที่จะรวมที่หลายโมดูลหรือถ้าคุณต้องการไฟล์บันทึกที่แตกต่างกันภายในโมดูลของคุณ ด้วยวิธีนี้คุณไม่ต้องสร้างตัวจัดการแบบกำหนดเอง

สมมติว่าโมดูลของคุณอยู่ในและชั้นที่คุณต้องการเข้าสู่ระบบไปยังไฟล์ที่กำหนดเองที่เรียกว่าMyNamespace/MyModule MyClassหากนวกรรมิกของคลาส injects \Psr\Log\LoggerInterfaceข้ามไปที่ขั้นตอนที่ 2) มิฉะนั้นคุณจะต้องฉีดมันในตัวสร้าง:

1) Inject LoggerInterface ในชั้นเรียนของคุณ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;
    }
}

หากคุณขยายคลาสที่มีตัวบันทึก (เช่น\Magento\Framework\App\Helper\AbstractHelper) คุณอาจเขียนทับสมาชิกนั้น (โดยปกติ$_logger) แทนการใช้คลาสแยก เพียงแค่เพิ่ม$this->_logger = $logger หลังจากคำสั่งปกครองคอนสตรัค

<?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) กำหนดค่าตัวบันทึกผ่านการฉีดพึ่งพา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>

/var/log/mymodule.logนี้จะเข้าสู่ระบบทุกอย่างเพื่อ

หากคุณต้องการเข้าสู่ไฟล์ที่แตกต่างกันสำหรับคลาสอื่นคุณสามารถสร้างตัวบันทึกเสมือนอีกตัวโดยใช้ตัวจัดการเสมือนตัวอื่นแล้วอัดเข้าไปในคลาสนั้น


5

หากคุณต้องการภายในชั้นเดียวของคุณเท่านั้น:

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 ไม่ได้เปิดเผยวิธีการบนส่วนต่อประสานและดูเหมือนว่าการติดตั้งจะไม่ทำงาน ...
George

เวอร์ชั่นวีโอไอพีของคุณ?
mshakeel

Magento CE 2.2.0
จอร์จ

ฉันจะลองใช้ CE 2.2.0 แล้วติดต่อกลับหาคุณ ฉันใช้มันในวันที่ 2.1
mshakeel

2

ลองใช้โมดูล " praxigento / mage2_ext_logging " โมดูลนี้เพิ่มการสนับสนุน "Monolog Cascade" ให้กับ Magento 2 "Monolog Cascade" ช่วยให้คุณสามารถกำหนดค่าการบันทึกผลลัพธ์ด้วยไฟล์กำหนดค่าเดียว คุณสามารถพิมพ์บันทึกของคุณไปยังไฟล์ฐานข้อมูลส่งอีเมลแจ้งเตือนและอื่น ๆ โดยไม่ต้องแก้ไขรหัสของคุณเอง

นี่เป็นตัวอย่างของไฟล์กำหนดค่า ('var / log / logging.yaml' โดยค่าเริ่มต้น):

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

หากไม่มีการเปลี่ยนแปลงเชิงตรรกะและจำเป็นต้องเปลี่ยนชื่อไฟล์บันทึกที่กำหนดเองเท่านั้นไม่จำเป็นต้องสร้างคลาสตัวบันทึกที่กำหนดเองเพียงแค่ทำตามขั้นตอนด้านล่าง

1. ใน 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. ผู้ดูแล

<?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';
}

ไม่ว่าคุณจะต้องการบันทึกข้อมูลที่คุณต้องการเรียกใช้บันทึก PSR เริ่มต้นหรือ
ไม่

<?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();
    }
}

ตัวอย่างข้างต้นจะบันทึกข้อมูลการดีบักทั้งหมดไปที่ test.log หากคุณต้องการเปลี่ยนระบบและคุณสามารถเพิ่มบรรทัดด้านล่างใน di.xml


0

ฉันลองใช้โค้ดวัตถุตัวตัดบันทึกด้านล่างในโมดูลบุคคลที่สามที่ฉันต้องการรับข้อมูลบันทึกที่นั่นและวางลงในไฟล์ custom.log ตรวจสอบรหัสนี้คุณจะได้รับบันทึกลงในไฟล์บันทึกที่กำหนดเองของคุณอย่างแน่นอน

$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);

หากคุณต้องการข้อมูลเพิ่มเติมเกี่ยวกับความคิดเห็นที่นี่ฉันจะตอบกลับ ขอขอบคุณ.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.