mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-09 14:21:02 +01:00
Modified DarkConsole Error Log to show more detailed information.
Summary: When function phlog() is called, stacktrace and detailed log information is shown in DarkConsole. Test Plan: Called 'phlog' function from various places in Phabricator and checked that the debug information was available in DarkConsole. Reviewed By: epriestley Reviewers: epriestley CC: jungejason, epriestley Differential Revision: 101
This commit is contained in:
parent
1910f43364
commit
d5ee8c792c
10 changed files with 212 additions and 101 deletions
|
@ -18,7 +18,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'aphront-dark-console-css' =>
|
||||
array(
|
||||
'uri' => '/res/056b0c12/rsrc/css/aphront/dark-console.css',
|
||||
'uri' => '/res/0417eb95/rsrc/css/aphront/dark-console.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -61,24 +61,6 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/css/aphront/headsup-action-list-view.css',
|
||||
),
|
||||
'aphront-list-filter-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/50a790ae/rsrc/css/aphront/list-filter-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/aphront/list-filter-view.css',
|
||||
),
|
||||
'aphront-pager-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/73ec8cd5/rsrc/css/aphront/pager-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/aphront/pager-view.css',
|
||||
),
|
||||
'aphront-panel-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/8f9f3632/rsrc/css/aphront/panel-view.css',
|
||||
|
@ -134,6 +116,24 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/css/aphront/typeahead.css',
|
||||
),
|
||||
'aphront-pager-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/73ec8cd5/rsrc/css/aphront/pager-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/aphront/pager-view.css',
|
||||
),
|
||||
'aphront-list-filter-view-css' =>
|
||||
array(
|
||||
'uri' => '/res/50a790ae/rsrc/css/aphront/list-filter-view.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/aphront/list-filter-view.css',
|
||||
),
|
||||
'phabricator-standard-page-view' =>
|
||||
array(
|
||||
'uri' => '/res/0d41ea7c/rsrc/css/application/base/standard-page-view.css',
|
||||
|
@ -297,15 +297,6 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/css/application/objectselector/object-selector.css',
|
||||
),
|
||||
'owners-path-editor-css' =>
|
||||
array(
|
||||
'uri' => '/res/f40dc6b1/rsrc/css/application/owners/owners-path-editor.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/owners/owners-path-editor.css',
|
||||
),
|
||||
'phabricator-profile-css' =>
|
||||
array(
|
||||
'uri' => '/res/259ad37f/rsrc/css/application/people/profile.css',
|
||||
|
@ -315,6 +306,15 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/css/application/people/profile.css',
|
||||
),
|
||||
'owners-path-editor-css' =>
|
||||
array(
|
||||
'uri' => '/res/f40dc6b1/rsrc/css/application/owners/owners-path-editor.css',
|
||||
'type' => 'css',
|
||||
'requires' =>
|
||||
array(
|
||||
),
|
||||
'disk' => '/rsrc/css/application/owners/owners-path-editor.css',
|
||||
),
|
||||
'phabricator-ui-example-css' =>
|
||||
array(
|
||||
'uri' => '/res/365a10f1/rsrc/css/application/uiexample/example.css',
|
||||
|
@ -360,6 +360,16 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/css/core/syntax.css',
|
||||
),
|
||||
'multirow-row-manager' =>
|
||||
array(
|
||||
'uri' => '/res/330d076b/rsrc/js/application/core/MultirowRowManager.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-lib-dev',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/core/MultirowRowManager.js',
|
||||
),
|
||||
'javelin-behavior-dark-console' =>
|
||||
array(
|
||||
'uri' => '/res/020b0265/rsrc/js/application/core/behavior-dark-console.js',
|
||||
|
@ -371,7 +381,7 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'javelin-behavior-phabricator-object-selector' =>
|
||||
array(
|
||||
'uri' => '/res/4fe735af/rsrc/js/application/core/behavior-object-selector.js',
|
||||
'uri' => '/res/c0f12b29/rsrc/js/application/core/behavior-object-selector.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
|
@ -399,15 +409,15 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/core/behavior-workflow.js',
|
||||
),
|
||||
'multirow-row-manager' =>
|
||||
'javelin-behavior-error-log' =>
|
||||
array(
|
||||
'uri' => '/res/330d076b/rsrc/js/application/core/MultirowRowManager.js',
|
||||
'uri' => '/res/c57a323f/rsrc/js/application/core/behavior-error-log.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'javelin-lib-dev',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/core/MultirowRowManager.js',
|
||||
'disk' => '/rsrc/js/application/core/behavior-error-log.js',
|
||||
),
|
||||
'javelin-behavior-differential-add-reviewers' =>
|
||||
array(
|
||||
|
@ -499,17 +509,6 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/diffusion/behavior-pull-lastmodified.js',
|
||||
),
|
||||
'javelin-behavior-herald-rule-editor' =>
|
||||
array(
|
||||
'uri' => '/res/48108130/rsrc/js/application/herald/herald-rule-editor.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'herald-rule-editor',
|
||||
1 => 'javelin-lib-dev',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/herald/herald-rule-editor.js',
|
||||
),
|
||||
'herald-rule-editor' =>
|
||||
array(
|
||||
'uri' => '/res/ec8e2110/rsrc/js/application/herald/HeraldRuleEditor.js',
|
||||
|
@ -523,6 +522,17 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/herald/HeraldRuleEditor.js',
|
||||
),
|
||||
'javelin-behavior-herald-rule-editor' =>
|
||||
array(
|
||||
'uri' => '/res/48108130/rsrc/js/application/herald/herald-rule-editor.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'herald-rule-editor',
|
||||
1 => 'javelin-lib-dev',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/herald/herald-rule-editor.js',
|
||||
),
|
||||
'path-typeahead' =>
|
||||
array(
|
||||
'uri' => '/res/42fb76c3/rsrc/js/application/herald/PathTypeahead.js',
|
||||
|
@ -544,17 +554,6 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/maniphest/behavior-transaction-controls.js',
|
||||
),
|
||||
'javelin-behavior-owners-path-editor' =>
|
||||
array(
|
||||
'uri' => '/res/7568aa22/rsrc/js/application/owners/owners-path-editor.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'owners-path-editor',
|
||||
1 => 'javelin-lib-dev',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/owners/owners-path-editor.js',
|
||||
),
|
||||
'owners-path-editor' =>
|
||||
array(
|
||||
'uri' => '/res/b01c1ca9/rsrc/js/application/owners/OwnersPathEditor.js',
|
||||
|
@ -568,6 +567,17 @@ celerity_register_resource_map(array(
|
|||
),
|
||||
'disk' => '/rsrc/js/application/owners/OwnersPathEditor.js',
|
||||
),
|
||||
'javelin-behavior-owners-path-editor' =>
|
||||
array(
|
||||
'uri' => '/res/7568aa22/rsrc/js/application/owners/owners-path-editor.js',
|
||||
'type' => 'js',
|
||||
'requires' =>
|
||||
array(
|
||||
0 => 'owners-path-editor',
|
||||
1 => 'javelin-lib-dev',
|
||||
),
|
||||
'disk' => '/rsrc/js/application/owners/owners-path-editor.js',
|
||||
),
|
||||
'javelin-magical-init' =>
|
||||
array(
|
||||
'uri' => '/res/76614f84/rsrc/js/javelin/init.dev.js',
|
||||
|
|
|
@ -124,7 +124,7 @@ final class DarkConsoleCore {
|
|||
$panel_markup[] = javelin_render_tag(
|
||||
'div',
|
||||
array(
|
||||
'class' => 'dark-console-panel',
|
||||
'class' => 'dark-console-panel dark-console-panel-'.$key,
|
||||
'style' => $style,
|
||||
'sigil' => 'dark-console-panel',
|
||||
),
|
||||
|
|
|
@ -46,39 +46,62 @@ class DarkConsoleErrorLogPlugin extends DarkConsolePlugin {
|
|||
$data = $this->getData();
|
||||
|
||||
$rows = array();
|
||||
foreach ($data as $row) {
|
||||
switch ($row['event']) {
|
||||
case 'error':
|
||||
$details = '';
|
||||
|
||||
foreach ($data as $index => $row) {
|
||||
$file = $row['file'];
|
||||
$line = $row['line'];
|
||||
break;
|
||||
case 'exception':
|
||||
$file = $row['exception']->getFile();
|
||||
$line = $row['exception']->getLine();
|
||||
break;
|
||||
|
||||
$tag = phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'onclick' => jsprintf('show_details(%d)', $index),
|
||||
),
|
||||
phutil_escape_html($row['str'].' at ['.basename($file).':'.$line.']'));
|
||||
$rows[] = array($tag);
|
||||
|
||||
$details .=
|
||||
'<div class="dark-console-panel-error-details" id="row-details-'.
|
||||
$index.'">'.
|
||||
phutil_escape_html($row['details'])."\n".
|
||||
'Stack trace:'."\n";
|
||||
|
||||
foreach ($row['trace'] as $key => $entry) {
|
||||
$line = '';
|
||||
if (isset($entry['class'])) {
|
||||
$line .= $entry['class'].'::';
|
||||
}
|
||||
$line .= idx($entry, 'function', '');
|
||||
$onclick = '';
|
||||
if (isset($entry['file'])) {
|
||||
$line .= ' called at ['.$entry['file'].':'.$entry['line'].']';
|
||||
$onclick = jsprintf(
|
||||
'open_file(%s, %d)', $entry['file'], $entry['line']);
|
||||
}
|
||||
|
||||
$details .= phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'onclick' => $onclick,
|
||||
),
|
||||
phutil_escape_html($line));
|
||||
$details .= "\n";
|
||||
}
|
||||
|
||||
$rows[] = array(
|
||||
basename($file).':'.$line,
|
||||
$row['str'],
|
||||
);
|
||||
$details .= '</div>';
|
||||
}
|
||||
|
||||
$table = new AphrontTableView($rows);
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
null,
|
||||
'wide wrap',
|
||||
));
|
||||
$table->setHeaders(
|
||||
array(
|
||||
'File',
|
||||
'Error',
|
||||
));
|
||||
$table->setClassName('error-log');
|
||||
$table->setHeaders(array('Error'));
|
||||
$table->setNoDataString('No errors.');
|
||||
|
||||
return $table->render();
|
||||
return '<div>'.
|
||||
'<div>'.$table->render().'</div>'.
|
||||
'<div class="dark-console-panel-error-separator"></div>'.
|
||||
'<pre class="PhabricatorMonospaced">'.
|
||||
$details.'</pre>'.
|
||||
'</div>';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,5 +10,9 @@ phutil_require_module('phabricator', 'aphront/console/plugin/base');
|
|||
phutil_require_module('phabricator', 'aphront/console/plugin/errorlog/api');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
phutil_require_module('phutil', 'xsprintf/jsprintf');
|
||||
|
||||
|
||||
phutil_require_source('DarkConsoleErrorLogPlugin.php');
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
class DarkConsoleErrorLogPluginAPI {
|
||||
|
||||
private static $errors = array();
|
||||
|
@ -30,29 +31,50 @@ class DarkConsoleErrorLogPluginAPI {
|
|||
return self::$errors;
|
||||
}
|
||||
|
||||
public static function handleError($num, $str, $file, $line, $cxt) {
|
||||
if (!self::$discardMode) {
|
||||
self::$errors[] = array(
|
||||
'event' => 'error',
|
||||
'num' => $num,
|
||||
'str' => $str,
|
||||
'file' => $file,
|
||||
'line' => $line,
|
||||
'cxt' => $cxt,
|
||||
'trace' => debug_backtrace(),
|
||||
);
|
||||
}
|
||||
error_log("{$file}:{$line} {$str}");
|
||||
public static function handleErrors($event, $value, $metadata) {
|
||||
if (self::$discardMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
public static function handleException($ex) {
|
||||
if (!self::$discardMode) {
|
||||
switch ($event) {
|
||||
case PhutilErrorHandler::EXCEPTION:
|
||||
// $value is of type Exception
|
||||
self::$errors[] = array(
|
||||
'event' => 'exception',
|
||||
'exception' => $ex,
|
||||
'details' => $value->getMessage(),
|
||||
'event' => $event,
|
||||
'file' => $value->getFile(),
|
||||
'line' => $value->getLine(),
|
||||
'str' => $value->getMessage(),
|
||||
'trace' => $metadata['trace'],
|
||||
);
|
||||
break;
|
||||
case PhutilErrorHandler::ERROR:
|
||||
// $value is a simple string
|
||||
self::$errors[] = array(
|
||||
'details' => $value,
|
||||
'event' => $event,
|
||||
'file' => $metadata['file'],
|
||||
'line' => $metadata['line'],
|
||||
'str' => $value,
|
||||
'trace' => $metadata['trace'],
|
||||
);
|
||||
break;
|
||||
case PhutilErrorHandler::PHLOG:
|
||||
// $value can be anything
|
||||
self::$errors[] = array(
|
||||
'details' => PhutilReadableSerializer::printShallow($value, 3),
|
||||
'event' => $event,
|
||||
'file' => $metadata['file'],
|
||||
'line' => $metadata['line'],
|
||||
'str' => PhutilReadableSerializer::printShort($value),
|
||||
'trace' => $metadata['trace'],
|
||||
);
|
||||
break;
|
||||
default:
|
||||
error_log('Unknown event : '.$event);
|
||||
break;
|
||||
}
|
||||
error_log($ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -6,5 +6,8 @@
|
|||
|
||||
|
||||
|
||||
phutil_require_module('phutil', 'error');
|
||||
phutil_require_module('phutil', 'readableserializer');
|
||||
|
||||
|
||||
phutil_require_source('DarkConsoleErrorLogPluginAPI.php');
|
||||
|
|
|
@ -101,6 +101,9 @@ class PhabricatorStandardPageView extends AphrontPageView {
|
|||
array(
|
||||
'uri' => '/~/',
|
||||
));
|
||||
|
||||
// Change this to initBehavior when there is some behavior to initialize
|
||||
require_celerity_resource('javelin-behavior-error-log');
|
||||
}
|
||||
|
||||
$this->bodyContent = $this->renderChildren();
|
||||
|
|
|
@ -71,6 +71,11 @@ $tz = PhabricatorEnv::getEnvConfig('phabricator.timezone');
|
|||
if ($tz) {
|
||||
date_default_timezone_set($tz);
|
||||
}
|
||||
phutil_require_module('phabricator', 'aphront/console/plugin/errorlog/api');
|
||||
phutil_require_module('phutil', 'error');
|
||||
|
||||
PhutilErrorHandler::setErrorListener(
|
||||
array('DarkConsoleErrorLogPluginAPI', 'handleErrors'));
|
||||
|
||||
foreach (PhabricatorEnv::getEnvConfig('load-libraries') as $library) {
|
||||
phutil_load_library($library);
|
||||
|
@ -89,6 +94,7 @@ switch ($host) {
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
$application->setHost($host);
|
||||
$application->setPath($path);
|
||||
$application->willBuildRequest();
|
||||
|
@ -126,6 +132,7 @@ foreach ($headers as $header) {
|
|||
header("{$header}: {$value}");
|
||||
}
|
||||
|
||||
|
||||
// TODO: This shouldn't be possible in a production-configured environment.
|
||||
if (isset($_REQUEST['__profile__']) &&
|
||||
($_REQUEST['__profile__'] == 'all')) {
|
||||
|
|
|
@ -70,3 +70,20 @@ a.dark-console-tab-selected {
|
|||
.dark-console .aphront-table-view tr.no-data td {
|
||||
color: #dddddd;
|
||||
}
|
||||
|
||||
.dark-console-panel-ErrorLog {
|
||||
max-height: 500px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.dark-console-panel-error-details {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dark-console-panel-error-separator {
|
||||
background-color: #e8e8e8;
|
||||
border-bottom: 1px solid #b7b7b7;
|
||||
border-top: 1px solid #b7b7b7;
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
|
|
22
webroot/rsrc/js/application/core/behavior-error-log.js
Normal file
22
webroot/rsrc/js/application/core/behavior-error-log.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* @provides javelin-behavior-error-log
|
||||
* @requires javelin-lib-dev
|
||||
*/
|
||||
|
||||
var current_details = null;
|
||||
|
||||
function open_file(file, row) {
|
||||
// Do some fun some here, e.g., open the diffusion page for the file
|
||||
// or open the file in an editor
|
||||
}
|
||||
|
||||
function show_details(row) {
|
||||
var node = JX.$('row-details-' + row);
|
||||
|
||||
if (current_details !== null) {
|
||||
JX.$('row-details-' + current_details).style.display = 'none';
|
||||
}
|
||||
|
||||
node.style.display = 'block';
|
||||
current_details = row;
|
||||
}
|
Loading…
Reference in a new issue