Skip to content

Commit

Permalink
Merge pull request #21 from BenceSzalai/master
Browse files Browse the repository at this point in the history
Improve: more concise fallback error logging when wpdb fails
  • Loading branch information
BenceSzalai authored Feb 9, 2022
2 parents 2d6fcbb + aea090f commit 6a370c3
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 39 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased v2]

## [2.2.1] - 2022-02-10
### Improved
- More concise fallback error logging when wpdb fails: The error message is only logged once per execution, it is adjusted based on the actual WordPress version and the format of the actual fallback logging is more compact as well.

## [2.2.0] - 2022-02-09
### Improved
- The handler did not check if inserting the records into the db was successful or not. This could cause important log messages to be lost unnoticed. The handler now logs a warning into the default PHP error log and also logs the failed record there for reference.
Expand Down Expand Up @@ -73,7 +77,8 @@ V1 is continued to be updated for continued support for Monolog v1 and PHP versi
No changelog had been maintained up to this point. Refer to the GIT commit history for more details.


[Unreleased v2]: https://github.com/bradmkjr/monolog-wordpress/compare/2.2.0...HEAD
[Unreleased v2]: https://github.com/bradmkjr/monolog-wordpress/compare/2.2.1...HEAD
[2.2.1]: https://github.com/bradmkjr/monolog-wordpress/tree/2.2.1
[2.2.0]: https://github.com/bradmkjr/monolog-wordpress/tree/2.2.0
[2.1.2]: https://github.com/bradmkjr/monolog-wordpress/tree/2.1.2
[2.1.1]: https://github.com/bradmkjr/monolog-wordpress/tree/2.1.1
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"keywords": ["wordpress", "log", "logging", "monolog", "mysql", "database"],
"homepage": "https://github.com/bradmkjr/monolog-wordpress",
"license": "MIT",
"version": "2.2.0",
"version": "2.2.1",
"authors": [
{
"name": "Bradford Knowlton",
Expand Down
85 changes: 48 additions & 37 deletions src/WordPressHandler/WordPressHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ class WordPressHandler extends AbstractProcessingHandler
* Do not choose a value too low, because it may generate huge database overhead!
*/
protected $truncate_batch_size = 1;
/**
* @var bool Indicates, if {@see \wpdb} has failed to write a log records and the related message has been logged
* into the default system log already. This is used to only write such message to the log file once
* per execution.
*/
protected $wpdb_no_error_message_logged = false;
/**
* Constructor of this class, sets own fields and calls parent constructor
*
Expand Down Expand Up @@ -93,7 +99,7 @@ public function __construct(
}
$this->table = $table;
$this->prefix = $this->wpdb->prefix;

$this->additionalFields = $additionalFields;
parent::__construct($level, $bubble);
}
Expand Down Expand Up @@ -145,31 +151,31 @@ public function get_table_name()
*/
public function initialize(array $record)
{

// referenced
// https://codex.wordpress.org/Creating_Tables_with_Plugins

// $this->wpdb->exec(
// 'CREATE TABLE IF NOT EXISTS `'.$this->table.'` '
// .'(channel VARCHAR(255), level INTEGER, message LONGTEXT, time INTEGER UNSIGNED)'
// );

$charset_collate = $this->wpdb->get_charset_collate();

$table_name = $this->get_table_name();

// allow for Extra fields
$extraFields = '';
foreach ($record['extra'] as $key => $val) {
$extraFields.=",\n`$key` TEXT NULL DEFAULT NULL";
}

// additional fields
$additionalFields = '';
foreach ($this->additionalFields as $f) {
$additionalFields.=",\n`$f` TEXT NULL DEFAULT NULL";
}

$sql = "CREATE TABLE $table_name (
id INT(11) NOT NULL AUTO_INCREMENT,
channel VARCHAR(255),
Expand All @@ -178,11 +184,11 @@ public function initialize(array $record)
time INTEGER UNSIGNED$extraFields$additionalFields,
PRIMARY KEY (id)
) $charset_collate;";


require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
dbDelta( $sql );

$this->initialized = true;
}
/**
Expand All @@ -192,7 +198,7 @@ public function uninitialize()
{
$table_name = $this->get_table_name();
$sql = "DROP TABLE IF EXISTS $table_name;";

if (!is_null($this->wpdb)) {
$this->wpdb->query($sql);
}
Expand Down Expand Up @@ -224,11 +230,17 @@ protected function maybe_truncate() {
}
return false;
}

/**
* Writes the record down to the log of the implementing handler
*
* @param $record[]
* @param $record []
*
* @return void
*
* @throws \Psr\Log\InvalidArgumentException
*
* @noinspection ForgottenDebugOutputInspection
*/
protected function write(array $record): void
{
Expand All @@ -242,51 +254,50 @@ protected function write(array $record): void
'message' => (isset($record['formatted']['message'])) ? $record['formatted']['message'] : $record['message'],
'time' => $record['datetime']->format('U')
);

// Make sure to use the formatted values for context and extra, if available
$recordExtra = (isset($record['formatted']['extra'])) ? $record['formatted']['extra'] : $record['extra'];
$recordContext = (isset($record['formatted']['context'])) ? $record['formatted']['context'] : $record['context'];

$recordContExtra = array_merge( $recordExtra, $recordContext );

// json encode values as needed
array_walk($recordContExtra, function(&$value, $key) {
if(is_array($value) || $value instanceof \Traversable) {
$value = json_encode($value);
}
});

$contentArray = $contentArray + $recordContExtra;

if(count($this->additionalFields) > 0) {
//Fill content array with "null" values if not provided
$contentArray = $contentArray + array_combine(
$this->additionalFields,
array_fill(0, count($this->additionalFields), null)
);
$this->additionalFields,
array_fill(0, count($this->additionalFields), null)
);
}

