PluginProbe
Search Atlas SEO – OTTO AI SEO Automation for WordPress / 2.7.1
Search Atlas SEO – OTTO AI SEO Automation for WordPress v2.7.1
2.7.1 2.7.2 2.7.0 2.6.26 2.6.25 2.6.24 2.6.23 2.6.22 2.6.21 2.6.20 2.6.19 2.6.18 2.6.17 2.6.16 2.6.15 2.6.14 2.6.13 2.6.12 2.6.11 2.6.10 2.6.9 2.6.8 2.6.7 2.6.6 2.6.5 All 141 releases
← All changes | includes/class-metasync-api-backoff-manager.php +29 -12 2.6.17 → 2.7.1 View file →
@@ -162,17 +162,14 @@
162 162 if ($this->is_endpoint_in_backoff($url)) {
163 163 $endpoint_hash = $this->get_endpoint_hash($url);
164 164 $backoff_data = $this->get_backoff_state($endpoint_hash);
165 165
166 - // Log the blocked request
167 - $this->log_backoff_event(
168 - 'API_BACKOFF_BLOCKED',
169 - sprintf(
170 - 'Request blocked due to active backoff. Endpoint: %s, Time remaining: %d seconds',
171 - $this->extract_endpoint($url),
172 - $backoff_data['time_remaining']
173 - )
174 - );
166 + // Deliberately NOT logged. This runs once per blocked request, so on a
167 + // busy site in backoff it would write a log line and an error-summary
168 + // row per request — write amplification at precisely the moment the
169 + // site is already struggling. The state transitions below
170 + // (triggered / cleared / counter reset) are what carry the diagnostic
171 + // value, and they fire once each.
175 172
176 173 // Return WP_Error to prevent the request
177 174 return new WP_Error(
178 175 'api_backoff_active',
@@ -368,9 +365,9 @@
368 365
369 366 $backoffs = [];
370 367
371 368 // Query all backoff transients
372 - $transient_keys = $wpdb->get_col(
369 + $transient_keys = $wpdb->get_col( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- transient enumeration on the options table — no API to scan transient rows
373 370 $wpdb->prepare(
374 371 "SELECT option_name FROM {$wpdb->options}
375 372 WHERE option_name LIKE %s",
376 373 '_transient_' . self::BACKOFF_PREFIX . '%'
@@ -425,9 +422,9 @@
425 422 self::LAST_SUCCESS_PREFIX,
426 423 ];
427 424
428 425 foreach ($prefixes as $prefix) {
429 - $transient_keys = $wpdb->get_col(
426 + $transient_keys = $wpdb->get_col( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- transient enumeration on the options table — no API to scan transient rows
430 427 $wpdb->prepare(
431 428 "SELECT option_name FROM {$wpdb->options}
432 429 WHERE option_name LIKE %s
433 430 OR option_name LIKE %s",
@@ -497,9 +494,29 @@
497 494 * @param string $event_type Event type identifier.
498 495 * @param string $message Log message.
499 496 */
500 497 private function log_backoff_event($event_type, $message) {
501 - // Backoff events are operational noise; suppress from error log.
498 + // This was previously an empty stub, which made fleet-wide backoff behaviour
499 + // completely invisible — we could not tell from a customer's logs whether
500 + // backoff had triggered, blocked, or cleared.
501 + //
502 + // Routed through Metasync_Error_Logger rather than error_log() so it stays
503 + // suppressed by default: CATEGORY_API_BACKOFF is in DEBUG_ONLY_CATEGORIES,
504 + // so nothing is written unless Debug Mode is on. That keeps the original
505 + // "operational noise" concern satisfied while making diagnosis possible.
506 + if (!class_exists('Metasync_Error_Logger')) {
507 + return;
508 + }
509 +
510 + Metasync_Error_Logger::log(
511 + Metasync_Error_Logger::CATEGORY_API_BACKOFF,
512 + Metasync_Error_Logger::SEVERITY_INFO,
513 + $message,
514 + [
515 + 'event_type' => $event_type,
516 + 'operation' => 'api_backoff',
517 + ]
518 + );
502 519 }
503 520
504 521 /**
505 522 * Get formatted time remaining