-
Notifications
You must be signed in to change notification settings - Fork 0
05 Advanced Topics
This section covers more complex usage patterns, customization, and best practices for production environments.
A powerful feature of the library is the ability to route different logs to different handlers. You can combine multiple handlers, each configured for specific channels or severity levels, to create a sophisticated logging strategy.
Imagine you have a plugin that processes payments and interacts with an external API. Your logging requirements are:
- Log all events to a file for general debugging.
- Log all payment and API events to the database for auditing.
- Receive an email notification only for critical errors related to payments.
<?php
global $wpdb;
use Psr\Log\LogLevel;
use WPTechnix\WP_Simple_Logger\Manager;
use WPTechnix\WP_Simple_Logger\Handlers\File_Handler;
use WPTechnix\WP_Simple_Logger\Handlers\Database_Handler;
use WPTechnix\WP_Simple_Logger\Handlers\Email_Handler;
$manager = new Manager();
// Handler 1: Log everything to a file.
$file_handler = new File_Handler( WP_CONTENT_DIR . '/logs/full_app.log' );
$manager->add_handler( $file_handler ); // No channel or level restriction.
// Handler 2: Log 'payments' and 'api' channels to the database.
$db_handler = new Database_Handler( $wpdb->prefix . 'app_logs' );
$db_handler->set_channels( ['payments', 'api'] ); // Restrict to specific channels.
$manager->add_handler( $db_handler );
// Handler 3: Email only critical errors from the 'payments' channel.
$email_handler = new Email_Handler(
'[email protected]',
'Critical Payment Error',
LogLevel::CRITICAL // Only handles CRITICAL level and higher.
);
$email_handler->set_channels( ['payments'] ); // Only handles the 'payments' channel.
$manager->add_handler($email_handler);
// Initialize the manager to register all hooks.
$manager->init();
// --- Usage Example ---
$payment_logger = $manager->get_logger('payments');
$api_logger = $manager->get_logger('api');
$general_logger = $manager->get_logger('general');
// This goes to File and Database.
$payment_logger->info('Payment initiated.', ['order_id' => 123]);
// This goes to File only.
$general_logger->debug('User session started.');
// This goes to File, Database, AND Email.
$payment_logger->critical('Payment gateway timeout!', ['gateway' => 'Stripe']);The library is designed to be extended. You can easily create your own handlers and formatters by implementing the provided interfaces.
To create a custom handler (e.g., to send logs to Slack), you should extend Abstract_Handler to get level-checking, channel filtering, and formatter logic for free.
- Create a class that extends
\WPTechnix\WP_Simple_Logger\Handlers\Abstract_Handler. - Implement the
handle(Log_Entry $entry)andflush()methods.
<?php
use WPTechnix\WP_Simple_Logger\Handlers\Abstract_Handler;
use WPTechnix\WP_Simple_Logger\Log_Entry;
use WPTechnix\WP_Simple_Logger\Formatters\Line_Formatter;
use Psr\Log\LogLevel;
class Slack_Handler extends Abstract_Handler {
private string $webhook_url;
private array $buffer = [];
public function __construct(string $webhook_url, string $min_level = LogLevel::ERROR) {
parent::__construct($min_level);
$this->webhook_url = $webhook_url;
// Use a simple, clean formatter by default for Slack messages.
if (null === $this->formatter) {
$this->formatter = new Line_Formatter(
"[%level_name%] %message% %context%",
true
);
}
}
public function handle(Log_Entry $entry): bool {
// Format the message and add it to the buffer.
$this->buffer[] = $this->formatter->format($entry);
return true;
}
public function flush(): void {
if (empty($this->buffer)) {
return;
}
$message = implode("\n", $this->buffer);
wp_remote_post($this->webhook_url, [
'body' => wp_json_encode(['text' => "```{$message}```"]),
'headers' => ['Content-Type' => 'application/json'],
]);
$this->buffer = [];
}
}
// Usage:
// $slack_handler = new Slack_Handler('https://hooks.slack.com/services/...');
// $manager->add_handler($slack_handler);To create a custom formatter, implement the Formatter_Interface.
- Create a class that implements
\WPTechnix\WP_Simple_Logger\Contracts\Formatter_Interface. - Implement the
format(Log_Entry $entry): stringmethod.
<?php
use WPTechnix\WP_Simple_Logger\Contracts\Formatter_Interface;
use WPTechnix\WP_Simple_Logger\Log_Entry;
class Simple_Message_Formatter implements Formatter_Interface {
public function format(Log_Entry $entry): string {
return strtoupper($entry->get_level_name()) . ': ' . $entry->get_message() . "\n";
}
}-
Centralize Initialization: Configure your
Managerand handlers in one central place (like a service container or a dedicated bootstrap function) to ensure consistency across your application. - Use Channels Effectively: Adopt a clear and consistent naming convention for your channels. This makes filtering and debugging much easier.
- Be Mindful of Sensitive Data: Avoid logging passwords, API keys, personal user information, or other sensitive data. If you must log potentially sensitive data, consider writing a custom formatter to sanitize or redact it before it's stored.
-
Use Appropriate Log Levels: Use
DEBUGfor verbose development information,INFOfor routine events,WARNINGfor non-critical issues, andERROR/CRITICALfor problems that require immediate attention. This makes level-based filtering effective. -
Leverage Buffering: For high-traffic sites, handlers like
Database_HandlerandFile_Handlerbenefit from a non-zero buffer limit. This reduces the number of I/O operations by batching writes.
-
Fatal Errors: If a PHP fatal error occurs that prevents WordPress's
shutdownhook from running, buffered logs may be lost. This is a fundamental limitation of PHP's execution model. -
wp_die(): The library automatically hooks intowp_dieto flush logs before execution terminates, so logs from AJAX handlers or form submissions that end inwp_die()should be saved correctly.