$table_name = $this->get_table_name();

if (!$this->wpdb->insert( $table_name, $contentArray )) {

// E_USER_ERROR would terminate PHP so we must only use WARNING or NOTICE
$php_error_level = ($record['level'] <= Logger::NOTICE) ? E_USER_NOTICE : E_USER_WARNING;

if ( '' === $this->wpdb->last_error ) {
trigger_error('WordPressHandler failed to write a log record into the database and wpdb returned no error message. This typically happens in WordPress versions prior v5.9 when the message, or a context or an extra field is too long or contains invalid data. Since WordPress v5.9 too long or invalid data triggers a specific error message. If you are using WordPress v5.9 or later the root cause of the issue is unknown.', E_USER_WARNING);
// Since this error message does not include details it is enough to log it only once
if (!$this->wpdb_no_error_message_logged) {
if ( function_exists('is_wp_version_compatible') && is_wp_version_compatible('5.9') ) {
$this->wpdb_no_error_message_logged = error_log( 'Monolog Error: WordPressHandler failed to write a log record into the database and wpdb returned no error message. The root cause of the issue is unknown.' );
}
else {
$this->wpdb_no_error_message_logged = error_log( 'Monolog Error: WordPressHandler failed to write a log record into the database and wpdb returned no error message. This typically happens when the message or a context or an extra field is too long or contains invalid data.' );
}
}
}
else {
trigger_error('WordPressHandler failed to write a log record into the database. ' . $this->wpdb->last_error, E_USER_WARNING);
error_log('Monolog Error: WordPressHandler failed to write a log record into the database. ' . $this->wpdb->last_error);
}

trigger_error(
'WordPressHandler failed to log the following record.'.
' Time: '.$contentArray['time'].
' Channel: '.$contentArray['channel'].
' Level: '.$contentArray['level'].
' Message: `'.$contentArray['message'].'`',
$php_error_level

error_log(
'Monolog fallback: '.$contentArray['channel'].' '.ucfirst(strtolower(Logger::getLevelName($contentArray['level']))).': '.$contentArray['message']
);
}
else {
Expand Down

0 comments on commit 6a370c3

Please sign in to comment.