定制 brianhenryie/bh-wp-logger 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

brianhenryie/bh-wp-logger

Composer 安装命令:

composer require brianhenryie/bh-wp-logger

包简介

A PSR logger for WordPress plugins, with a nice WP_List_Table UI.

README 文档

README

PHP WordPress tested 6.9 PHPCS WPCS PHPUnit PHPStan

BH WP Logger

Zero-config logger UI for WordPress plugins.

$logger = Logger::instance();

Wraps existing PSR-3 loggers and adds some UI.

Uses Monolog by default, WC_Logger when specified, NullLogger when log level is set to "none".

Uses PHP's set_error_handler() to catch PHP deprecated/warning/notice/errors.

Hook into WordPress's deprecated function hooks (deprecated_function_run etc.) to log those only once per day.

Uses PHP's register_shutdown_function() to catch Exceptions related to the plugin.

Deletes log files older than 30 days on cron.

Records a full backtrace on errors. Records two steps of backtrace on every log when the level is Debug.

UI

Displays logs in WP_List_Table.

Logs WP_List_Table

Shows a dismissible admin error notice each time there is a new error.

Admin Error Notice

Adds a link to the logs view on the plugin's entry on plugins.php.

Plugins page logs link

When log messages contain `wp_user:123` (NB: surrounded by single backticks) it will be replaced with a link to the user profile. This allows for logging useful references to users without logging their PII.

Similarly, any post type can be linked with `post_type_name:123`, e.g. `shop_order:123` will link to the WooCommerce order.

Links in log message

Use

Composer

composer require brianhenryie/bh-wp-logger

Expect breaking changes with every release until v1.0.0.

Instantiate

You should use brianhenryie/strauss to prefix the library's namespace. Then Strauss's autoloader will include the files for you.

The following will work, but it will be faster and more reliable to provide the settings:

$logger = Logger::instance();

Provide the settings:

$logger_settings = new class() implements BrianHenryIE\WP_Logger\API\Logger_Settings_Interface {
    use BrianHenryIE\WP_Logger\Logger_Settings_Trait;
    
	public function get_log_level(): string {
		return LogLevel::INFO;
	}

	// This is used in admin notices.
	public function get_plugin_name(): string {
		return "My Plugin Name";
	}

	// This is used in option names and URLs.
	public function get_plugin_slug(): string {
		return "my-plugin-name";
	}

	// This is needed for the plugins.php logs link.
	public function get_plugin_basename(): string {
		return "my-plugin-name/my-plugin-name.php";
	}
};
$logger = Logger::instance( $logger_settings );

Then pass around your $logger instance.

After the logger has been instantiated once, subsequent calls to ::instance() return the existing instance and any $logger_settings passed is ignored.

To use WooCommerce's native WC_Logger, use the WooCommerce_Logger_Interface interface (which just extends Logger_Settings_Interface) on the settings object.

