1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-12-02 03:32:41 +01:00

[Wilds] Shove the logging stuff into a bit of an abstraction before it gets out of control

Summary:
Ref T13098. The logging stuff is starting to get a little sketchy, so wrap it in several layers of class-based indirection before it can escape its cage.

This at least gives us an actual API and structure to work with later instead of scattering a lot of `fprintf(STDERR, ....)` all over the place.

Test Plan: Ran a few commands, got slightly more sensible/consistent logging out of them.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13098

Differential Revision: https://secure.phabricator.com/D19699
This commit is contained in:
epriestley 2018-09-20 15:28:19 -07:00
parent e6c37bd4b3
commit b6f93a46d7
10 changed files with 186 additions and 46 deletions

View file

@ -311,6 +311,8 @@ phutil_register_library_map(array(
'ArcanistListConfigOption' => 'config/option/ArcanistListConfigOption.php', 'ArcanistListConfigOption' => 'config/option/ArcanistListConfigOption.php',
'ArcanistListWorkflow' => 'workflow/ArcanistListWorkflow.php', 'ArcanistListWorkflow' => 'workflow/ArcanistListWorkflow.php',
'ArcanistLocalConfigurationSource' => 'config/source/ArcanistLocalConfigurationSource.php', 'ArcanistLocalConfigurationSource' => 'config/source/ArcanistLocalConfigurationSource.php',
'ArcanistLogEngine' => 'log/ArcanistLogEngine.php',
'ArcanistLogMessage' => 'log/ArcanistLogMessage.php',
'ArcanistLogicalOperatorsXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistLogicalOperatorsXHPASTLinterRule.php', 'ArcanistLogicalOperatorsXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistLogicalOperatorsXHPASTLinterRule.php',
'ArcanistLogicalOperatorsXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistLogicalOperatorsXHPASTLinterRuleTestCase.php', 'ArcanistLogicalOperatorsXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistLogicalOperatorsXHPASTLinterRuleTestCase.php',
'ArcanistLowercaseFunctionsXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistLowercaseFunctionsXHPASTLinterRule.php', 'ArcanistLowercaseFunctionsXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistLowercaseFunctionsXHPASTLinterRule.php',
@ -1416,6 +1418,8 @@ phutil_register_library_map(array(
'ArcanistListConfigOption' => 'ArcanistConfigOption', 'ArcanistListConfigOption' => 'ArcanistConfigOption',
'ArcanistListWorkflow' => 'ArcanistWorkflow', 'ArcanistListWorkflow' => 'ArcanistWorkflow',
'ArcanistLocalConfigurationSource' => 'ArcanistWorkingCopyConfigurationSource', 'ArcanistLocalConfigurationSource' => 'ArcanistWorkingCopyConfigurationSource',
'ArcanistLogEngine' => 'Phobject',
'ArcanistLogMessage' => 'Phobject',
'ArcanistLogicalOperatorsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistLogicalOperatorsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistLogicalOperatorsXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistLogicalOperatorsXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistLowercaseFunctionsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistLowercaseFunctionsXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',

View file

@ -131,7 +131,7 @@ final class ArcanistConfigurationSourceList
return $this->configOptions; return $this->configOptions;
} }
public function validateConfiguration() { public function validateConfiguration(ArcanistRuntime $runtime) {
$options = $this->getConfigOptions(); $options = $this->getConfigOptions();
$aliases = array(); $aliases = array();
@ -158,7 +158,7 @@ final class ArcanistConfigurationSourceList
// for config files we emit a warning; for "--config" we fatal. // for config files we emit a warning; for "--config" we fatal.
if (!$option) { if (!$option) {
$source->didReadUnknownOption($key); $source->didReadUnknownOption($runtime, $key);
continue; continue;
} }

View file

@ -22,18 +22,13 @@ abstract class ArcanistConfigurationSource
return false; return false;
} }
public function didReadUnknownOption($key) { public function didReadUnknownOption(ArcanistRuntime $runtime, $key) {
// TOOLSETS: Standardize this kind of messaging? On ArcanistRuntime? $runtime->getLogEngine()->writeWarning(
pht('UNKNOWN CONFIGURATION'),
fprintf(
STDERR,
tsprintf(
"<bg:yellow>** %s **</bg> %s\n",
pht('WARNING'),
pht( pht(
'Ignoring unrecognized configuration option ("%s") from source: %s.', 'Ignoring unrecognized configuration option ("%s") from source: %s.',
$key, $key,
$this->getSourceDisplayName()))); $this->getSourceDisplayName()));
} }
} }

