Skip to content

feat(submissions): diagnostic logging across the translation-enqueue phases#206

Merged
JohnRDOrazio merged 1 commit into
mainfrom
feat/diagnostic-logging-translation-enqueue
Jun 11, 2026
Merged

feat(submissions): diagnostic logging across the translation-enqueue phases#206
JohnRDOrazio merged 1 commit into
mainfrom
feat/diagnostic-logging-translation-enqueue

Conversation

@JohnRDOrazio

@JohnRDOrazio JohnRDOrazio commented Jun 11, 2026

Copy link
Copy Markdown
Member

Summary

Adds structured per-phase error_log lines to cdcf_enqueue_translations_for_submission so future incidents are diagnosable from production FPM logs alone.

Today's investigation into post 1508 (Eucharistic Miracles — "auto-translation didn't happen") consumed a lot of time because the function only logged on explicit failure paths:

  • Polylang not active
  • Source post N not found
  • Failed to create {lang} sibling
  • pll_save_post_translations returned false; rolling back N draft(s)

All the silent happy paths and the "all langs already linked" no-op path were invisible. We could only reconstruct what happened from the worker's cdcf_process_translation: Translation complete for post N (lang) lines + access-log timestamps. The actual story turned out to be: the hook DID create translation siblings successfully, but the Polylang group connection got disconnected somehow after the worker finished. Without entry/exit logs in the hook, we couldn't even confirm it had fired correctly until digging through 5 layers of secondary evidence.

What the new logs look like

Uniform shape, parseable, one line per phase transition:

cdcf_enqueue_translations_for_submission: ENTER post_id=1508 post_type=community_project pre_seed_group={en:1508}
cdcf_enqueue_translations_for_submission: PHASE_1_DONE post_id=1508 newly_created={it:1511, es:1512, fr:1513, pt:1514, de:1515} already_linked={}
cdcf_enqueue_translations_for_submission: PHASE_2_OK post_id=1508 atomic group save succeeded; final_group={en:1508, it:1511, es:1512, fr:1513, pt:1514, de:1525}
cdcf_enqueue_translations_for_submission: PHASE_3_DONE post_id=1508 queued 5 job(s) via redis: {it:1511, es:1512, fr:1513, pt:1514, de:1515}

Or for the no-op path (all langs already pre-seeded from a partial re-run):

cdcf_enqueue_translations_for_submission: ENTER post_id=1508 post_type=community_project pre_seed_group={en:1508, it:1511, es:1512, fr:1513, pt:1514, de:1515}
cdcf_enqueue_translations_for_submission: PHASE_1_DONE post_id=1508 newly_created={} already_linked={it:1511, es:1512, fr:1513, pt:1514, de:1515}
cdcf_enqueue_translations_for_submission: NO_OP post_id=1508 (all target langs already pre-seeded); exiting without group save.

The existing PHASE_2_FAIL rollback log is preserved with the same shape — post_id=X pll_save_post_translations returned false; rolling back N draft(s): {it:X, es:Y, ...}.

A single grep -E 'PHASE_|ENTER|NO_OP' against the FPM log now produces a complete timeline per submission publish.

Volume

  • ~3-5 new lines per submission publish (one publish per public referral approval = a handful per week at current load)
  • Per-sibling worker logs (cdcf_process_translation: Translation complete for post N (lang)) are unchanged
  • Negligible disk impact, meaningful debuggability lift

Implementation

  • New helper cdcf_format_lang_map(array): string centralizes the {lang:id, lang:id, ...} formatting so all lines parse consistently. Empty array → "{}". String-numeric IDs (which ACF / Polylang sometimes return) are coerced to int.
  • 4 unit tests for the formatter: empty array, single entry, 6-language order preservation, string→int coercion.
  • No production behavior change — purely additional logging on existing code paths.

