From 5661e41c73cbfadd00fb2e9220f7c60edded497a Mon Sep 17 00:00:00 2001 From: Thomas Gelf Date: Wed, 22 Jan 2014 12:08:20 +0000 Subject: [PATCH] Trace option for CLI commands Added --trace to show full stack trace if an exception is thrown fixes #5555 --- library/Icinga/Cli/Command.php | 10 ++++-- library/Icinga/Cli/Loader.php | 59 ++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/library/Icinga/Cli/Command.php b/library/Icinga/Cli/Command.php index 3553305cb..6e68e6aad 100644 --- a/library/Icinga/Cli/Command.php +++ b/library/Icinga/Cli/Command.php @@ -28,8 +28,9 @@ abstract class Command $this->moduleName = $moduleName; $this->commandName = $commandName; $this->actionName = $actionName; - $this->params = $app->getParams(); - $this->screen = Screen::instance($app); + $this->params = $app->getParams(); + $this->screen = Screen::instance($app); + $this->trace = $this->params->shift('trace', false); $this->isVerbose = $this->params->shift('verbose', false); $this->isDebuging = $this->params->shift('debug', false); if ($initialize) { @@ -42,6 +43,11 @@ abstract class Command return $this->params->count() > 0; } + public function showTrace() + { + return $this->trace; + } + public function fail($msg) { throw new Exception($msg); diff --git a/library/Icinga/Cli/Loader.php b/library/Icinga/Cli/Loader.php index b818f9a2d..c93b35016 100644 --- a/library/Icinga/Cli/Loader.php +++ b/library/Icinga/Cli/Loader.php @@ -6,6 +6,7 @@ use Icinga\Application\ApplicationBootstrap as App; use Icinga\Exception\ProgrammingError; use Icinga\Cli\Params; use Icinga\Cli\Screen; +use Icinga\Cli\Command; use Icinga\Cli\Documentation; use Exception; @@ -246,6 +247,9 @@ class Loader $obj->init(); return $obj->{$this->actionName . 'Action'}(); } catch (Exception $e) { + if ($obj && $obj instanceof Command && $obj->showTrace()) { + echo $this->formatTrace($e->getTrace()); + } $this->fail($e->getMessage()); } } @@ -336,6 +340,61 @@ class Loader } } + protected function formatTrace($trace) + { + $output = array(); + foreach($trace as $i => $step) + { + $object = ''; + if (isset($step['object']) && is_object($step['object'])) { + $object = sprintf('[%s]', get_class($step['object'])) . $step['type']; + } elseif (! empty($step['object'])) { + $object = (string) $step['object'] . $step['type']; + } + if (is_array($step['args'])) + { + foreach ($step['args'] as & $arg) + { + if (is_object($arg)) + { + $arg = sprintf('[%s]', get_class($arg)); + } + if (is_string($arg)) { + $arg = preg_replace('~\n~', '\n', $arg); + if (strlen($arg) > 50) $arg = substr($arg, 0, 47) . '...'; + $arg = "'" . $arg . "'"; + } + if ($arg === null) $arg = 'NULL'; + if (is_bool($arg)) $arg = $arg ? 'TRUE' : 'FALSE'; + } + } else { + $step['args'] = array(); + } + $args = $step['args']; + foreach ($args as & $v) { + if (is_array($v)) { + $v = var_export($v, 1); + } else { + $v = (string) $v; + } + } + $output[$i] = sprintf( + '#%d %s:%d %s%s(%s)', + $i, + isset($step['file']) ? preg_replace( + '~.+/library/~', + 'library/', + $step['file'] + ) : '[unknown file]', + isset($step['line']) ? $step['line'] : '0', + $object, + $step['function'], + implode(', ', $args) + ); + } + return implode(PHP_EOL, $output) . PHP_EOL; + } + public function hasCommand($name) { return in_array($name, $this->listCommands());