View file

@ -30,7 +30,7 @@ final class ArcanistRuntimeConfigurationSource
parent::__construct($map); parent::__construct($map);
} }
public function didReadUnknownOption($key) { public function didReadUnknownOption(ArcanistRuntime $runtime, $key) {
throw new PhutilArgumentUsageException( throw new PhutilArgumentUsageException(
pht( pht(
'Configuration option ("%s") specified with "--config" flag is not '. 'Configuration option ("%s") specified with "--config" flag is not '.

View file

@ -81,6 +81,11 @@ final class ArcanistUSEnglishTranslation extends PhutilTranslation {
'This commit will be landed:', 'This commit will be landed:',
'These commits will be landed:', 'These commits will be landed:',
), ),
'Updated %s librarie(s).' => array(
'Updated library.',
'Updated %s libraries.',
),
); );
} }

View file

@ -0,0 +1,81 @@
<?php
final class ArcanistLogEngine
extends Phobject {
private $showTraceMessages;
public function setShowTraceMessages($show_trace_messages) {
$this->showTraceMessages = $show_trace_messages;
return $this;
}
public function getShowTraceMessages() {
return $this->showTraceMessages;
}
public function newMessage() {
return new ArcanistLogMessage();
}
public function writeMessage(ArcanistLogMessage $message) {
$color = $message->getColor();
fprintf(
STDERR,
'%s',
tsprintf(
"**<bg:".$color."> %s </bg>** %s\n",
$message->getLabel(),
$message->getMessage()));
return $message;
}
public function writeWarning($label, $message) {
return $this->writeMessage(
$this->newMessage()
->setColor('yellow')
->setLabel($label)
->setMessage($message));
}
public function writeError($label, $message) {
return $this->writeMessage(
$this->newMessage()
->setColor('red')
->setLabel($label)
->setMessage($message));
}
public function writeSuccess($label, $message) {
return $this->writeMessage(
$this->newMessage()
->setColor('green')
->setLabel($label)
->setMessage($message));
}
public function writeStatus($label, $message) {
return $this->writeMessage(
$this->newMessage()
->setColor('blue')
->setLabel($label)
->setMessage($message));
}
public function writeTrace($label, $message) {
$trace = $this->newMessage()
->setColor('magenta')
->setLabel($label)
->setMessage($message);
if ($this->getShowTraceMessages()) {
$this->writeMessage($trace);
}
return $trace;
}
}

View file

@ -0,0 +1,48 @@
<?php
final class ArcanistLogMessage
extends Phobject {
private $label;
private $message;
private $color;
private $channel;
public function setLabel($label) {
$this->label = $label;
return $this;
}
public function getLabel() {
return $this->label;
}
public function setColor($color) {
$this->color = $color;
return $this;
}
public function getColor() {
return $this->color;
}
public function setChannel($channel) {
$this->channel = $channel;
return $this;
}
public function getChannel() {
return $this->channel;
}
public function setMessage($message) {
$this->message = $message;
return $this;
}
public function getMessage() {
return $this->message;
}
}

View file

@ -185,4 +185,8 @@ abstract class ArcanistWorkflow extends Phobject {
return $this->conduitEngine; return $this->conduitEngine;
} }
final protected function getLogEngine() {
return $this->getRuntime()->getLogEngine();
}
} }

View file

@ -31,6 +31,8 @@ EOTEXT
} }
public function runWorkflow() { public function runWorkflow() {
$log = $this->getLogEngine();
$argv = $this->getArgument('argv'); $argv = $this->getArgument('argv');
if (count($argv) > 1) { if (count($argv) > 1) {
throw new ArcanistUsageException( throw new ArcanistUsageException(
@ -38,6 +40,10 @@ EOTEXT
'Provide only one path to "arc liberate". The path should identify '. 'Provide only one path to "arc liberate". The path should identify '.
'a directory where you want to create or update a library.')); 'a directory where you want to create or update a library.'));
} else if (!$argv) { } else if (!$argv) {
$log->writeStatus(
pht('SCAN'),
pht('Searching for libraries in the current working directory...'));
$init_files = id(new FileFinder(getcwd())) $init_files = id(new FileFinder(getcwd()))
->withPath('*/__phutil_library_init__.php') ->withPath('*/__phutil_library_init__.php')
->find(); ->find();
@ -60,9 +66,16 @@ EOTEXT
} }
foreach ($paths as $path) { foreach ($paths as $path) {
$log->writeStatus(
pht('WORK'),
pht('Updating library: %s', Filesystem::readablePath($path)));
$this->liberatePath($path); $this->liberatePath($path);
} }
$log->writeSuccess(
pht('DONE'),
pht('Updated %s librarie(s).', phutil_count($paths)));
return 0; return 0;
} }

