Bagaimana cara membuat file Log kustom di Magento 2?

57

Di Magento 1, adalah umum untuk mengelompokkan log ke dalam file yang berbeda (untuk memisahkan log untuk metode pembayaran, dll.). Itu semudah mengubah $fileparameter Mage::log.

Magento 2 telah berubah untuk menggunakan Monolog.

Tampaknya Monolog (atau implementasi Magento2) mengelompokkan semua log untuk seluruh kerangka kerja ke penangan berdasarkan tingkat keparahannya. Ada beberapa penangan yang menulis ke file:

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

Masuk ke masing-masing file di var / log seperti di Magento 1.

Saya bisa menambahkan handler untuk keparahan tertentu (yaitu, menulis pemberitahuan var/log/notice.log). Perpanjang \Magento\Framework\Logger\Handler\Base, dan daftarkan pawang masuk di.xml.

Artikel ini secara kasar menjelaskan proses itu: http://semaphoresoftware.kinja.com/how-to-create-a-custom-log-in-magento-2-1704130912

Tetapi bagaimana cara saya menulis semua log (bukan hanya satu keparahan) untuk satu kelas (tidak semua Magento) ke file pilihan saya?

Sepertinya saya harus membuat versi saya sendiri Magento\Framework\Logger\Monolog, tetapi kemudian bagaimana semuanya cocok agar itu benar-benar berfungsi?

Jika ini adalah no-no besar di Magento 2, lalu apa alternatifnya? Saya ingin sesuatu untuk memisahkan log untuk ekstensi ini untuk keperluan debugging ketika diperlukan di situs klien. Memiliki info yang ditulis ke system.log, exception.log, dll. Dan campur aduk dengan log dari setiap modul lainnya tidak praktis.

Ryan Hoerr
sumber

Jawaban:

101

Anda tidak perlu menyesuaikan atau mencoba untuk memperpanjang logging Magento2. Seperti yang Anda katakan itu menggunakan Monolog dengan hanya sedikit penyesuaian. Cukup menulis logger Anda sendiri yang memperluas Monolog dengan sedikit usaha.

Dengan asumsi modul Anda ada di YourNamespace/YourModule:

1) Tulis kelas Logger di Logger/Logger.php:

<?php
namespace YourNamespace\YourModule\Logger;

class Logger extends \Monolog\Logger
{
}

2) Tulis kelas Handler di 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';
}

Catatan: Ini adalah satu-satunya langkah yang menggunakan kode Magento. \Magento\Framework\Logger\Handler\Basemeluas Monolog StreamHandlerdan eg menambahkan atribut $ fileName dengan jalur dasar Magento.

3) Daftar Logger di Injeksi Ketergantungan 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>

Catatan: Ini tidak sepenuhnya diperlukan tetapi memungkinkan DI untuk memberikan argumen spesifik kepada konstruktor. Jika Anda tidak melakukan langkah ini, maka Anda perlu menyesuaikan konstruktor untuk mengatur pawang.

4) Gunakan logger di kelas Magento Anda:

Ini dilakukan oleh Dependency Injection. Di bawah ini Anda akan menemukan kelas dummy yang hanya menulis entri log:

<?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');
    }
}
halk
sumber
2
Saya meminta sesuatu yang mirip dengan salah satu arsitek tempo hari, jadi terima kasih untuk contoh ini! Saya bertanya-tanya tentang menambahkan dukungan berdasarkan nama kelas sehingga kerangka kerja DI dapat menyuntikkan logger "kanan" ke kelas yang berbeda, dan memiliki saklar di Admin untuk mengaktifkan / menonaktifkan bendera tanpa perubahan kode seperti ini. Seberapa berguna fungsi semacam ini bagi orang-orang?
Alan Kent
1
Manoj, jika templat yang Anda maksud memiliki kelas blok dengan logger maka Anda dapat menulis metode publik yang kemudian meneruskan pesan ke logger. Contoh Anda tidak akan berfungsi karena _logger dilindungi jika ada sama sekali
halk
3
Menurut pendapat saya, pendekatan saat ini adalah langkah mundur dari apa yang dimiliki M1. Penebangan juga harus menjadi alat pengembang, tidak hanya dimaksudkan untuk memonitor aplikasi langsung. Saya dapat melihat bagaimana sebuah perpustakaan multi-tujuan opsional yang disederhanakan dapat dibuat untuk digunakan dalam pengembangan yang mengesampingkan implementasi saat ini dan kemudian diganti untuk penggunaan produksi
barbazul
2
@AlanKent Saya setuju dengan barbazul di sini - kemampuan untuk dengan mudah login ke file mana pun yang Anda inginkan, menentukan level dengan cepat di M1 sangat bagus. Ini tidak sefleksibel (secara dinamis) yang memalukan. Akan lebih baik untuk memiliki nama file sebagai parameter untuk panggilan logger default. Terima kasih atas jawabannya halk!
Robbie Averill
2
Bagi saya selalu menggunakan /var/log/system.log, ada ide mengapa?
MagePsycho
20

