Skip to content

Commit

Permalink
Refactoring, cleanup, extra tests
Browse files Browse the repository at this point in the history
* Improve LogTarget
* Add more tests
* Implement Message object
  • Loading branch information
rustamwin committed Dec 10, 2020
1 parent 40db38a commit 6225be4
Show file tree
Hide file tree
Showing 11 changed files with 513 additions and 278 deletions.
3 changes: 2 additions & 1 deletion composer.json
Expand Up @@ -19,7 +19,8 @@
"require": {
"php": "^7.4|^8.0",
"psr/log": "^1.1",
"yiisoft/files": "^3.0@dev"
"yiisoft/files": "^3.0@dev",
"yiisoft/strings": "^1.1.0"
},
"require-dev": {
"phpunit/phpunit": "^9.4",
Expand Down
63 changes: 29 additions & 34 deletions src/FileTarget.php
Expand Up @@ -26,7 +26,7 @@
* ];
* ```
*/
class FileTarget extends Target
final class FileTarget extends Target
{
/**
* @var string file path or [path alias](guide:concept-aliases). File name may contain the placeholders,
Expand All @@ -39,7 +39,7 @@ class FileTarget extends Target
* The directory containing the file will be automatically created if not existing.
* If target file is already exist it will be overridden.
*/
private string $filename = '@runtime/profiling/{date}-{time}.txt';
private string $filename;

/**
* @var int the permission to be set for newly created directories.
Expand All @@ -49,6 +49,11 @@ class FileTarget extends Target
*/
private int $dirMode = 0775;

public function __construct(string $filename = '@runtime/profiling/{date}-{time}.txt')
{
$this->filename = $filename;
}

public function export(array $messages): void
{
$memoryPeakUsage = memory_get_peak_usage();
Expand All @@ -62,7 +67,7 @@ public function export(array $messages): void
$filename = $this->resolveFilename();

if (file_exists($filename)) {
unlink($filename);
FileHelper::unlink($filename);
} else {
$filePath = dirname($filename);

Expand All @@ -74,52 +79,42 @@ public function export(array $messages): void
file_put_contents($filename, $text);
}

/**
* Set profiles filename
*
* @param string $value
*/
public function setFilename(string $value): void
{
$this->filename = $value;
}

/**
* Resolves value of {@see filename} processing path alias and placeholders.
*
* @return string actual target filename.
*/
protected function resolveFilename(): string
private function resolveFilename(): string
{
$filename = $this->filename;

return preg_replace_callback('/{\\w+}/', static function ($matches) {
switch ($matches[0]) {
case '{ts}':
return time();
case '{date}':
return gmdate('ymd');
case '{time}':
return gmdate('His');
}
return $matches[0];
}, $filename);
return preg_replace_callback(
'/{\\w+}/',
static function ($matches) {
switch ($matches[0]) {
case '{ts}':
return time();
case '{date}':
return gmdate('ymd');
case '{time}':
return gmdate('His');
}
return $matches[0];
},
$this->filename
);
}

/**
* Formats a profiling message for display as a string.
*
* @param array $message the profiling message to be formatted.
* @param Message $message the profiling message to be formatted.
* The message structure follows that in {@see Profiler::$messages}.
*
* @return string the formatted message.
*/
protected function formatMessage(array $message): string
private function formatMessage(Message $message): string
{
return date(
'Y-m-d H:i:s',
(int) $message['beginTime']
) . " [{$message['duration']} ms][{$message['memoryDiff']} B][{$message['category']}] {$message['token']}" .
__METHOD__;
return date('Y-m-d H:i:s', (int)$message->context('beginTime'))
. " [{$message->context('duration')} ms][{$message->context('memoryDiff')} B][{$message->level()}] {$message->message()}"
. __METHOD__;
}
}
19 changes: 5 additions & 14 deletions src/LogTarget.php
Expand Up @@ -26,7 +26,7 @@
* ];
* ```
*/
class LogTarget extends Target
final class LogTarget extends Target
{
/**
* @var LoggerInterface logger to be used for message export.
Expand All @@ -44,22 +44,13 @@ public function __construct(LoggerInterface $logger, ?string $logLevel = LogLeve
$this->logLevel = $logLevel;
}

/**
* @param Message[] $messages
*/
public function export(array $messages): void
{
foreach ($messages as $message) {
$message['time'] = $message['beginTime'];

$this->logger->log($this->logLevel, $message['token'], $message);
$this->logger->log($this->logLevel, $message->message(), $message->context());
}
}

/**
* @return string|null log level
*
* {@see logLevel}
*/
public function getLogLevel(): ?string
{
return $this->logLevel;
}
}
95 changes: 95 additions & 0 deletions src/Message.php
@@ -0,0 +1,95 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Profiler;

use Psr\Log\InvalidArgumentException;
use Psr\Log\LoggerTrait;
use Psr\Log\LogLevel;

/**
* Message is a data object that stores log message data.
*/
final class Message
{
/**
* @var string Log message level.
*
* @see LogLevel See constants for valid level names.
*/
private string $level;

/**
* @var string Log message.
*/
private string $message;

/**
* @var array Log message context.
*
* Message context has a following keys:
*
* - category: string, message category.
* - memory: int, memory usage in bytes, obtained by `memory_get_usage()`.
* - time: float, message timestamp obtained by microtime(true).
* - trace: array, debug backtrace, contains the application code call stacks.
*/
private array $context;

/**
* @param mixed $level Log message level.
* @param mixed $message Log message.
* @param array $context Log message context.
*
* @throws InvalidArgumentException for invalid log message level.
*
* @see LoggerTrait::log()
* @see LogLevel
*/
public function __construct($level, string $message, array $context = [])
{
$this->level = $level;
$this->message = $message;
$this->context = $context;
}

/**
* Gets a log message level.
*
* @return string Log message level.
*/
public function level(): string
{
return $this->level;
}

/**
* Gets a log message.
*
* @return string Log message.
*/
public function message(): string
{
return $this->message;
}

/**
* Returns a value of the context parameter for the specified name.
*
* If no name is specified, the entire context is returned.
*
* @param string|null $name The context parameter name.
* @param mixed $default If the context parameter does not exist, the `$default` will be returned.
*
* @return mixed The context parameter value.
*/
public function context(string $name = null, $default = null)
{
if ($name === null) {
return $this->context;
}

return $this->context[$name] ?? $default;
}
}

0 comments on commit 6225be4

Please sign in to comment.