View file

@ -3,6 +3,7 @@
final class ArcanistRuntime { final class ArcanistRuntime {
private $workflows; private $workflows;
private $logEngine;
public function execute(array $argv) { public function execute(array $argv) {
@ -19,28 +20,23 @@ final class ArcanistRuntime {
->setLocale(PhutilLocale::loadLocale('en_US')) ->setLocale(PhutilLocale::loadLocale('en_US'))
->setTranslations(PhutilTranslation::getTranslationMapForLocale('en_US')); ->setTranslations(PhutilTranslation::getTranslationMapForLocale('en_US'));
$log = new ArcanistLogEngine();
$this->logEngine = $log;
try { try {
return $this->executeCore($argv); return $this->executeCore($argv);
} catch (ArcanistConduitException $ex) { } catch (ArcanistConduitException $ex) {
fwrite( $log->writeError(pht('CONDUIT'), $ex->getMessage());
STDERR,
tsprintf(
"**%s:** %s\n",
pht('Conduit Exception'),
$ex->getMessage()));
} catch (PhutilArgumentUsageException $ex) { } catch (PhutilArgumentUsageException $ex) {
fwrite( $log->writeError(pht('USAGE EXCEPTION'), $ex->getMessage());
STDERR,
tsprintf(
"**%s:** %s\n",
pht('Usage Exception'),
$ex->getMessage()));
return 77;
} }
return 1;
} }
private function executeCore(array $argv) { private function executeCore(array $argv) {
$log = $this->getLogEngine();
$config_args = array( $config_args = array(
array( array(
'name' => 'library', 'name' => 'library',
@ -68,9 +64,9 @@ final class ArcanistRuntime {
->parseStandardArguments(); ->parseStandardArguments();
$is_trace = $args->getArg('trace'); $is_trace = $args->getArg('trace');
if ($is_trace) { $log->setShowTraceMessages($is_trace);
$this->logTrace(pht('ARGV'), csprintf('%Ls', $argv));
} $log->writeTrace(pht('ARGV'), csprintf('%Ls', $argv));
$args->parsePartial($config_args, true); $args->parsePartial($config_args, true);
@ -83,7 +79,7 @@ final class ArcanistRuntime {
// Do this before continuing since configuration can impact other // Do this before continuing since configuration can impact other
// behaviors immediately and we want to catch any issues right away. // behaviors immediately and we want to catch any issues right away.
$config->setConfigOptions($config_engine->newConfigOptionsMap()); $config->setConfigOptions($config_engine->newConfigOptionsMap());
$config->validateConfiguration(); $config->validateConfiguration($this);
$toolset = $this->newToolset($argv); $toolset = $this->newToolset($argv);
@ -483,32 +479,26 @@ final class ArcanistRuntime {
return $map; return $map;
} }
private function logTrace($label, $message) {
echo tsprintf(
"**<bg:magenta> %s </bg>** %s\n",
$label,
$message);
}
public function getWorkflows() { public function getWorkflows() {
return $this->workflows; return $this->workflows;
} }
public function getLogEngine() {
return $this->logEngine;
}
private function applyAliasEffects(array $effects, array $argv) { private function applyAliasEffects(array $effects, array $argv) {
assert_instances_of($effects, 'ArcanistAliasEffect'); assert_instances_of($effects, 'ArcanistAliasEffect');
$log = $this->getLogEngine();
$command = null; $command = null;
$arguments = null; $arguments = null;
foreach ($effects as $effect) { foreach ($effects as $effect) {
$message = $effect->getMessage(); $message = $effect->getMessage();
if ($message !== null) { if ($message !== null) {
fprintf( $log->writeInfo(pht('ALIAS'), $message);
STDERR,
tsprintf(
"**<bg:yellow> %s </bg>** %s\n",
pht('ALIAS'),
$message));
} }
if ($effect->getCommand()) { if ($effect->getCommand()) {