Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add logging support to Playground #1035

Merged
merged 37 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6b21516
Basic error logging
bgrgicak Feb 13, 2024
d804cec
Move logger to a new file
bgrgicak Feb 14, 2024
8480857
Update log message param
bgrgicak Feb 14, 2024
7f2c27a
Cleanup
bgrgicak Feb 14, 2024
46542e5
Return n lines
bgrgicak Feb 14, 2024
315a622
Move logger to website
bgrgicak Feb 16, 2024
c23dd92
Display debug.log for request
bgrgicak Feb 16, 2024
60aa62f
Rewrite compiler error to return all error data
bgrgicak Feb 16, 2024
0923c3e
Remove test log
bgrgicak Feb 16, 2024
6d6bdaf
Clean up
bgrgicak Feb 16, 2024
d13033d
Merge branch 'trunk' into add/wp-logs
bgrgicak Feb 16, 2024
194bcbd
Merge branch 'add/wp-logs' of https://github.com/WordPress/wordpress-…
bgrgicak Feb 16, 2024
b84bdc0
Collect PHP logs on compile error
bgrgicak Feb 19, 2024
46ca5ee
Merge branch 'trunk' into add/wp-logs
bgrgicak Feb 19, 2024
42e47d8
Move logger to blueprints
bgrgicak Feb 19, 2024
3ea93c5
Remove unused dependency
bgrgicak Feb 19, 2024
b1b1c71
Fix linter error
bgrgicak Feb 19, 2024
c3e2c77
Move logger length to Logger
bgrgicak Feb 19, 2024
9eed92f
Cleanup unused changes
bgrgicak Feb 19, 2024
cabbd9b
Address feedback
bgrgicak Feb 21, 2024
5ab98c7
Reset base-php
bgrgicak Feb 21, 2024
6ec3c4a
Merge branch 'trunk' into add/wp-logs
bgrgicak Feb 21, 2024
c9f0b5c
Move logger to package
bgrgicak Feb 22, 2024
f28c20a
Start logger in client and node
bgrgicak Feb 22, 2024
65dd662
Merge branch 'trunk' into add/wp-logs
bgrgicak Feb 22, 2024
be90919
Remove node logger
bgrgicak Feb 23, 2024
d0398a3
Set WP_DEBUG only if WP exists
bgrgicak Feb 23, 2024
0650878
Update packages/playground/logger/logger.ts
bgrgicak Feb 23, 2024
a192ceb
Update packages/playground/remote/src/lib/playground-mu-plugin/playgr…
bgrgicak Feb 23, 2024
06158e7
Merge branch 'trunk' into add/wp-logs
bgrgicak Feb 23, 2024
b14f4a5
Move logger to a buildable package
bgrgicak Feb 26, 2024
d0546aa
Fix linter
bgrgicak Feb 26, 2024
451ede1
Merge branch 'trunk' into add/wp-logs
bgrgicak Feb 26, 2024
1d840ed
Move logger code to main plugin file
bgrgicak Feb 27, 2024
a3feb32
Attach JS logger in Website only
bgrgicak Feb 28, 2024
ef4993b
Revert compile error
bgrgicak Feb 28, 2024
988a9a5
Move window log collection to main
bgrgicak Feb 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 23 additions & 13 deletions packages/php-wasm/universal/src/lib/base-php.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
UnhandledRejectionsTarget,
} from './wasm-error-reporting';
import { Semaphore, createSpawnHandler, joinPaths } from '@php-wasm/util';
import { LogSeverity, get_logger } from './logger';

