diff --git a/phalcon/DM/Pdo/Profiler/MemoryLogger.zep b/phalcon/DM/Pdo/Profiler/MemoryLogger.zep new file mode 100644 index 00000000000..a695b137e11 --- /dev/null +++ b/phalcon/DM/Pdo/Profiler/MemoryLogger.zep @@ -0,0 +1,60 @@ + +/** + * This file is part of the Phalcon Framework. + * + * (c) Phalcon Team + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + * + * Implementation of this file has been influenced by AtlasPHP + * + * @link https://github.com/atlasphp/Atlas.Pdo + * @license https://github.com/atlasphp/Atlas.Pdo/blob/1.x/LICENSE.md + */ + +namespace Phalcon\DM\Pdo\Profiler; + +use Psr\Log\AbstractLogger; + +/** + * A naive memory-based logger. + * + * @property array $messages + */ +class MemoryLogger extends AbstractLogger +{ + /** + * @var array + */ + protected messages = []; + + /** + * Returns the logged messages. + * + * @return array + */ + public function getMessages() + { + return this->messages; + } + + /** + * Logs a message. + * + * @param mixed $level + * @param string $message + * @param array $context + */ + public function log(var level, var message, array context = []) + { + var key, value; + array replace = []; + + for key, value in context { + let replace["{" . key . "}"] = value; + } + + let this->messages[] = strtr(message, replace); + } +} diff --git a/phalcon/DM/Pdo/Profiler/Profiler.zep b/phalcon/DM/Pdo/Profiler/Profiler.zep new file mode 100644 index 00000000000..4ae57749838 --- /dev/null +++ b/phalcon/DM/Pdo/Profiler/Profiler.zep @@ -0,0 +1,201 @@ +/** + * This file is part of the Phalcon Framework. + * + * (c) Phalcon Team + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + * + * Implementation of this file has been influenced by AtlasPHP + * + * @link https://github.com/atlasphp/Atlas.Pdo + * @license https://github.com/atlasphp/Atlas.Pdo/blob/1.x/LICENSE.md + */ + +namespace Phalcon\DM\Pdo\Profiler; + +use Phalcon\DM\Pdo\Exception\Exception; +use Phalcon\Helper\Json; +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; + +/** + * Sends query profiles to a logger. + * + * @property bool $active + * @property array $context + * @property string $logFormat + * @property string $logLevel + * @property LoggerInterface $logger + */ +class Profiler implements ProfilerInterface +{ + /** + * @var bool + */ + protected active = false; + + /** + * @var array + */ + protected context = []; + + /** + * @var string + */ + protected logFormat; + + /** + * @var string + */ + protected logLevel; + + /** + * @var LoggerInterface + */ + protected logger; + + /** + * Constructor. + * + * @param LoggerInterface $logger + */ + public function __construct( logger = null) + { + if null === logger { + let logger = new MemoryLogger(); + } + + let this->logger = logger, + this->logFormat = "{method} ({duration} seconds): {statement} {backtrace}", + this->logLevel = LogLevel::DEBUG; + } + + /** + * Finishes and logs a profile entry. + * + * @param string $statement + * @param array $values + */ + public function finish(string statement = null, array values = []) -> void + { + var ex, finish, params; + + if this->active { + let finish = microtime(true), + ex = new Exception(), + params = ""; + + if !empty values { + let params = Json::encode(values); + } + + let this->context["backtrace"] = ex->getTraceAsString(), + this->context["duration"] = finish - this->context["start"], + this->context["finish"] = finish, + this->context["statement"] = statement, + this->context["values"] = params; + + this->logger->log(this->logLevel, this->logFormat, this->context); + + let this->context = []; + } + } + + /** + * Returns the log message format string, with placeholders. + * + * @return string + */ + public function getLogFormat() -> string + { + return this->logFormat; + } + + /** + * Returns the underlying logger instance. + * + * @return LoggerInterface + */ + public function getLogger() -> + { + return this->logger; + } + + /** + * Returns the level at which to log profile messages. + * + * @return string + */ + public function getLogLevel() -> string + { + return this->logLevel; + } + + /** + * Returns true if logging is active. + * + * @return bool + */ + public function isActive() -> bool + { + return this->active; + } + + /** + * Enable or disable profiler logging. + * + * @param bool $active + * + * @return ProfilerInterface + */ + public function setActive(bool active) -> + { + let this->active = active; + + return this; + } + + /** + * Sets the log message format string, with placeholders. + * + * @param string $logFormat + * + * @return ProfilerInterface + */ + public function setLogFormat(string logFormat) -> + { + let this->logFormat = logFormat; + + return this; + } + + /** + * Level at which to log profile messages. + * + * @param string $logLevel + * + * @return ProfilerInterface + */ + public function setLogLevel(string logLevel) -> + { + let this->logLevel = logLevel; + + return this; + } + + /** + * Starts a profile entry. + * + * @param string $method + */ + public function start(string method) -> void + { + if this->active { + let this->context = [ + "method" : method, + "start" : microtime(true) + ]; + } + } +}