/** * Log something into our log file * @param $environment = string (minimum environment state for logging this message) * @param $message = string (the message body) **/ static function Log($message = '', $environment = 'dev') { // only proceed if LogJam is enabled if (static::$enabled) { // make sure our log level matches our environment level, otherwise break out if (Director::isLive() && $environment != 'live') { return false; } else { if (Director::isTest() && ($environment != 'live' || $environment != 'test')) { return false; } } // trace the origin call $trace = SS_Backtrace::filtered_backtrace(); $trace = $trace[0]; $file = isset($trace['file']) ? $trace['file'] : ''; $line = isset($trace['line']) ? $trace['line'] : ''; // construct the line in our file $output = 'LogJam: '; $output .= $message; $output .= ' (line ' . $line . ' in ' . $file . ')'; // piggy-back PHP error_log return error_log($output); } return false; }
public function format($event) { switch ($event['priorityName']) { case 'ERR': $errorType = 'Error'; $colour = 'red'; break; case 'WARN': $errorType = 'Warning'; $colour = 'orange'; break; case 'NOTICE': $errorType = 'Notice'; $colour = 'grey'; break; default: $errorType = $event['priorityName']; $colour = 'grey'; } if (!is_array($event['message'])) { return false; } $errno = $event['message']['errno']; $errstr = $event['message']['errstr']; $errfile = $event['message']['errfile']; $errline = $event['message']['errline']; $errcontext = $event['message']['errcontext']; $data = ''; $data .= '<style type="text/css">html, body, table {font-family: sans-serif; font-size: 12px;}</style>'; $data .= "<div style=\"border: 5px {$colour} solid;\">\n"; $data .= "<p style=\"color: white; background-color: {$colour}; margin: 0\">[{$errorType}] "; $data .= nl2br(htmlspecialchars($errstr)) . "<br />{$errfile}:{$errline}\n<br />\n<br />\n</p>\n"; // Render the provided backtrace $data .= SS_Backtrace::get_rendered_backtrace($errcontext); // Compile extra data $blacklist = array('message', 'timestamp', 'priority', 'priorityName'); $extras = array_diff_key($event, array_combine($blacklist, $blacklist)); if ($extras) { $data .= "<h3>Details</h3>\n"; $data .= "<table class=\"extras\">\n"; foreach ($extras as $k => $v) { if (is_array($v)) { $v = var_export($v, true); } $data .= sprintf("<tr><td><strong>%s</strong></td><td><pre>%s</pre></td></tr>\n", $k, $v); } $data .= "</table>\n"; } $data .= "</div>\n"; $relfile = Director::makeRelative($errfile); if ($relfile && $relfile[0] == '/') { $relfile = substr($relfile, 1); } $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : null; $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null; $subject = "[{$errorType}] in {$relfile}:{$errline} (http://{$host}{$uri})"; return array('subject' => $subject, 'data' => $data); }
public function testIgnoredFunctionArgs() { $bt = array(array('type' => '->', 'file' => 'MyFile.php', 'line' => 99, 'function' => 'myIgnoredGlobalFunction', 'args' => array('password' => 'secred')), array('class' => 'MyClass', 'type' => '->', 'file' => 'MyFile.php', 'line' => 99, 'function' => 'myIgnoredClassFunction', 'args' => array('password' => 'secred')), array('class' => 'MyClass', 'type' => '->', 'file' => 'MyFile.php', 'line' => 99, 'function' => 'myFunction', 'args' => array('myarg' => 'myval'))); $orig = Config::inst()->get('SS_Backtrace', 'ignore_function_args'); Config::inst()->update('SS_Backtrace', 'ignore_function_args', array(array('MyClass', 'myIgnoredClassFunction'), 'myIgnoredGlobalFunction')); $filtered = SS_Backtrace::filter_backtrace($bt); $this->assertEquals('<filtered>', $filtered[0]['args']['password'], 'Filters global functions'); $this->assertEquals('<filtered>', $filtered[1]['args']['password'], 'Filters class functions'); $this->assertEquals('myval', $filtered[2]['args']['myarg'], 'Doesnt filter other functions'); Config::inst()->remove('SS_Backtrace', 'ignore_function_args'); Config::inst()->update('SS_Backtrace', 'ignore_function_args', $orig); }
public function testIgnoredFunctionArgs() { $orig = SS_Backtrace::$ignore_function_args; $bt = array(array('type' => '->', 'file' => 'MyFile.php', 'line' => 99, 'function' => 'myIgnoredGlobalFunction', 'args' => array('password' => 'secred')), array('class' => 'MyClass', 'type' => '->', 'file' => 'MyFile.php', 'line' => 99, 'function' => 'myIgnoredClassFunction', 'args' => array('password' => 'secred')), array('class' => 'MyClass', 'type' => '->', 'file' => 'MyFile.php', 'line' => 99, 'function' => 'myFunction', 'args' => array('myarg' => 'myval'))); SS_Backtrace::$ignore_function_args[] = array('MyClass', 'myIgnoredClassFunction'); SS_Backtrace::$ignore_function_args[] = 'myIgnoredGlobalFunction'; $filtered = SS_Backtrace::filter_backtrace($bt); $this->assertEquals('<filtered>', $filtered[0]['args']['password'], 'Filters global functions'); $this->assertEquals('<filtered>', $filtered[1]['args']['password'], 'Filters class functions'); $this->assertEquals('myval', $filtered[2]['args']['myarg'], 'Doesnt filter other functions'); SS_Backtrace::$ignore_function_args = $orig; }
public function format($event) { switch ($event['priorityName']) { case 'ERR': $errorType = 'Error'; break; case 'WARN': $errorType = 'Warning'; break; case 'NOTICE': $errorType = 'Notice'; break; default: $errorType = $event['priorityName']; } if (!is_array($event['message'])) { return false; } $errno = $event['message']['errno']; $errstr = $event['message']['errstr']; $errfile = $event['message']['errfile']; $errline = $event['message']['errline']; $errcontext = $event['message']['errcontext']; $protocol = 'http'; if (isset($_SERVER['HTTPS'])) { $protocol = 'https'; } $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : null; $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null; $relfile = Director::makeRelative($errfile); if ($relfile && $relfile[0] == '/') { $relfile = substr($relfile, 1); } $data = "[{$errorType}] in {$relfile}:{$errline} ({$protocol}://{$host}{$uri})\n"; // Render the provided backtrace $data .= SS_Backtrace::get_rendered_backtrace($errcontext, true); // Compile extra data $blacklist = array('message', 'timestamp', 'priority', 'priorityName'); $extras = array_diff_key($event, array_combine($blacklist, $blacklist)); if ($extras) { $data .= "DETAILS\n\n"; foreach ($extras as $k => $v) { if (is_array($v)) { $v = var_export($v, true); } $data .= sprintf("[%s]\n%s\n\n", strtoupper($k), $v); } } $subject = "[{$errorType}] in {$relfile}:{$errline} ({$host})"; return array('subject' => $subject, 'data' => $data); }
public function format($event) { switch ($event['priorityName']) { case 'ERR': $errorType = 'Error'; $colour = 'red'; break; case 'WARN': $errorType = 'Warning'; $colour = 'orange'; break; case 'NOTICE': $errorType = 'Notice'; $colour = 'grey'; break; } if (!is_array($event['message'])) { return false; } $errno = $event['message']['errno']; $errstr = $event['message']['errstr']; $errfile = $event['message']['errfile']; $errline = $event['message']['errline']; $errcontext = $event['message']['errcontext']; $ref = @$_SERVER['HTTP_REFERER']; if (empty($ref)) { $ref = 'N/A'; } if (!empty($_SERVER['HTTP_CLIENT_IP'])) { $ip = $_SERVER['HTTP_CLIENT_IP']; } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; } else { $ip = $_SERVER['REMOTE_ADDR']; } $data = "<div style=\"border: 5px {$colour} solid\">\n"; $data .= "<p style=\"color: white; background-color: {$colour}; margin: 0\">HTTP_REFERER :{$ref} - CLIENT_IP : {$ip} <br/>{$errorType}: {$errstr}<br/> At line {$errline} in {$errfile}\n<br />\n<br />\n</p>\n"; // Get a backtrace, filtering out debug method calls $data .= SS_Backtrace::backtrace(true, false, array('SS_LogErrorEmailFormatter->format', 'SS_LogEmailWriter->_write')); $data .= "</div>\n"; $relfile = Director::makeRelative($errfile); if ($relfile[0] == '/') { $relfile = substr($relfile, 1); } $subject = "{$errorType} at {$relfile} line {$errline} (http://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']})"; return array('subject' => $subject, 'data' => $data); }
/** * Get the alfresco seamistrepository connector. * * This is used by this object directly, but also * via AlfrescoContentItems via composition * * @return SeaMistRepository */ public function getRemoteRepository() { // For the first batch, just get all the immediate children of the // top level $repo = SeaMist::getInstance()->getRepository('Alfresco', $this->ID); if (!$repo->isConnected() && $this->ApiUrl) { $config = array('apiUrl' => $this->ApiUrl, 'username' => $this->Username, 'password' => $this->Password); try { $repo->connect($config); } catch (Zend_Uri_Exception $zue) { error_log("Failed connecting to repository: " . $zue->getMessage() . "\n" . SS_Backtrace::backtrace(true)); } catch (FailedRequestException $fre) { error_log("Failed request: " . $fre->getMessage()); } } return $repo; }
/** * Get the Cmis seamistrepository connector. * * This is used by this object directly, but also * via CmisContentItems via composition * * @return SeaMistRepository */ public function getRemoteRepository() { // For the first batch, just get all the immediate children of the // top level if (!$this->RepositoryType) { return null; } $repo = SeaMist::getInstance()->getRepository($this->RepositoryType, $this->ID); if (!$repo->isConnected() && $this->RepositoryInfoUrl) { try { $repo->connect($this->RepositoryInfoUrl, $this->RootNodeUrl, $this->Username, $this->Password); } catch (Zend_Uri_Exception $zue) { error_log("Failed connecting to repository: " . $zue->getMessage() . "\n" . SS_Backtrace::backtrace(true)); } catch (FailedRequestException $fre) { error_log("Failed request: " . $fre->getMessage()); } } return $repo; }
/** * Write a backtrace */ function writeTrace($trace = null) { echo "Trace\n=====\n"; echo SS_Backtrace::get_rendered_backtrace($trace ? $trace : debug_backtrace(), true); }
/** * Writes a status message to the output stream in a user readable HTML format * @param string $name Name of the object that generated the error * @param string $message Message of the error * @param array $trace Stacktrace */ protected function writeResultError($name, $message, $trace) { echo "<div class=\"failure\"><h2 class=\"test-case\">⊗ " . $this->testNameToPhrase($name) . "</h2>"; echo "<pre>" . htmlentities($message, ENT_COMPAT, 'UTF-8') . "</pre>"; echo SS_Backtrace::get_rendered_backtrace($trace); echo "</div>"; }
/** * Display error bar if it exists */ public function writeResults() { $passCount = 0; $failCount = 0; $testCount = 0; $incompleteCount = 0; $errorCount = 0; foreach ($this->suiteResults['suites'] as $suite) { foreach ($suite['tests'] as $test) { $testCount++; if ($test['status'] == 2) { $incompleteCount++; } elseif ($test['status'] == 1) { $passCount++; } else { $failCount++; } if ($test['status'] != 1) { echo "<div class=\"failure\"><h2 class=\"test-case\">⊗ " . $this->testNameToPhrase($test['name']) . "</h2>"; echo "<pre>" . htmlentities($test['message'], ENT_COMPAT, 'UTF-8') . "</pre>"; echo SS_Backtrace::get_rendered_backtrace($test['trace']); echo "</div>"; } } } $result = $failCount > 0 ? 'fail' : 'pass'; echo "<div class=\"status {$result}\">"; echo "<h2><span>{$testCount}</span> tests run: <span>{$passCount}</span> passes, <span>{$failCount}</span> failures, and <span>{$incompleteCount}</span> incomplete</h2>"; echo "</div>"; }
protected function writeTest($test) { if ($test['status'] != TEST_SUCCESS) { $filteredTrace = array(); $ignoredClasses = array('TestRunner'); foreach ($test['trace'] as $item) { if (isset($item['file']) && strpos($item['file'], 'PHPUnit/Framework') === false && (!isset($item['class']) || !in_array($item['class'], $ignoredClasses))) { $filteredTrace[] = $item; } if (isset($item['class']) && isset($item['function']) && $item['class'] == 'PHPUnit_Framework_TestSuite' && $item['function'] == 'run') { break; } } $color = $test['status'] == 2 ? 'yellow' : 'red'; echo "\n" . SS_Cli::text($test['name'] . "\n" . $test['message'] . "\n", $color, null); echo SS_Backtrace::get_rendered_backtrace($filteredTrace, true); echo "--------------------\n"; } }
/** * Dispatch a message by priority level. * * The message parameter can be either a string (a simple error * message), or an array of variables. The latter is useful for passing * along a list of debug information for the writer to handle, such as * error code, error line, error context (backtrace). * * @param mixed $message Exception object or array of error context variables * @param const $priority Priority. Possible values: SS_Log::ERR, SS_Log::WARN or SS_Log::NOTICE * @param mixed $extras Extra information to log in event */ public static function log($message, $priority, $extras = null) { if ($message instanceof Exception) { $message = array('errno' => '', 'errstr' => $message->getMessage(), 'errfile' => $message->getFile(), 'errline' => $message->getLine(), 'errcontext' => $message->getTrace()); } elseif (is_string($message)) { $trace = SS_Backtrace::filtered_backtrace(); $lastTrace = $trace[0]; $message = array('errno' => '', 'errstr' => $message, 'errfile' => @$lastTrace['file'], 'errline' => @$lastTrace['line'], 'errcontext' => $trace); } try { self::get_logger()->log($message, $priority, $extras); } catch (Exception $e) { // @todo How do we handle exceptions thrown from Zend_Log? // For example, an exception is thrown if no writers are added } }
/** * Set the environment type of the current site. * * Typically, a SilverStripe site have a number of environments: * - development environments, such a copy on your local machine. * - test sites, such as the one you show the client before going live. * - the live site itself. * * The behaviour of these environments often varies slightly. For example, development sites may have errors dumped to the screen, * and order confirmation emails might be sent to the developer instead of the client. * * To help with this, Sapphire support the notion of an environment type. The environment type can be dev, test, or live. * * You can set it explicitly with Director::set_environment_tpye(). Or you can use {@link Director::set_dev_servers()} and {@link Director::set_test_servers()} * to set it implicitly, based on the value of $_SERVER['HTTP_HOST']. If the HTTP_HOST value is one of the servers listed, then * the environment type will be test or dev. Otherwise, the environment type will be live. * * Dev mode can also be forced by putting ?isDev=1 in your URL, which will ask you to log in and then push the site into dev * mode for the remainder of the session. Putting ?isDev=0 onto the URL can turn it back. * * Test mode can also be forced by putting ?isTest=1 in your URL, which will ask you to log in and then push the site into test * mode for the remainder of the session. Putting ?isTest=0 onto the URL can turn it back. * * Generally speaking, these methods will be called from your _config.php file. * * Once the environment type is set, it can be checked with {@link Director::isDev()}, {@link Director::isTest()}, and * {@link Director::isLive()}. * * @param $et string The environment type: dev, test, or live. */ static function set_environment_type($et) { if ($et != 'dev' && $et != 'test' && $et != 'live') { SS_Backtrace::backtrace(); user_error("Director::set_environment_type passed '{$et}'. It should be passed dev, test, or live", E_USER_WARNING); } else { self::$environment_type = $et; } }
/** * Display error bar if it exists */ public function writeResults() { $passCount = 0; $failCount = 0; $testCount = 0; $errorCount = 0; foreach ($this->suiteResults['suites'] as $suite) { foreach ($suite['tests'] as $test) { $testCount++; $test['status'] == 1 ? $passCount++ : $failCount++; if ($test['status'] != 1) { echo "<div class=\"failure\"><span>⊗ " . $this->testNameToPhrase($test['name']) . "</span><br>"; echo "<pre>" . htmlentities($test['message']) . "</pre><br>"; echo SS_Backtrace::get_rendered_backtrace($test['trace']); echo "</div>"; } } } $result = $failCount > 0 ? 'fail' : 'pass'; echo "<div class=\"{$result}\">"; echo "<h2><span>{$testCount}</span> tests run: <span>{$passCount}</span> passes, <span>{$failCount}</span> fails, and <span>0</span> exceptions</h2>"; echo "</div>"; }
/** * Write a backtrace */ public function renderTrace($trace = null) { $output = "Trace\n=====\n"; $output .= SS_Backtrace::get_rendered_backtrace($trace ? $trace : debug_backtrace(), true); return $output; }
/** * Write a backtrace */ function writeTrace($trace) { echo '<h3>Trace</h3>'; echo SS_Backtrace::get_rendered_backtrace($trace); echo '</div>'; }
/** * Render a call track * * @param array $trace The debug_backtrace() array * @return string */ public function renderTrace($trace) { $output = '<h3>Trace</h3>'; $output .= SS_Backtrace::get_rendered_backtrace($trace); $output .= '</div>'; return $output; }
function testFullFuncNameWithArgsAndCustomCharLimit() { $func = array('class' => 'MyClass', 'type' => '->', 'file' => 'MyFile.php', 'line' => 99, 'function' => 'myFunction', 'args' => array('number' => 1, 'mylongstring' => 'more than 20 characters 1234567890')); $this->assertEquals('MyClass->myFunction(1,more than 20 charact...)', SS_Backtrace::full_func_name($func, true, 20)); }
/** * @deprecated 2.5 Please use {@link SS_Backtrace::get_rendered_backtrace()} */ static function get_rendered_backtrace($bt, $plainText = false) { Deprecation::notice('2.5', 'Use SS_Backtrace::get_rendered_backtrace() instead.'); return SS_Backtrace::get_rendered_backtrace($bt, $plainText); }
/** * @deprecated 2.5 Please use {@link SS_Backtrace::get_rendered_backtrace()} */ static function get_rendered_backtrace($bt, $plainText = false) { user_error('Debug::get_rendered_backtrace() is deprecated. Please use SS_Backtrace::get_rendered_backtrace() instead', E_USER_NOTICE); return SS_Backtrace::get_rendered_backtrace($bt, $plainText); }
protected function writeTest($test) { if ($test['status'] != 1) { $filteredTrace = array(); $ignoredClasses = array('TestRunner'); foreach ($test['trace'] as $item) { if (isset($item['file']) && strpos($item['file'], 'PHPUnit/Framework') === false && (!isset($item['class']) || !in_array($item['class'], $ignoredClasses))) { $filteredTrace[] = $item; } if (isset($item['class']) && isset($item['function']) && $item['class'] == 'PHPUnit_Framework_TestSuite' && $item['function'] == 'run') { break; } } echo "\n\n" . SS_Cli::text($this->testNameToPhrase($test['name']) . "\n" . $test['message'] . "\n", 'red', null, true); echo SS_Cli::text("In line {$test['exception']['line']} of {$test['exception']['file']}" . "\n\n", 'red'); echo SS_Backtrace::get_rendered_backtrace($filteredTrace, true); echo "\n--------------------\n"; } }