$logger_settings = new class() implements BrianHenryIE\WP_Logger\WooCommerce\WooCommerce_Logger_Settings_Interface {
    ...

WooCommerce Settings

Something like this can be used for WooCommerce Settings API.

$log_levels        = array( 'none', LogLevel::ERROR, LogLevel::WARNING, LogLevel::NOTICE, LogLevel::INFO, LogLevel::DEBUG );
$log_levels_option = array();
foreach ( $log_levels as $log_level ) {
    $log_levels_option[ $log_level ] = ucfirst( $log_level );
}

$setting_fields[] = array(
    'title'    => __( 'Log Level', 'text-domain' ),
    'label'    => __( 'Enable Logging', 'text-domain' ),
    'type'     => 'select',
    'options'  => $log_levels_option,
    'desc'    => __( 'Increasingly detailed levels of logs. ', 'text-domain' ) . '<a href="' . admin_url( 'admin.php?page=plugin-slug-logs' ) . '">View Logs</a>',
    'desc_tip' => false,
    'default'  => 'notice',
    'id'       => 'text-domain-log-level',
);

WooCommerce Settings

Filters

Two filters are present, to modify the log data as it is being saved, and to modify the log data as it is being presented.

E.g. change the log level for specific log messages:

/**
 * Modify the log data array or return null to cancel logging this entry.
 * The library php-http/logger-plugin is using INFO for detailed logging, let's change that to DEBUG.
 *
 * @hooked {$plugin_slug}_bh_wp_logger_log
 * 
 * @pararm array{level:string,message:string,context:array} $log_data
 * @param Logger_Settings_Interface $settings
 * @param BH_WP_PSR_Logger $bh_wp_psr_logger
 */
function modify_log_data( array $log_data, \BrianHenryIE\WP_Logger\Logger_Settings_Interface $settings, \BrianHenryIE\WP_Logger\API\BH_WP_PSR_Logger $bh_wp_psr_logger): ?array {
    
    if ( 0 === strpos( $log_data['message'], 'Sending request' ) ) {
        $log_data['level'] = LogLevel::DEBUG;
    }

    return $log_data;
}
add_filter( "{$plugin_slug}_bh_wp_logger_log", 'modify_log_data', 10, 3 );

E.g. turn text in logs into hyperlinks as it is being displayed in the logs table:

/**
 * Update ` `wc_order:123` ` with links to the order.
 * Use preg_replace_callback to find and replace all instances in the string.
 *
 * @hooked {$plugin_slug}_bh_wp_logger_column
 *
 * @param string                                                          $column_output The column output so far.
 * @param array{time:string, level:string, message:string, context:array} $item The log entry row.
 * @param string                                                          $column_name The current column name.
 * @param Logger_Settings_Interface                                       $logger_settings The logger settings.
 * @param BH_WP_PSR_Logger                                                $bh_wp_psr_logger The logger API instance.
 *
 * @return string
 */
function replace_wc_order_id_with_link( string $column_output, array $item, string $column_name,\BrianHenryIE\WP_Logger\Logger_Settings_Interface $logger_settings, \BrianHenryIE\WP_Logger\API\BH_WP_PSR_Logger $bh_wp_psr_logger ): string {

    if ( 'message' !== $column_name ) {
        return $column_output;
    }

    $callback = function( array $matches ): string {

        $url  = admin_url( "post.php?post={$matches[1]}&action=edit" );
        $link = "<a href=\"{$url}\">Order {$matches[1]}</a>";

        return $link;
    };

    $message = preg_replace_callback( '/`wc_order:(\d+)`/', $callback, $column_output ) ?? $column_output;

    return $message;
}
add_filter( "{$plugin_slug}_bh_wp_logger_column", 'replace_wc_order_id_with_link', 10, 5 );

WP_Mock

If using WP_Mock for your tests, and you are instantiating this logger, the following should help:

\Patchwork\redefine(
    array( Logger::class, '__construct' ),
    function( $settings ) {}
);

Test Plugin

The development-plugin folder contains a small plugin with buttons to trigger the types of errors that can be logged.

Test Plugin

Best Practice

From my limited logging experience, I find it useful to add a debug log at the beginning of functions and an appropriate info...error as the function returns.

TODO

  • Check log directory is not publicly accessible
  • Check uploads dir chmod (is writable). => see brianhenryie/bh-wp-private-uploads
  • Add current user to context
  • Don't log empty context (WC)
  • Option for what level of errors to display as admin notices
  • Option for user capability for displaying admin notices (filter, at least)
  • Zero-config WC_Logger: detect "wc", "woo" in plugin names
  • Use Code prettify on the context json : Used caldwell/renderjson
  • Paging and filtering
  • Hyperlinks in messages
  • Record timestamp the logs were last viewed at, make the plugins.php link bold if new logs are present.
  • Auto-delete old logs
  • Log notice should dismiss when the log page is visited
  • Redact sensitive data. e.g. use userid:123 in the saved logs and replace it with richer data when displaying them
  • Add errors to dashboard Site Health widget
  • Ensure output is properly escaped

Minor concerns:

  • Debug logging could maybe be moved to a shutdown handler
  • Transients to suppress duplicate logs might be inefficient

Status

To date I think it has been used mostly by me, i.e. internal projects. There are no egregious issues. It should work for everyone but I would like some feedback from others on how well it works for you.

I'll start at Semver 1.0.0 once I've caught up with WPCS ✅, PhpStan ✅ and PhpUnit. There's about 65 tests and 43% coverage. WPCS + PHPStan are both pretty good now 100%.

I think that's higher code-quality than most WordPress plugins.

brianhenryie/bh-wp-logger 适用场景与选型建议

brianhenryie/bh-wp-logger 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 19.81k 次下载、GitHub Stars 达 19, 最近一次更新时间为 2024 年 04 月 20 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 brianhenryie/bh-wp-logger 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 brianhenryie/bh-wp-logger 我们能提供哪些服务?
定制开发 / 二次开发

基于 brianhenryie/bh-wp-logger 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 19.81k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 19
  • 点击次数: 16
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 19
  • Watchers: 2
  • Forks: 3
  • 开发语言: PHP

其他信息

  • 授权协议: GPL-2.0-or-later
  • 更新时间: 2024-04-20