const STRING = 'string';
const NUMBER = 'number';
Expand Down Expand Up @@ -264,21 +265,28 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
this.#setPHPCode(' ?>' + request.code);
}
this.#addServerGlobalEntriesInWasm();
const response = await this.#handleRequest();
if (request.throwOnError && response.exitCode !== 0) {
const output = {
stdout: response.text,
stderr: response.errors,
};
console.warn(`PHP.run() output was:`, output);
const error = new Error(
`PHP.run() failed with exit code ${response.exitCode} and the following output`
try {
const response = await this.#handleRequest();
if (request.throwOnError && response.exitCode !== 0) {
const output = {
stdout: response.text,
stderr: response.errors,
};
console.warn(`PHP.run() output was:`, output);
const error = new Error(
`PHP.run() failed with exit code ${response.exitCode} and the following output`
);
// @ts-ignore
error.output = output;
throw error;
}
return response;
bgrgicak marked this conversation as resolved.
Show resolved Hide resolved
} catch (e: any) {
get_logger(this).log(
bgrgicak marked this conversation as resolved.
Show resolved Hide resolved
e.message,
LogSeverity.Error,
);
// @ts-ignore
error.output = output;
throw error;
}
return response;
} finally {
try {
if (heapBodyPointer) {
Expand Down Expand Up @@ -770,6 +778,7 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
// runtime.
const oldFS = this[__private__dont__use].FS;

console.log('PHP runtime exited');
// Kill the current runtime
try {
this.exit();
Expand Down Expand Up @@ -799,6 +808,7 @@ export abstract class BasePHP implements IsomorphicLocalPHP {
}

exit(code = 0) {
console.log('PHP exit()');
this.dispatchEvent({
type: 'runtime.beforedestroy',
});
Expand Down
121 changes: 121 additions & 0 deletions packages/php-wasm/universal/src/lib/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { UniversalPHP } from "./universal-php";

export enum LogSeverity {
// A dine grained debugging event. Typically disabled in default configurations.
Trace = 1,
// A debugging event.
Debug = 5,
// An informational event. Indicates that an event happened.
Info = 9,
// A warning event. Not an error but is likely more important than an informational event.
Warn = 13,
// An error event. Something went wrong.
Error = 17,
// A fatal error such as application or system crash.
Fatal = 21,
}

export type Log = {
// Time when the event occurred.
timestamp: number;
// Time when the event was observed.
observedTimestamp: number;
// Request trace id.
traceId: number;
// Request span id.
spanId: number; // Not implemented
bgrgicak marked this conversation as resolved.
Show resolved Hide resolved
// W3C trace flag.
traceFlags: number;
// The severity text (also known as log level).
severityText: string;
// Numerical value of the severity.
severityNumber: LogSeverity;
// The body of the log record.
body: string;
// Describes the source of the log.
resource: string;
// Describes the scope that emitted the log.
instrumentationScope: string; // Not implemented
// Additional information about the event.
attributes: Record<string, string>;
};

export class Logger {
private php: UniversalPHP | undefined;
private logs: Log[] = [];
private wordpressLogs: string[] | undefined = undefined;

constructor(php?: UniversalPHP) {
this.php = php;
if (this.php) {
this.php.addEventListener(
'request.end',
() => {
console.log(this.getLogs());
}
)
this.php.onMessage((message) => {
try {
const logMessage = JSON.parse(message);
if (logMessage.type === 'wordpress-log') {
this.log(
logMessage.body,
logMessage.severityNumber,
logMessage.timestamp,
'wordpress',
);
}
} catch (error) {
// Not a log message
}
});
}
if ( typeof window !== 'undefined' ) {
window.onerror = (message, source, lineno, colno) => {
this.log(
`${message} in ${source} on line ${lineno}:${colno}`,
LogSeverity.Fatal,
Date.now(),
'javascript',
);
}
}
}

public log(body: string, severityNumber: LogSeverity = LogSeverity.Info, timestamp?: number, resource = 'php', instrumentationScope = 'php', attributes: Record<string, string> = {}): void {
bgrgicak marked this conversation as resolved.
Show resolved Hide resolved
const now = Date.now();
this.logs.push({
timestamp: timestamp || now,
observedTimestamp: now,
traceId: 1, // @TODO: Implement trace id
spanId: 1, // @TODO: Implement span id
traceFlags: 1,
severityText: LogSeverity[severityNumber],
severityNumber,
body,
resource,
instrumentationScope,
attributes,
});
}

public getLogs(): Log[] {
return this.logs;
}

public async addWordPressLogs() {
if (this.php && this.wordpressLogs === undefined) {
const rawLogs = await this.php.readFileAsText('/tmp/debug.log');

Check failure on line 108 in packages/php-wasm/universal/src/lib/logger.ts

View workflow job for this annotation

GitHub Actions / Lint and typecheck

'rawLogs' is assigned a value but never used
}
}

};

let logger: Logger | undefined = undefined;

export function get_logger(php?: BasePHP): Logger {
if (!logger) {
logger = new Logger(php);
}
return logger;
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

/**
* This is a temporary workaround to hide the 32bit integer warnings that
* This is a temporary workaround to hide the 32bit integer warnings that
* appear when using various time related function, such as strtotime and mktime.
* Examples of the warnings that are displayed:
* Warning: mktime(): Epoch doesn't fit in a PHP integer in <file>
Expand Down Expand Up @@ -29,19 +29,19 @@ function () {
);

/**
* Because the in-browser Playground doesn't have access to the internet,
* network-dependent features like directories don't work. Normally, you'll
* Because the in-browser Playground doesn't have access to the internet,
* network-dependent features like directories don't work. Normally, you'll
* see a confusing message like "An unexpected error occurred." This mu-plugin
* makes it more clear that the feature is not yet supported.
*
*
* https://github.com/WordPress/wordpress-playground/issues/498
*
*
* Added styling to hide the Popular tags section of the Plugins page
* and the nonfunctional Try Again button (both Plugins and Themes) that's
* appended when the message is displayed.
*
*
* https://github.com/WordPress/wordpress-playground/issues/927
*
*
*/
add_action('admin_head', function () {
echo '<style>
Expand Down Expand Up @@ -90,7 +90,7 @@ function networking_disabled() {
* the sandbox attribute. What they really should be targeting is the
* playground iframe itself (name="playground"). This mu-plugin rewrites
* all target="_top" links to target="playground" instead.
*
*
* https://github.com/WordPress/wordpress-playground/issues/266
*/
add_action('admin_print_scripts', function () {
Expand Down Expand Up @@ -129,9 +129,9 @@ function networking_disabled() {
* The default WordPress requests transports have been disabled
* at this point. However, the Requests class requires at least
* one working transport or else it throws warnings and acts up.
*
*
* This mu-plugin provides that transport. It's one of the two:
*
*
* * WP_Http_Fetch – Sends requests using browser's fetch() function.
* Only enabled when PHP was compiled with the VRZNO
* extension.
Expand All @@ -154,10 +154,10 @@ function networking_disabled() {
/**
* Disable signature verification as it doesn't seem to work with
* fetch requests:
*
*
* https://downloads.wordpress.org/plugin/classic-editor.zip returns no signature header.
* https://downloads.wordpress.org/plugin/classic-editor.zip.sig returns 404.
*
*
* @TODO Investigate why.
*/
add_filter('wp_signature_hosts', function ($hosts) {
Expand All @@ -176,3 +176,51 @@ function networking_disabled() {
return $transports;
});
}

// Configure error logging
$log_file = WP_CONTENT_DIR . '/debug.log';
error_reporting(E_ALL);
define('ERROR_LOG_FILE', $log_file);
ini_set('error_log', $log_file);

/**
* Get OpenTracing severity number from PHP error code
*
* @param int $code PHP error code
* @return int OpenTracing severity number
*/
function get_severity_number($code)
{
// @TODO Update numbers
switch ($code) {
case E_ERROR:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
return 17;
bgrgicak marked this conversation as resolved.
Show resolved Hide resolved
case E_WARNING:
case E_CORE_WARNING:
case E_COMPILE_WARNING:
case E_USER_WARNING:
return 13;
case E_NOTICE:
case E_USER_NOTICE:
return 9;
default:
return 5;
}
}

function playground_error_handler($errno, $errstr, $errfile, $errline)
{
post_message_to_js(
json_encode([
'event' => 'wordpress-log',
'timestamp' => time(),
'severityNumber' => get_severity_number($errno),
'body' => "$errstr in $errfile on line $errline",
])
);
return true;
}
set_error_handler('playground_error_handler');
Loading