Kita bisa mencatat data dalam file seperti ini.

$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());
Pramod Kharade
sumber
2
ini cepat dan mudah
PMB
9

Cara sesederhana mungkin:

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

Selain jawaban Halk dan Pradeep Kumar: Jika memang satu-satunya masalah Anda adalah masuk ke file lain, ada cara yang sedikit lebih mudah. Terutama jika Anda ingin memasukkannya ke beberapa modul atau jika Anda ingin file log yang berbeda dalam modul Anda. Dengan metode ini, Anda tidak perlu membuat penangan khusus.

Dengan asumsi modul Anda ada di dalam MyNamespace/MyModuledan kelas, yang ingin Anda log masuk ke file kustom, dipanggil MyClass. Jika konstruktor dari kelas sudah menyuntikkan \Psr\Log\LoggerInterfacelompat ke langkah 2). Kalau tidak, Anda perlu menyuntikkannya di konstruktor:

1) Suntikkan LoggerInterface di kelas Anda 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;
    }
}

Jika Anda menambah kelas yang sudah menyertakan logger (seperti \Magento\Framework\App\Helper\AbstractHelper), Anda mungkin juga akan menimpa anggota itu (biasanya $_logger) alih-alih menggunakan yang terpisah. Cukup tambahkan $this->_logger = $logger setelah arahan konstruktor induk.

<?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) Konfigurasikan logger melalui injeksi ketergantungan 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>

Ini akan mencatat semuanya /var/log/mymodule.log.

Jika Anda perlu masuk ke file yang berbeda untuk kelas yang berbeda, Anda bisa membuat virtual logger lain dengan handler virtual lain dan menyuntikkannya ke kelas itu.

T. Dreiling
sumber
5

Jika Anda membutuhkannya dalam satu kelas saja:

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'));
}
mshakeel
sumber
pushHandler tidak mengekspos metode pada antarmuka dan implementasinya tampaknya tidak berfungsi ...
George
Versi Magento Anda?
mshakeel
Magento CE 2.2.0
George
Saya akan mencobanya pada CE 2.2.0 dan kembali kepada Anda. Saya telah menggunakannya pada 2.1
mshakeel
2

Coba modul " praxigento / mage2_ext_logging ". Modul ini menambahkan dukungan "Monolog Cascade" ke Magento 2. "Monolog Cascade" memungkinkan Anda mengkonfigurasi output logging dengan file konfigurasi tunggal. Anda dapat mencetak log ke file yang berbeda, database, mengirim peringatan email dan lain-lain tanpa modifikasi kode Anda sendiri.

Ini adalah contoh file konfigurasi ('var / log / logging.yaml' secara default):

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]
Alex Gusev
sumber
1

Jika tidak ada perubahan logika dan hanya perlu mengubah nama file log kustom maka tidak perlu membuat kelas logger kustom juga cukup ikuti langkah-langkah di bawah ini

1. di 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. Penangan

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

dimanapun Anda perlu untuk login data yang Anda butuhkan untuk memanggil log PSR default
itu

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

jadi contoh di atas akan mencatat semua data debug ke test.log jika Anda perlu mengubah sistem juga Anda dapat menambahkan baris di bawah ini di.xml

Pradeep Kumar
sumber
0

Saya mencoba ini di bawah kode objek logger dalam modul pihak ketiga di mana saya ingin mendapatkan info log di sana saya menempatkan dan memasukkannya ke file custom.log, periksa kode ini, Anda pasti mendapatkan log ke file log kustom Anda.

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

Jika Anda memerlukan komentar informasi lebih lanjut di sini, saya akan menjawab. Terima kasih.

Jdprasad V
sumber