Skip to content

fix: include feed source URL and import ID in log context for easier troubleshooting#1284

Open
lucadobrescu wants to merge 5 commits into
developmentfrom
feat/1278-log-feed-context
Open

fix: include feed source URL and import ID in log context for easier troubleshooting#1284
lucadobrescu wants to merge 5 commits into
developmentfrom
feat/1278-log-feed-context

Conversation

@lucadobrescu

@lucadobrescu lucadobrescu commented Jul 17, 2026

Copy link
Copy Markdown

Feedzy logs couldn't tell you which import produced an entry, so users with multiple feeds couldn't trace an error back to its source (#1278). This PR tags every log entry written during an import run with the import's ID, title and source, and surfaces them as badges in the log viewer.

What changed

  • run_job() is now a thin wrapper that sets persistent logger context (import_id, import_title, source) via the existing Feedzy_Rss_Feeds_Log::set_context() and clears it in finally; the original body moved unchanged to run_job_logic(). Every entry written during a run — including fetch-layer errors — is attributed automatically.
  • A single broken feed URL used to import 0 items with no error logged (init_single_feed() returned early on unparseable feeds); it now logs the SimplePie error with feed_url, matching the multi-feed path.
  • The Settings → Logs viewer renders an import badge (Title (#ID)) and a feed-source badge per entry, falling back to the legacy job_id/source context keys; entries without attribution keys render as before, and the raw JSON context stays.
  • No new translatable strings (keeps the generated POT unchanged, as the Translations Diff job requires).

Also in this PR

WordPress.org Plugin Check errors (pre-existing, plugin-wide — the check fails every PR until resolved):

  • Direct-access ABSPATH guards added to 26 PHP files.
  • unlink()wp_delete_file() (5 call sites); the deliberate direct-filesystem fast paths (rename() on temp files, fclose()/readfile() in the guarded log tail/download) carry the matching phpcs:ignore annotations the file already used for fopen().
  • chosen-sprite@2x.pngchosen-sprite-2x.png (special character in filename), CSS reference updated.
  • feedzy-rss-feeds-util-simplepie.phpfeedzy-rss-feeds-util-feed.php — the filename false-matched the bundled-core-library check. The class is renamed to match (Feedzy_Rss_Feeds_Util_SimplePieFeedzy_Rss_Feeds_Util_Feed), so the autoloader's naming convention resolves it with no special-casing; Pro has no references to the old name.
  • e2e helper: the run-now AJAX wait allows 60s (a real import run with image sideloads exceeds the 10s default).

Where to start reviewing

  • includes/admin/feedzy-rss-feeds-import.php — the run_job() wrapper is the behavior change; run_job_logic() is a pure rename.
  • includes/abstract/feedzy-rss-feeds-admin-abstract.php — the previously silent single-feed error path.
  • includes/layouts/feedzy-logs-viewer.php — badge rendering and legacy-key fallbacks.
  • The 26 guard additions, the two file renames and css/settings.css are mechanical.
flowchart TD
    A["run_now() / run_cron()"] --> B["run_job(): set_context(import_id, import_title, source), clear in finally"]:::added
    B --> C["run_job_logic() — former run_job body"]
    C --> D["init_single_feed(): parse failure now logged with feed_url"]:::changed
    D --> E["Feedzy_Rss_Feeds_Log: persistent + per-call context merged"]
    E --> F["Logs viewer: import + feed badges, legacy job_id/source fallback"]:::changed

    classDef added fill:#1a7f37,color:#fff,stroke:#1a7f37
    classDef changed fill:#9a6700,color:#fff,stroke:#9a6700
Loading

🟩 green = added by this PR, 🟨 amber = behavior changed, gray = untouched.

Data transformation

New optional keys inside each JSONL log entry's context object (file: wp-content/uploads/feedzy-logs/feedzy.jsonl; written only while an import job runs; old entries are never rewritten):

Key Value Set by
import_id Import post ID run_job() wrapper
import_title Import post title run_job() wrapper
source Raw source meta (URL list or category slug) run_job() wrapper; per-call feed_url overrides it for URL-specific entries

QA instructions

  1. Create two imports, one with a dead feed URL (e.g. https://example.com/nonexistent-feed.xml), Run Now on both, open Feedzy → Settings → Logs, filter by Error: each error entry names the failing import and its feed URL — the healthy import is never blamed.
  2. Set logging level to Debug, run an import: info/debug entries carry the same badges.
  3. View a page with a [feedzy-rss feeds="…dead-url…"] shortcode, reload the logs: the fetch error shows a feed badge but no import badge.

tests/e2e/specs/log-attribution.spec.js covers all three flows (written failing-first against the unpatched code to confirm the bug, green after the fix).

Check before Pull Request is ready:

Closes #1278.

🤖 Generated with Claude Code

…troubleshooting

Scope the logger context to each import run so every entry written while a
job runs carries import_id, import_title and source; log single-feed parse
failures that were previously swallowed; surface the import and feed URL as
badges in the logs viewer with fallbacks for legacy job_id/source entries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pirate-bot pirate-bot added the pr-checklist-complete The Pull Request checklist is complete. (automatic label) label Jul 17, 2026
@lucadobrescu lucadobrescu self-assigned this Jul 17, 2026
@pirate-bot

pirate-bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Plugin build for 69fc9f7 is ready 🛎️!

Note

You can preview the changes in the Playground

Luca Dobrescu and others added 3 commits July 17, 2026 11:57
The Translations Diff CI job fails on any POT change; render the import ID
as a plain (#ID) suffix and drop the badge tooltips so the badges add no
new strings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add direct-access guards to 26 PHP files; replace unlink() with
wp_delete_file(); annotate the deliberate direct-filesystem fast paths;
rename chosen-sprite@2x.png (special character) and the SimplePie util
file that false-matched the core-library check (class name unchanged,
resolved via an autoloader class map). Also raise the run-now wait
timeout in the e2e helper for slow import runs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread feedzy-rss-feed.php Outdated
Comment on lines +62 to +71
// Class files named differently from the autoloader convention
// (e.g. to avoid matching core-library filename patterns).
$class_map = array(
'Feedzy_Rss_Feeds_Util_SimplePie' => 'includes/util/feedzy-rss-feeds-util-feed.php',
);
if ( isset( $class_map[ $class_to_load ] ) ) {
require_once plugin_dir_path( __FILE__ ) . $class_map[ $class_to_load ];

return true;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove this.

…Util_Feed

Match the class name to its file (feedzy-rss-feeds-util-feed.php) so the
autoloader's naming convention resolves it, and drop the special-case
class map from feedzy_rss_feeds_autoload().

Addresses review feedback:
#1284 (review)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds import/feed attribution to logs and improves troubleshooting, alongside Plugin Check cleanup.

Changes:

  • Adds scoped import context and feed parsing error attribution.
  • Displays import/source badges with legacy fallbacks and E2E coverage.
  • Adds access guards, safer file deletion, and asset/class renames.

Reviewed changes

Copilot reviewed 35 out of 36 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/e2e/utils.js Adds log-test helpers and import utilities.
tests/e2e/specs/log-attribution.spec.js Tests log attribution flows.
phpstan-baseline.neon Updates renamed utility references.
includes/views/wordai-view.php Adds direct-access guard.
includes/views/spinnerchief-view.php Adds direct-access guard.
includes/views/openrouter-view.php Adds direct-access guard.
includes/views/openai-view.php Adds direct-access guard.
includes/views/misc-view.php Adds direct-access guard.
includes/views/import-metabox-edit.php Adds direct-access guard.
includes/views/css/chosen.css References renamed sprite.
includes/views/css/chosen-sprite-2x.png Renames high-resolution sprite.
includes/views/amazon-product-advertising-view.php Adds direct-access guard.
includes/views/ai-quota-view.php Adds direct-access guard.
includes/util/feedzy-rss-feeds-util-feed.php Renames the SimplePie utility class/file.
includes/layouts/setup-wizard.php Adds direct-access guard.
includes/layouts/settings.php Adds direct-access guard.
includes/layouts/integration.php Adds direct-access guard.
includes/layouts/header.php Adds direct-access guard.
includes/layouts/feedzy-tutorial.php Adds direct-access guard.
includes/layouts/feedzy-support.php Adds direct-access guard.
includes/layouts/feedzy-subscribe-notice.php Adds direct-access guard.
includes/layouts/feedzy-schedules.php Adds direct-access guard.
includes/layouts/feedzy-pro.php Adds direct-access guard.
includes/layouts/feedzy-logs-viewer.php Renders attribution badges and fallbacks.
includes/layouts/feedzy-license.php Adds direct-access guard.
includes/layouts/feedzy-improve.php Adds direct-access guard.
includes/layouts/feedzy-documentation.php Adds direct-access guard.
includes/feedzy-rss-feeds-feed-tweaks.php Adds direct-access guard.
includes/admin/feedzy-rss-feeds-upgrader.php Adds direct-access guard.
includes/admin/feedzy-rss-feeds-options.php Adds direct-access guard.
includes/admin/feedzy-rss-feeds-log.php Documents direct filesystem operations.
includes/admin/feedzy-rss-feeds-import.php Scopes log context and modernizes file deletion.
includes/admin/feedzy-rss-feeds-actions.php Adds direct-access guard.
includes/abstract/feedzy-rss-feeds-admin-abstract.php Logs single-feed failures with URLs.
form/form.php Adds direct-access guard.
css/settings.css Styles attribution badges.
Comments suppressed due to low confidence (1)

includes/util/feedzy-rss-feeds-util-feed.php:31

  • Renaming this public class removes the autoload target for Feedzy_Rss_Feeds_Util_SimplePie. Any extension that still instantiates the old class will now fail before this new file is loaded, and there is no compatibility alias or autoloader mapping. Please keep the old class name resolvable while avoiding the flagged filename, for example via a bootstrap/autoloader alias to this class.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/e2e/utils.js
Comment on lines +294 to +309
await page
.locator('tr', { hasText: importName })
.getByRole('button', { name: 'Run Now' })
.click();

const runNowResponse = await page.waitForResponse(
(response) =>
response.url().includes('/wp-admin/admin-ajax.php') &&
response.request().method() === 'POST' &&
response
.request()
.postData()
.includes('action=feedzy&_action=run_now'),
// Importing a feed can take a while (remote fetch + image sideloads).
{ timeout: 60000 }
);
Comment on lines +168 to +170
// Backward compatibility: entries whose context has no attribution keys
// (this one only has a `feed_urls` array) render fine, without a badge row.
const keylessEntry = page.locator('.fz-log-container', {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-checklist-complete The Pull Request checklist is complete. (automatic label)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants