Merge branch 'feature/refactor-logger-implementation-5683'

resolves #5683
This commit is contained in:
Johannes Meyer 2014-02-26 13:53:08 +01:00
commit c5faf9fa41
38 changed files with 590 additions and 692 deletions

View File

@ -28,13 +28,9 @@
// {{{ICINGA_LICENSE_HEADER}}}
// @codingStandardsIgnoreStart
use Icinga\Web\Form;
use Icinga\Web\Controller\ActionController;
use Icinga\Filter\Filter;
use Icinga\Filter\FilterAttribute;
use Icinga\Filter\Type\TextFilter;
use Icinga\Application\Logger;
use Icinga\Web\Url;
use Icinga\Logger\Logger;
/**
* Application wide interface for filtering

View File

@ -29,10 +29,9 @@
// {{{ICINGA_LICENSE_HEADER}}}
use \Zend_Controller_Action_Exception as ActionException;
use \Icinga\Web\Controller\ActionController;
use \Icinga\Application\Icinga;
use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Application\Logger;
use Icinga\Web\Controller\ActionController;
use Icinga\Application\Icinga;
use Icinga\Logger\Logger;
/**
* Delivery static content to clients
@ -104,7 +103,8 @@ class StaticController extends ActionController
if (!Icinga::app()->getModuleManager()->hasEnabled($module)) {
Logger::error(
'Non-existing frontend component "' . $module . '/' . $file
. '" was requested. The module "' . $module . '" does not exist or is not active.');
. '" was requested. The module "' . $module . '" does not exist or is not active.'
);
echo "/** Module not enabled **/";
return;
}
@ -115,7 +115,8 @@ class StaticController extends ActionController
if (!file_exists($filePath)) {
Logger::error(
'Non-existing frontend component "' . $module . '/' . $file
. '" was requested, which would resolve to the the path: ' . $filePath);
. '" was requested, which would resolve to the the path: ' . $filePath
);
echo '/** Module has no js files **/';
return;
}

View File

@ -30,9 +30,9 @@
namespace Icinga\Form\Config\Resource;
use \Zend_Config;
use \Icinga\Web\Form;
use \Icinga\Web\Form\Decorator\HelpText;
use \Icinga\Application\Logger;
use Icinga\Web\Form;
use Icinga\Logger\Logger;
use Icinga\Web\Form\Decorator\HelpText;
use Icinga\Data\ResourceFactory;
/**
@ -440,7 +440,7 @@ class EditResourceForm extends Form
if ($key !== 'resource_type' && $key !== 'resource_all_name' && $key !== 'resource_all_name_old') {
$configKey = explode('_', $key, 3);
if (sizeof($configKey) < 3) {
Logger::warn('EditResourceForm: invalid form key "' . $key . '" was ignored.');
Logger::warning('EditResourceForm: invalid form key "' . $key . '" was ignored.');
continue;
}
$result[$configKey[2]] = $value;

View File

@ -15,18 +15,30 @@ moduleFolder = "@icingaweb_config_path@/enabledModules"
; modulePath = "/vagrant/modules:/usr/share/icingaweb/modules"
[logging]
; General log
enable = "1"
enable = true
; Writing to a Stream
type = "stream"
verbose = "1"
; Write data to the following file
target = "@icingaweb_log_path@/icingaweb.log"
; Write data to a PHP stream
;target = "php://output"
; For development and debug purposes: Logs additional (non critical) events to a
; seperate log
debug.enable = "1"
debug.type = "stream"
debug.target = "@icingaweb_log_path@/icingaweb.debug.log"
; Writing to the System Log
;type = "syslog"
; Prefix all syslog messages generated with the string "Icinga Web"
;application = "Icinga Web"
;facility = "LOG_USER"
level = 1
; The default level is WARNING, which means that only events of this level and
; above will be tracked. Level numbers descend in order of importance where
; ERROR (0) is the most important level and DEBUG (3) is the least important
; level:
;
; ERROR = 0 - Error: error conditions
; WARNING = 1 - Warning: warning conditions
; INFO = 2 - Informational: informational messages
; DEBUG = 3 - Debug: debug messages
; Use ini store to store preferences on local disk
[preferences]

View File

@ -29,13 +29,15 @@
namespace Icinga\Application;
use \DateTimeZone;
use \Exception;
use \Icinga\Application\Modules\Manager as ModuleManager;
use \Icinga\Application\Config;
use \Icinga\Exception\ConfigurationError;
use \Icinga\Util\DateTimeFactory;
use \Icinga\Util\Translator;
use \DateTimeZone;
use \Zend_Config;
use Icinga\Application\Modules\Manager as ModuleManager;
use Icinga\Application\Config;
use Icinga\Exception\ConfigurationError;
use Icinga\Util\DateTimeFactory;
use Icinga\Util\Translator;
use Icinga\Logger\Logger;
use Icinga\Data\ResourceFactory;
@ -262,10 +264,6 @@ abstract class ApplicationBootstrap
$application = new $class($configDir);
$application->bootstrap();
if (Logger::hasErrorsOccurred()) {
$application->stopApplication(Logger::getQueue());
}
return $application;
}
@ -359,14 +357,33 @@ abstract class ApplicationBootstrap
try {
$this->moduleManager->loadEnabledModules();
} catch (Exception $e) {
Logger::fatal(
'Could not load modules. An exception was thrown during bootstrap: %s',
$e->getMessage()
);
}
return $this;
}
/**
* Setup default logging
*
* @return self
*/
protected function setupLogging()
{
Logger::create(
new Zend_Config(
array(
'enable' => true,
'level' => Logger::$ERROR,
'type' => 'syslog',
'facility' => 'LOG_USER',
'application' => 'Icinga Web'
)
)
);
return $this;
}
/**
* Load Configuration
*
@ -391,7 +408,13 @@ abstract class ApplicationBootstrap
ini_set('display_startup_errors', 1);
ini_set('display_errors', 1);
}
Logger::create($this->config->logging);
try {
Logger::create($this->config->logging);
} catch (ConfigurationError $e) {
Logger::error($e);
}
return $this;
}
@ -438,7 +461,7 @@ abstract class ApplicationBootstrap
try {
Translator::setupLocale($this->config->global->get('language', Translator::DEFAULT_LOCALE));
} catch (Exception $error) {
Logger::info($error->getMessage());
Logger::error($error);
}
$localeDir = $this->getApplicationDir('locale');

View File

@ -61,11 +61,12 @@ class Cli extends ApplicationBootstrap
protected function bootstrap()
{
$this->assertRunningOnCli();
$this->setupConfig()
->setupInternationalization()
->parseBasicParams()
$this->setupLogging()
->setupConfig()
->fixLoggingConfig()
->setupErrorHandling()
->setupInternationalization()
->parseBasicParams()
->setupResourceFactory()
->setupModuleManager();
}
@ -74,13 +75,9 @@ class Cli extends ApplicationBootstrap
{
$conf = & $this->getConfig()->logging;
if ($conf->type === 'stream') {
$conf->verbose = $this->verbose;
$conf->level = $this->verbose;
$conf->target = 'php://stderr';
}
if ($conf->debug && $conf->debug->type === 'stream') {
$conf->debug->target = 'php://stderr';
$conf->debug->enable = $this->debug;
}
return $this;
}

View File

@ -1,380 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga Web 2.
*
* Icinga Web 2 - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Application;
use Icinga\Protocol\Ldap\Exception;
use \Zend_Config;
use \Zend_Log;
use \Zend_Log_Filter_Priority;
use \Zend_Log_Writer_Abstract;
use \Zend_Log_Exception;
use \Icinga\Exception\ConfigurationError;
/**
* Singleton logger
*/
final class Logger
{
/**
* Default log type
*/
const DEFAULT_LOG_TYPE = "stream";
/**
* Default log target
*/
const DEFAULT_LOG_TARGET = "./var/log/icingaweb.log";
/**
* Default debug target
*/
const DEFAULT_DEBUG_TARGET = "./var/log/icingaweb.debug.log";
/**
* Array of writers
*
* @var array
*/
private $writers = array();
/**
* Instance of Zend_Log
*
* @var Zend_Log
*/
private $logger;
/**
* Singleton instance
*
* @var Logger
*/
private static $instance;
/**
* Queue of unwritten messages
*
* @var array
*/
private static $queue = array();
/**
* Flag indicate that errors occurred in the past
*
* @var bool
*/
private static $errorsOccurred = false;
/**
* Create a new logger object
*
* @param Zend_Config $config
*/
public function __construct(Zend_Config $config)
{
$this->overwrite($config);
}
/**
* @return array
*/
public function getWriters()
{
return $this->writers;
}
/**
* Overwrite config to initiated logger
*
* @param Zend_Config $config
*
* @return self
*/
public function overwrite(Zend_Config $config)
{
$this->clearLog();
try {
if ($config->debug && $config->debug->enable == '1') {
$this->setupDebugLog($config);
}
} catch (ConfigurationError $e) {
$this->warn('Could not create debug log: ' . $e->getMessage());
}
if ($config->get('enable', '1') != '0') {
$this->setupLog($config);
}
$this->flushQueue();
return $this;
}
/**
* Configure debug log
*
* @param Zend_Config $config
*/
private function setupDebugLog(Zend_Config $config)
{
$type = $config->debug->get("type", self::DEFAULT_LOG_TYPE);
$target = $config->debug->get("target", self::DEFAULT_LOG_TARGET);
if ($target == self::DEFAULT_LOG_TARGET) {
$type = self::DEFAULT_LOG_TYPE;
}
$this->addWriter($type, $target, Zend_Log::DEBUG);
}
/**
* Configure log
*
* @param Zend_Config $config
*/
private function setupLog(Zend_Config $config)
{
$type = $config->get("type", self::DEFAULT_LOG_TYPE);
$target = $config->get("target", self::DEFAULT_DEBUG_TARGET);
if ($target == self::DEFAULT_DEBUG_TARGET) {
$type = self::DEFAULT_LOG_TYPE;
}
$level = Zend_Log::WARN;
if ($config->get("verbose", 0) == 1) {
$level = Zend_Log::INFO;
}
$this->addWriter($type, $target, $level);
}
/**
* Add writer to log instance
*
* @param string $type Type, e.g. stream
* @param string $target Target, e.g. filename
* @param int $priority Value of Zend::* constant
* @throws ConfigurationError
*/
private function addWriter($type, $target, $priority)
{
$type[0] = strtoupper($type[0]);
$writerClass = "Zend_Log_Writer_" . $type;
if (!@class_exists($writerClass)) {
self::fatal(
'Could not add log writer of type "%s". Type does not exist.',
$type
);
return;
}
try {
$target = Config::resolvePath($target);
// Make sure the permissions for log target file are correct
if ($type === 'Stream') {
$writer = new $writerClass($target);
if (substr($target, 0, 6) !== 'php://' && !file_exists($target)) {
touch($target);
chmod($target, 0664);
}
} elseif ($type === 'Syslog') {
$writer = new $writerClass();
} else {
self::fatal('Got invalid lot type "%s"', $type);
}
$writer->addFilter(new Zend_Log_Filter_Priority($priority));
$this->logger->addWriter($writer);
$this->writers[] = $writer;
} catch (Zend_Log_Exception $e) {
self::fatal(
'Could not add log writer of type %s. An exception was thrown: %s',
$type,
$e->getMessage()
);
}
}
/**
* Flush pending messages to writer
*/
public function flushQueue()
{
try {
foreach (self::$queue as $msgTypePair) {
$this->logger->log($msgTypePair[0], $msgTypePair[1]);
}
} catch (Zend_Log_Exception $e) {
self::fatal(
'Could not flush logs to output. An exception was thrown: %s',
$e->getMessage()
);
}
}
/**
* Format output message
*
* @param array $argv
*
* @return string
*/
public static function formatMessage(array $argv)
{
if (count($argv) == 1) {
$format = $argv[0];
} else {
$format = array_shift($argv);
}
if (!is_string($format)) {
$format = json_encode($format);
}
foreach ($argv as &$arg) {
if (!is_string($arg)) {
$arg = json_encode($arg);
}
}
return @vsprintf($format, $argv);
}
/**
* Reset object configuration
*/
public function clearLog()
{
$this->logger = null;
$this->writers = array();
$this->logger = new Zend_Log();
}
/**
* Create an instance
*
* @param Zend_Config $config
*
* @return Logger
*/
public static function create(Zend_Config $config)
{
if (self::$instance) {
return self::$instance->overwrite($config);
}
return self::$instance = new Logger($config);
}
/**
* Log message with severity debug
*/
public static function debug()
{
self::log(self::formatMessage(func_get_args()), Zend_Log::DEBUG);
}
/**
* Log message with severity warn
*/
public static function warn()
{
self::log(self::formatMessage(func_get_args()), Zend_Log::WARN);
}
/**
* Log message with severity info
*/
public static function info()
{
self::log(self::formatMessage(func_get_args()), Zend_Log::INFO);
}
/**
* Log message with severity error
*/
public static function error()
{
self::log(self::formatMessage(func_get_args()), Zend_Log::ERR);
}
/**
* Log message with severity fatal
*/
public static function fatal()
{
self::log(self::formatMessage(func_get_args()), Zend_Log::EMERG);
}
/**
* Log message
*
* @param string $msg Message
* @param int $level Log level
*/
private static function log($msg, $level = Zend_Log::INFO)
{
$logger = self::$instance;
if ($level < Zend_Log::WARN && self::$errorsOccurred === false) {
self::$errorsOccurred =true;
}
if (!$logger || !count($logger->getWriters())) {
array_push(self::$queue, array($msg, $level));
return;
}
$logger->logger->log($msg, $level);
}
/**
* Flag if messages > warning occurred
*
* @return bool
*/
public static function hasErrorsOccurred()
{
return self::$errorsOccurred;
}
/**
* Access the log queue
*
* The log queue holds messages that could not be written to output
*
* @return array
*/
public static function getQueue()
{
return self::$queue;
}
/**
* Reset object state
*/
public static function reset()
{
self::$queue = array();
self::$instance = null;
}
}

View File

@ -31,7 +31,7 @@ namespace Icinga\Application\Modules;
use Icinga\Application\ApplicationBootstrap;
use Icinga\Application\Icinga;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Data\DataArray\Datasource as ArrayDatasource;
use Icinga\Data\DataArray\Query as ArrayQuery;
use Icinga\Exception\ConfigurationError;
@ -161,7 +161,7 @@ class Manager
$link = $this->enableDir . '/' . $file;
if (! is_link($link)) {
Logger::warn(
Logger::warning(
'Found invalid module in enabledModule directory "%s": "%s" is not a symlink',
$this->enableDir,
$link
@ -171,7 +171,7 @@ class Manager
$dir = realpath($link);
if (!file_exists($dir) || !is_dir($dir)) {
Logger::warn(
Logger::warning(
'Found invalid module in enabledModule directory "%s": "%s" points to non existing path "%s"',
$this->enableDir,
$link,
@ -517,7 +517,7 @@ class Manager
{
foreach ($this->modulePaths as $basedir) {
if (!file_exists($basedir)) {
Logger::warn('Module path "%s" does not exist.', $basedir);
Logger::warning('Module path "%s" does not exist.', $basedir);
continue;
}
$fh = opendir($basedir);
@ -532,7 +532,7 @@ class Manager
if (! array_key_exists($name, $this->installedBaseDirs)) {
$this->installedBaseDirs[$name] = $basedir . '/' . $name;
} else {
Logger::warn(
Logger::warning(
'Module "%s" already exists in installation path "%s" and is ignored.',
$basedir . '/' . $name,
$this->installedBaseDirs[$name]

View File

@ -34,7 +34,7 @@ use Zend_Controller_Router_Route as Route;
use Icinga\Application\ApplicationBootstrap;
use Icinga\Application\Config;
use Icinga\Application\Icinga;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Util\Translator;
use Icinga\Web\Hook;
@ -185,7 +185,7 @@ class Module
try {
$this->launchRunScript();
} catch (Exception $e) {
Logger::warn(
Logger::warning(
'Launching the run script %s for module %s failed with the following exception: %s',
$this->runScript,
$this->name,

View File

@ -37,7 +37,7 @@ use \Zend_View_Helper_PaginationControl;
use \Zend_Controller_Action_HelperBroker;
use \Zend_Controller_Router_Route;
use \Zend_Controller_Front;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Authentication\Manager as AuthenticationManager;
use Icinga\Exception\ConfigurationError;
use Icinga\User\Preferences;
@ -114,7 +114,8 @@ class Web extends ApplicationBootstrap
*/
protected function bootstrap()
{
return $this->setupConfig()
return $this->setupLogging()
->setupConfig()
->setupErrorHandling()
->setupResourceFactory()
->setupSession()
@ -260,7 +261,7 @@ class Web extends ApplicationBootstrap
$path = Config::resolvePath($this->getConfig()->preferences->configPath);
if (is_dir($path) === false) {
Logger::warn(
Logger::warning(
'Path for preferences not found (IniStore, "%s"). Using default one: "%s"',
$this->getConfig()->preferences->configPath,
$this->getConfigDir('preferences')
@ -278,7 +279,7 @@ class Web extends ApplicationBootstrap
);
$preferences->attach($preferenceStore);
} catch (Exception $e) {
Logger::warn(
Logger::warning(
'Could not create create preferences provider, preferences will be discarded: '
. '"%s"',
$e->getMessage()
@ -290,7 +291,7 @@ class Web extends ApplicationBootstrap
try {
$initialPreferences = $preferenceStore->load();
} catch (Exception $e) {
Logger::warn(
Logger::warning(
'%s::%s: Could not load preferences from provider. '
. 'An exception during bootstrap was thrown: %s',
__CLASS__,

View File

@ -39,7 +39,7 @@ use \Icinga\User;
use \Icinga\Authentication\UserBackend;
use \Icinga\Authentication\Credential;
use \Icinga\Authentication;
use \Icinga\Application\Logger;
use \Icinga\Logger\Logger;
use \Icinga\Exception\ProgrammingError;
use \Icinga\Exception\ConfigurationError;

View File

@ -34,7 +34,7 @@ use \Zend_Config;
use Icinga\User;
use Icinga\Web\Session;
use Icinga\Data\ResourceFactory;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Exception\ConfigurationError;
use Icinga\Application\Config as IcingaConfig;
use Icinga\Authentication\Backend\DbUserBackend;
@ -168,7 +168,7 @@ class Manager
$name = $backendConfig->name;
// TODO: implement support for groups (#4624) and remove OR-Clause
if ((!$target || strtolower($target) != "user") && !$backendConfig->class) {
Logger::warn('AuthManager: Backend "%s" has no target configuration. (e.g. target=user|group)', $name);
Logger::warning('AuthManager: Backend "%s" has no target configuration. (e.g. target=user|group)', $name);
return null;
}
try {
@ -188,10 +188,10 @@ class Manager
case 'ldap':
return new LdapUserBackend($backendConfig);
default:
Logger::warn('AuthManager: Resource type ' . $backendConfig->type . ' not available.');
Logger::warning('AuthManager: Resource type ' . $backendConfig->type . ' not available.');
}
} catch (Exception $e) {
Logger::warn('AuthManager: Not able to create backend. Exception was thrown: %s', $e->getMessage());
Logger::warning('AuthManager: Not able to create backend. Exception was thrown: %s', $e->getMessage());
}
return null;
}
@ -288,7 +288,6 @@ class Manager
}
if ($authErrors >= count($this->userBackends)) {
Logger::fatal('AuthManager: No working backend found, unable to authenticate any user');
throw new ConfigurationError(
'No working backend found. Unable to authenticate any user.' .
"\nPlease examine the logs for more information."

View File

@ -2,7 +2,7 @@
namespace Icinga\Data;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Exception;
use Icinga\Filter\Filterable;
use Icinga\Filter\Query\Node;

View File

@ -0,0 +1,23 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Logger;
use \Zend_Config;
/**
* Abstract class for writers that write messages to a log
*/
abstract class LogWriter
{
/**
* Create a new log writer initialized with the given configuration
*/
abstract public function __construct(Zend_Config $config);
/**
* Log a message with the given severity
*/
abstract public function log($severity, $message);
}

View File

@ -0,0 +1,194 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Logger;
use \Exception;
use \Zend_Config;
use Icinga\Exception\ConfigurationError;
/**
* Singleton logger
*/
class Logger
{
/**
* This logger's instance
*
* @var Logger
*/
protected static $instance;
/**
* The log writer to use
*
* @var LogWriter
*/
protected $writer;
/**
* The maximum severity to emit
*
* @var int
*/
protected $verbosity;
/**
* The supported severities
*/
public static $ERROR = 0;
public static $WARNING = 1;
public static $INFO = 2;
public static $DEBUG = 3;
/**
* Create a new logger object
*
* @param Zend_Config $config
*/
public function __construct(Zend_Config $config)
{
$this->verbosity = $config->level;
if ($config->enable) {
$this->writer = $this->getWriter($config);
}
}
/**
* Create a new logger object
*
* @param Zend_Config $config
*/
public static function create(Zend_Config $config)
{
static::$instance = new static($config);
}
/**
* Return a log writer
*
* @param Zend_Config $config The configuration to initialize the writer with
*
* @return LogWriter The requested log writer
*
* @throws ConfigurationError In case the requested writer cannot be found
*/
protected function getWriter(Zend_Config $config)
{
$class = 'Icinga\\Logger\\Writer\\' . ucfirst(strtolower($config->type)) . 'Writer';
if (!class_exists($class)) {
throw new ConfigurationError('Cannot find log writer of type "' . $config->type . '"');
}
return new $class($config);
}
/**
* Write a message to the log
*
* @param string $message The message to write
* @param int $severity The severity to use
*/
public function log($message, $severity)
{
if ($this->writer !== null && $this->verbosity >= $severity) {
$this->writer->log($severity, $message);
}
}
/**
* Return a string representation of the passed arguments
*
* This method provides three different processing techniques:
* - If the only passed argument is a string it is returned unchanged
* - If the only passed argument is an exception it is formatted as follows:
* <name> in <file>:<line> with message: <message>[ <- <name> ...]
* - If multiple arguments are passed the first is interpreted as format-string
* that gets substituted with the remaining ones which can be of any type
*
* @param array $arguments The arguments to format
*
* @return string The formatted result
*/
protected static function formatMessage(array $arguments)
{
if (count($arguments) === 1) {
$message = $arguments[0];
if ($message instanceof Exception) {
$messages = array();
$error = $message;
do {
$messages[] = sprintf(
'%s in %s:%d with message: %s',
get_class($error),
$error->getFile(),
$error->getLine(),
$error->getMessage()
);
} while ($error = $error->getPrevious());
$message = implode(' <- ', $messages);
}
return $message;
}
return vsprintf(
array_shift($arguments),
array_map(
function ($a) { return is_string($a) ? $a : json_encode($a); },
$arguments
)
);
}
/**
* Log a message with severity ERROR
*
* @param mixed $arg,... A string, exception or format-string + substitutions
*/
public static function error()
{
if (static::$instance !== null && func_num_args() > 0) {
static::$instance->log(static::formatMessage(func_get_args()), static::$ERROR);
}
}
/**
* Log a message with severity WARNING
*
* @param mixed $arg,... A string, exception or format-string + substitutions
*/
public static function warning()
{
if (static::$instance !== null && func_num_args() > 0) {
static::$instance->log(static::formatMessage(func_get_args()), static::$WARNING);
}
}
/**
* Log a message with severity INFO
*
* @param mixed $arg,... A string, exception or format-string + substitutions
*/
public static function info()
{
if (static::$instance !== null && func_num_args() > 0) {
static::$instance->log(static::formatMessage(func_get_args()), static::$INFO);
}
}
/**
* Log a message with severity DEBUG
*
* @param mixed $arg,... A string, exception or format-string + substitutions
*/
public static function debug()
{
if (static::$instance !== null && func_num_args() > 0) {
static::$instance->log(static::formatMessage(func_get_args()), static::$DEBUG);
}
}
}

View File

@ -0,0 +1,97 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Logger\Writer;
use \Zend_Config;
use Icinga\Logger\Logger;
use Icinga\Logger\LogWriter;
use Icinga\Application\Config;
use Icinga\Exception\ConfigurationError;
/**
* Class to write log messages to a stream
*/
class StreamWriter extends LogWriter
{
/**
* The path to the stream
*
* @var string
*/
protected $stream;
/**
* Create a new log writer initialized with the given configuration
*/
public function __construct(Zend_Config $config)
{
$this->stream = Config::resolvePath($config->target);
$this->setup();
}
/**
* Log a message with the given severity
*
* @param int $severity The severity to use
* @param string $message The message to log
*/
public function log($severity, $message)
{
$this->write(date('c') . ' ' . $this->getSeverityString($severity) . ' ' . $message);
}
/**
* Create the stream if it does not already exist
*/
protected function setup()
{
if (substr($this->stream, 0, 6) !== 'php://') {
if (!file_exists($this->stream) && (!@touch($this->stream) || !@chmod($this->stream, 0664))) {
throw new ConfigurationError('Cannot create log file "' . $this->stream . '"');
}
if (!@is_writable($this->stream)) {
throw new ConfigurationError('Cannot write to log file "' . $this->stream . '"');
}
}
}
/**
* Return a string representation for the given severity
*
* @param string $severity The severity to use
*
* @return string The string representation of the severity
*
* @throws Exception In case the given severity is unknown
*/
protected function getSeverityString($severity)
{
switch ($severity) {
case Logger::$ERROR:
return '- ERROR -';
case Logger::$WARNING:
return '- WARNING -';
case Logger::$INFO:
return '- INFO -';
case Logger::$DEBUG:
return '- DEBUG -';
default:
throw new Exception('Unknown severity "' . $severity . '"');
}
}
/**
* Write a message to the stream
*
* @param string $text The message to write
*/
protected function write($text)
{
$fd = fopen($this->stream, 'a');
fwrite($fd, $text . PHP_EOL);
fclose($fd);
}
}

View File

@ -0,0 +1,108 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Logger\Writer;
use \Exception;
use \Zend_Config;
use Icinga\Logger\Logger;
use Icinga\Logger\LogWriter;
use Icinga\Exception\ConfigurationError;
/**
* Class to write messages to syslog
*/
class SyslogWriter extends LogWriter
{
/**
* The facility where to write messages to
*
* @var string
*/
protected $facility;
/**
* The prefix to prepend to each message
*
* @var string
*/
protected $ident;
/**
* Known syslog facilities
*
* @var array
*/
protected $facilities = array(
'LOG_USER' => LOG_USER
);
/**
* Create a new log writer initialized with the given configuration
*/
public function __construct(Zend_Config $config)
{
if (!array_key_exists($config->facility, $this->facilities)) {
throw new ConfigurationError(
'Cannot create syslog writer with unknown facility "' . $config->facility . '"'
);
}
$this->ident = $config->application;
$this->facility = $this->facilities[$config->facility];
}
/**
* Log a message with the given severity
*
* @param int $severity The severity to use
* @param string $message The message to log
*
* @throws Exception In case the given severity cannot be mapped to a valid syslog priority
*/
public function log($severity, $message)
{
$priorities = array(
Logger::$ERROR => LOG_ERR,
Logger::$WARNING => LOG_WARNING,
Logger::$INFO => LOG_INFO,
Logger::$DEBUG => LOG_DEBUG
);
if (!array_key_exists($severity, $priorities)) {
throw new Exception('Severity "' . $severity . '" cannot be mapped to a valid syslog priority');
}
$this->open();
$this->write($priorities[$severity], $message);
$this->close();
}
/**
* Open a new syslog connection
*/
protected function open()
{
openlog($this->ident, 0, $this->facility);
}
/**
* Write a message to the syslog connection
*
* @param int $priority The priority to use
* @param string $message The message to write
*/
protected function write($priority, $message)
{
syslog($priority, $message);
}
/**
* Close the syslog connection
*/
protected function close()
{
closelog();
}
}

View File

@ -29,7 +29,7 @@
namespace Icinga\Protocol\Commandpipe\Transport;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
/**
* CommandPipe Transport class that writes to a file accessible by the filesystem

View File

@ -31,7 +31,7 @@ namespace Icinga\Protocol\Commandpipe\Transport;
use \RuntimeException;
use \Zend_Config;
use \Icinga\Application\Logger;
use \Icinga\Logger\Logger;
/**
* Command pipe transport class that uses ssh for connecting to a remote filesystem with the icinga.cmd pipe

View File

@ -31,7 +31,7 @@ namespace Icinga\Protocol\Ldap;
use Icinga\Application\Platform;
use Icinga\Application\Config;
use Icinga\Application\Logger as Log;
use Icinga\Logger\Logger;
use \Zend_Config;
/**
@ -273,14 +273,14 @@ class Connection
$r = @ldap_bind($ds, $username, $password);
if ($r) {
log::debug(
Logger::debug(
'Successfully tested LDAP credentials (%s / %s)',
$username,
'***'
);
return true;
} else {
log::debug(
Logger::debug(
'Testing LDAP credentials (%s / %s) failed: %s',
$username,
'***',
@ -321,9 +321,9 @@ class Connection
if ($use_tls) {
if ($cap->starttls) {
if (@ldap_start_tls($ds)) {
Log::debug('LDAP STARTTLS succeeded');
Logger::debug('LDAP STARTTLS succeeded');
} else {
Log::debug('LDAP STARTTLS failed: %s', ldap_error($ds));
Logger::debug('LDAP STARTTLS failed: %s', ldap_error($ds));
throw new \Exception(
sprintf(
'LDAP STARTTLS failed: %s',
@ -352,7 +352,7 @@ class Connection
// TODO: remove this -> FORCING v3 for now
ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3);
Log::warn('No LDAPv3 support detected');
Logger::warn('No LDAPv3 support detected');
}
// Not setting this results in "Operations error" on AD when using the

View File

@ -29,7 +29,7 @@
namespace Icinga\Protocol\Statusdat;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Data\DatasourceInterface;
use Icinga\Exception\ConfigurationError;
@ -147,7 +147,7 @@ class Reader implements IReader, DatasourceInterface
$maxCacheLifetime = intval($this->config->get('cache_path', self::DEFAULT_CACHE_LIFETIME));
$cachingEnabled = true;
if (!is_writeable($cachePath)) {
Logger::warn(
Logger::warning(
'Can\'t cache Status.dat backend; make sure cachepath %s is writable by the web user. '
. 'Caching is now disabled',
$cachePath

View File

@ -29,7 +29,7 @@
namespace Icinga\Session;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use \Icinga\Exception\ConfigurationError;
/**
@ -95,7 +95,7 @@ class PhpSession extends Session
foreach ($options as $sessionVar => $value) {
if (ini_set("session." . $sessionVar, $value) === false) {
Logger::warn(
Logger::warning(
'Could not set php.ini setting %s = %s. This might affect your sessions behaviour.',
$sessionVar,
$value

View File

@ -29,9 +29,8 @@
namespace Icinga\User\Preferences;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Protocol\Ldap\Exception;
use \SplObserver;
use \SplSubject;
use \Icinga\User;
use \Icinga\User\Preferences;

View File

@ -39,7 +39,7 @@ use Icinga\Application\Benchmark;
use Icinga\Util\Translator;
use Icinga\Web\Widget\Tabs;
use Icinga\Web\Url;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Web\Request;
use Icinga\File\Pdf;

View File

@ -30,7 +30,7 @@
namespace Icinga\Web;
use \stdClass;
use \Icinga\Application\Logger as Log;
use \Icinga\Logger\Logger;
use \Icinga\Exception\ProgrammingError;
/**
@ -110,7 +110,7 @@ class Hook
$obj = new $class();
} catch (\Exception $e) {
// TODO: Persist unloading for "some time" or "current session"
Log::debug(
Logger::debug(
'Hook "%s" (%s) failed, will be unloaded: %s',
$name,
$class,
@ -155,7 +155,7 @@ class Hook
try {
$instance = new $class();
} catch (\Exception $e) {
Log::debug(
Logger::debug(
'Hook "%s" (%s) (%s) failed, will be unloaded: %s',
$name,
$key,

View File

@ -31,7 +31,7 @@ namespace Icinga\Web;
use Icinga\Exception\ProgrammingError;
use Icinga\Application\Platform;
use Icinga\Application\Logger as Log;
use Icinga\Logger\Logger;
use Icinga\Web\Session;
/**
@ -90,13 +90,13 @@ class Notification
switch ($type) {
case 'info':
case 'success':
Log::info($msg);
Logger::info($msg);
break;
case 'warning':
Log::warn($msg);
Logger::warn($msg);
break;
case 'error':
Log::error($msg);
Logger::error($msg);
break;
}
return;

View File

@ -31,7 +31,7 @@ namespace Icinga\Web\Widget;
use \Icinga\Application\Icinga;
use \Icinga\Application\Config as IcingaConfig;
use \Icinga\Application\Logger;
use \Icinga\Logger\Logger;
use \Icinga\Exception\ConfigurationError;
use \Icinga\Web\Widget\Widget;
use \Icinga\Web\Widget\Dashboard\Pane;

View File

@ -29,7 +29,7 @@
namespace Icinga\Web\Widget\Tabextension;
use \Icinga\Application\Logger;
use \Icinga\Logger\Logger;
use \Icinga\Web\Widget\Tab;
use \Icinga\Web\Widget\Tabs;
use \Icinga\Web\Url;

View File

@ -29,7 +29,7 @@
use Icinga\Application\Icinga;
use Icinga\Application\Config;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Web\Form;
use Icinga\Web\Controller\ActionController;
use Icinga\Chart\SVGRenderer;

View File

@ -30,7 +30,7 @@
use Icinga\Application\Icinga;
use Icinga\Application\Config;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Module\Monitoring\DataView\HostStatus;
use Icinga\Module\Monitoring\DataView\ServiceStatus;
use Icinga\Module\Monitoring\Form\Command\DisableNotificationWithExpireForm;

View File

@ -29,7 +29,7 @@
namespace Icinga\Module\Monitoring\Backend\Ido\Query;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Data\Db\Query;
use Icinga\Application\Benchmark;
use Icinga\Exception\ProgrammingError;
@ -211,7 +211,7 @@ abstract class IdoQuery extends Query
} elseif ($this->hasAliasName($columnOrAlias)) {
$columnOrAlias = $this->aliasToColumnName($columnOrAlias);
} else {
Logger::info('Can\'t order by column '.$columnOrAlias);
Logger::info('Can\'t order by column ' . $columnOrAlias);
return $this;
}
return parent::order($columnOrAlias, $dir);

View File

@ -29,7 +29,7 @@
namespace Icinga\Module\Monitoring\Backend\Statusdat\Query;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Data\Optional;
use Icinga\Data\The;
use Icinga\Filter\Query\Node;

View File

@ -30,7 +30,7 @@
namespace Icinga\Module\Monitoring\Filter;
use Icinga\Application\Icinga;
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Filter\Domain;
use Icinga\Filter\FilterAttribute;
use Icinga\Filter\Query\Node;

View File

@ -34,7 +34,6 @@ use Icinga\Filter\Query\Tree;
use Icinga\Filter\Query\Node;
use Icinga\Web\Request;
use Icinga\Web\Url;
use Icinga\Application\Logger;
/**
* Converter class that allows to create Query Trees from an request query and vice versa

View File

@ -27,170 +27,65 @@
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Tests\Icinga\Application;
// @codingStandardsIgnoreStart
require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php');
// @codingStandardsIgnoreEnd
use \Zend_Config;
use Icinga\Application\Logger;
use Icinga\Test\BaseTestCase;
/**
* Test class for Logger
*
* @backupStaticAttributes enabled
**/
// @codingStandardsIgnoreStart
require_once BaseTestCase::$libDir . '/Logger/Logger.php';
require_once BaseTestCase::$libDir . '/Logger/LogWriter.php';
require_once BaseTestCase::$libDir . '/Logger/Writer/StreamWriter.php';
// @codingStandardsIgnoreEnd
use \Zend_Config;
use Icinga\Logger\Logger;
class LoggerTest extends BaseTestCase
{
private $tempDir;
private $logTarget;
private $debugTarget;
public function setUp()
/**
* @backupStaticAttributes enabled
*/
public function testLogfileCreation()
{
$this->tempDir = tempnam(sys_get_temp_dir(), 'icingaweb-log');
unlink($this->tempDir); // tempnam create the file automatically
if (!is_dir($this->tempDir)) {
mkdir($this->tempDir, 0755);
}
$this->debugTarget = $this->tempDir . '/debug.log';
$this->logTarget = $this->tempDir . '/application.log';
$loggingConfigurationArray = array(
'enable' => 1,
'type' => 'stream',
'verbose' => 1,
'target' => $this->logTarget,
'debug' => array(
'enable' => 1,
'type' => 'stream',
'target' => $this->debugTarget
$target = tempnam(sys_get_temp_dir(), 'log');
unlink($target);
Logger::create(
new Zend_Config(
array(
'enable' => true,
'level' => Logger::$ERROR,
'type' => 'stream',
'target' => $target
)
)
);
$loggingConfiguration = new Zend_Config($loggingConfigurationArray);
Logger::reset();
Logger::create($loggingConfiguration);
}
public function tearDown()
{
if (file_exists($this->debugTarget)) {
unlink($this->debugTarget);
}
if (file_exists($this->logTarget)) {
unlink($this->logTarget);
}
rmdir($this->tempDir);
}
private function getLogData()
{
return array(
explode(PHP_EOL, file_get_contents($this->logTarget)),
explode(PHP_EOL, file_get_contents($this->debugTarget))
);
$this->assertFileExists($target, 'Logger did not create the log file');
unlink($target);
}
/**
* Test error messages
* @backupStaticAttributes enabled
* @depends testLogfileCreation
*/
public function testLoggingErrorMessages()
{
Logger::error('test-error-1');
Logger::error('test-error-2');
$this->assertFileExists($this->logTarget);
$this->assertFileExists($this->debugTarget);
list($main, $debug) = $this->getLogData();
$this->assertCount(3, $main);
$this->assertCount(3, $debug);
$this->assertContains(' ERR (3): test-error-1', $main[0]);
$this->assertContains(' ERR (3): test-error-2', $main[1]);
$this->assertContains(' ERR (3): test-error-1', $debug[0]);
$this->assertContains(' ERR (3): test-error-2', $debug[1]);
}
/**
* Test debug log and difference between error and debug messages
*/
public function testLoggingDebugMessages()
{
Logger::debug('test-debug-1');
Logger::error('test-error-1');
Logger::debug('test-debug-2');
$this->assertFileExists($this->logTarget);
$this->assertFileExists($this->debugTarget);
list($main, $debug) = $this->getLogData();
$this->assertCount(2, $main);
$this->assertCount(4, $debug);
$this->assertContains(' ERR (3): test-error-1', $main[0]);
$this->assertContains(' DEBUG (7): test-debug-1', $debug[0]);
$this->assertContains(' ERR (3): test-error-1', $debug[1]);
$this->assertContains(' DEBUG (7): test-debug-2', $debug[2]);
}
public function testLoggingQueueIfNoWriterAvailable()
{
Logger::reset();
Logger::error('test-error-1');
Logger::debug('test-debug-1');
Logger::error('test-error-2');
list($main, $debug) = $this->getLogData();
$this->assertCount(1, $main);
$this->assertCount(1, $debug);
$this->assertTrue(Logger::hasErrorsOccurred());
$queue = Logger::getQueue();
$this->assertCount(3, $queue);
$this->assertEquals(
array(
'test-error-1',
3
),
$queue[0]
);
$this->assertEquals(
array(
'test-debug-1',
7
),
$queue[1]
);
$this->assertEquals(
array(
'test-error-2',
3
),
$queue[2]
$target = tempnam(sys_get_temp_dir(), 'log');
unlink($target);
Logger::create(
new Zend_Config(
array(
'enable' => true,
'level' => Logger::$ERROR,
'type' => 'stream',
'target' => $target
)
)
);
Logger::error('This is a test error');
$log = file_get_contents($target);
unlink($target);
$this->assertContains('This is a test error', $log, 'Log does not contain the error "This is a test error"');
}
}

View File

@ -33,13 +33,12 @@ namespace Tests\Icinga\Authentication;
require_once realpath(__DIR__ . '/../../../../../library/Icinga/Test/BaseTestCase.php');
// @codingStandardsIgnoreEnd
use Icinga\Application\Logger;
use \Icinga\Test\BaseTestCase;
// @codingStandardsIgnoreStart
require_once 'Zend/Log.php';
require_once 'Zend/Config.php';
require_once BaseTestCase::$libDir . '/Application/Logger.php';
require_once BaseTestCase::$libDir . '/Logger/Logger.php';
require_once BaseTestCase::$libDir . '/Authentication/Manager.php';
require_once BaseTestCase::$libDir . '/Authentication/Membership.php';
require_once BaseTestCase::$libDir . '/Authentication/Credential.php';

View File

@ -14,7 +14,7 @@ require_once "Zend/Session.php";
require_once "Zend/Log/Writer/Abstract.php";
require_once "Zend/Log/Writer/Stream.php";
use Icinga\Application\Logger;
use Icinga\Logger\Logger;
use Icinga\Web\Notification;
class NotificationTest extends \PHPUnit_Framework_TestCase

View File

@ -1,65 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga Web 2.
*
* Icinga Web 2 - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Tests\Icinga\Regression;
use \Icinga\Test\BaseTestCase;
use \Icinga\Application\Logger;
use \Zend_Config;
require_once 'Zend/Log.php';
require_once 'Zend/Config.php';
require_once 'Zend/Log/Writer/Mock.php';
require_once 'Zend/Log/Writer/Null.php';
require_once 'Zend/Log/Filter/Priority.php';
require_once realpath(__DIR__ . '/../../../library/Icinga/Test/BaseTestCase.php');
require_once realpath(BaseTestCase::$libDir.'/Application/Logger.php');
/**
* Bug 4595 : "If log disabled, default target (./var/log) is not writable / no path exist"
*
* This is caused because the logger ignored the 'enable' parameter
*/
class Regression4595 extends BaseTestCase {
public function testDisableLogging()
{
$cfg = new Zend_Config(
array(
'enable' => '0',
'type' => 'mock',
'target' => 'target2'
)
);
$logger = new Logger($cfg);
$writers = $logger->getWriters();
$this->assertEquals(0, count($writers), 'Assert that loggers aren\'t registered when "enable" is set to false');
}
}