Test plan

  • php -l clean
  • composer test --working-dir=wordpress/themes/cdcf-headless553/553 pass (+4 new helper tests; existing 549 unchanged)
  • After deploy: the next public referral approval should produce 3-5 visible cdcf_enqueue_translations_for_submission: lines in the FPM log (where today's runs produced 0 on the happy path)

Deploy

Backend (theme) change — ship via gh workflow run deploy.yml -f environment=production after merge.

Related

Follow-ups (out of scope here)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests

    • Added comprehensive test coverage for language map formatting in the translation submission workflow.
  • Chores

    • Enhanced diagnostic logging throughout the translation submission lifecycle to improve troubleshooting and visibility into the translation enqueue process.

…phases

Today's investigation into post 1508 (Eucharistic Miracles) cost a lot
of time because cdcf_enqueue_translations_for_submission ran with
almost no observability — the function only logged on explicit failure
paths (Polylang inactive, source missing, individual wp_insert_post
failure, atomic save returning false). All the SILENT happy paths and
the "all langs already linked" no-op path were invisible to
production log greps.

For 1508 the actual sequence was:
  ENTER post_id=1508 pre_seed={en:1508}
  PHASE_1_DONE newly_created={it:1511, es:1512, fr:1513, pt:1514, de:1515}
  PHASE_2_OK final_group={en:1508, it:1511, ...}
  PHASE_3_DONE queued 5 jobs via redis

None of which we could see in the FPM logs — only the worker's
"Translation complete for post N (lang)" lines from cdcf_process_translation.
We had to grep the access log and reconstruct timing from worker
completion timestamps to figure out the hook had actually succeeded
and the Polylang group disconnected SOMEHOW between hook completion
(03:00:28) and the next hook fire (03:21:00).

This adds 5 structured error_log lines at each phase transition with
a uniform shape:
  ENTER       post_id=X post_type=Y pre_seed_group={...}
  PHASE_1_DONE post_id=X newly_created={...} already_linked={...}
  PHASE_2_OK  post_id=X atomic group save succeeded; final_group={...}
    (or already-existing PHASE_2_FAIL on save returning false)
  PHASE_3_DONE post_id=X queued N job(s) via redis|wp-cron: {...}
  NO_OP       post_id=X (all target langs already pre-seeded)

Each line is a single grep -E 'PHASE_|ENTER|NO_OP' away from a
complete timeline. Volume: ~3-5 lines per submission publish (one
publish per public referral approval, so a few per week max). Per-
sibling worker logs (1 per translation) are unchanged.

New helper cdcf_format_lang_map() centralizes the {lang:id} formatting
so the lines are consistent and parseable. 4 unit tests for it: empty
array, single entry, 6-language order preservation, string->int
coercion.

553/553 theme suite green. No production behavior change — purely
additional logging.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 754e9d18-9e37-43b5-bdca-8c72a3c98935

📥 Commits

Reviewing files that changed from the base of the PR and between fef66d3 and c2dc390.

📒 Files selected for processing (2)
  • wordpress/themes/cdcf-headless/includes/admin/submission-lifecycle.php
  • wordpress/themes/cdcf-headless/tests/SubmissionLifecycleTest.php

📝 Walkthrough

Walkthrough

Updated the translation enqueue function with structured diagnostic logging at entry, phase completion, and failure checkpoints. Introduced a new helper function to format language-to-post-id maps compactly for log output, with comprehensive test coverage for empty, single, and multi-language scenarios.

Changes

Diagnostic Logging

Layer / File(s) Summary
Diagnostic logging in translation enqueue lifecycle
wordpress/themes/cdcf-headless/includes/admin/submission-lifecycle.php, wordpress/themes/cdcf-headless/tests/SubmissionLifecycleTest.php
Entry point logs the pre-seeded Polylang translation map; phase 1 logs completion and early exit when no newly-created siblings; phase 2 logs atomic save success and failure with draft rollback details; phase 3 logs job queue count and mechanism. New cdcf_format_lang_map() helper formats {lang => post_id} maps into compact {lang:id, ...} strings (or {} when empty) for error logs. Tests validate empty-map, single-entry, multi-language key order preservation, and string-to-integer coercion of language IDs.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • CatholicOS/cdcf-website#203: The phase 2 atomic save and rollback mechanism used by the new logging directly builds on the group save flow introduced in PR #203.
  • CatholicOS/cdcf-website#37: The translation enqueue function being instrumented was originally added in PR #37 to auto-create and link Polylang sibling drafts; this PR adds observability to that same workflow.

Poem

🐰 A rabbit hops through logs so clear,
Mapping tongues from far and near—
Entry, phase, and rollback tracked,
Translations queued with every fact! 📋✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately describes the main change: adding diagnostic logging across translation-enqueue phases in the submission lifecycle function.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/diagnostic-logging-translation-enqueue

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 4 complexity

Metric Results
Complexity 4

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@JohnRDOrazio JohnRDOrazio merged commit f0f8834 into main Jun 11, 2026
13 checks passed
@JohnRDOrazio JohnRDOrazio deleted the feat/diagnostic-logging-translation-enqueue branch June 11, 2026 03:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants