WordPress / WordPress/wordpress-playground

[Enhancement]: Surface debug.log errors

Open
#3,602 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

[Type] Enhancement
Dominant language
JavaScript
Stars
2k
Forks
462
Avg merge
18h 44m
Merged PRs (30d)
33

Description

Describe the solution you'd like

RIght now the Logs panel shows a 🎉 even if there were fatals that were logged to /wordpress/wp-content/debug.log. We should surface those.

Describe alternatives you've considered

A lower-level Playground client API such as stat(path) plus readFileRange(path, offset, length) may be the cleaner long-term solution.
The PHP-side tailing sketch is a workaround that avoids broadening the client API in the short term.

Additional context

I tried an implementation in #3601 but it was getting out of hand. We don't have a playground.stat() that allows reading the file at boot to determine if something was added.

This is a potential workaround:

const debugLogMaxUnreadChars = 256 * 1024;
const debugLogReadOffsets = new WeakMap<PlaygroundClient, number>();

type DebugLogTail = {
	size: number;
	content: string;
};

async function readDebugLogTail(
	playground: PlaygroundClient
	): Promise<DebugLogTail | null> {
	const previousOffset = debugLogReadOffsets.get(playground) ?? 0;

	const response = await playground.run({
		code: `<?php
$path = '/wordpress/wp-content/debug.log';
$previousOffset = ${JSON.stringify(previousOffset)};
$maxBytes = ${JSON.stringify(debugLogMaxUnreadChars)};

if (!file_exists($path)) {
		echo json_encode(null);
		return;
}

$size = filesize($path);
$start = $previousOffset;

if ($start > $size) {
		$start = 0;
}

$start = max($start, $size - $maxBytes);

$handle = fopen($path, 'rb');
if (!$handle) {
		echo json_encode(null);
		return;
}

fseek($handle, $start);
$content = stream_get_contents($handle);
fclose($handle);

echo json_encode(array(
		'size' => $size,
			'content' => $content,
));
		`,
	});

	if (response.exitCode !== 0) {
		return null;
	}

	return response.json as DebugLogTail | null;
}

async function surfaceDebugLogEntries(playground: PlaygroundClient) {
	try {
		const tail = await readDebugLogTail(playground);
		if (!tail) {
			return;
		}

		debugLogReadOffsets.set(playground, tail.size);

		const filtered = tail.content
		.split('\n')
		.filter((line) => line.trim() && !isIgnoredLogLine(line))
		.join('\n');

		if (filtered.length > 0) {
			logger.logMessage({
				message: filtered,
				severity: LogSeverity.Log,
				raw: true,
			});
		}
	} catch {
							// Playground may not be ready yet.
	}
}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the Logs panel and the PlaygroundClient.run call shown in the issue; inspect how log messages are filtered and rendered. Confirm the implementation can detect new /wordpress/wp-content/debug.log content and that fatal entries appear instead of a success-only state, including when the Playground is not ready.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, php, wasm
Domain
backend, observability
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.