Test Failed
Pull Request — master (#19)
by Alexander
03:33 queued 30s
created

FileTarget::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
c 0
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Profiler;
6
7
use Yiisoft\Files\FileHelper;
8
9
/**
10
 * FileTarget records profiling messages in a file specified via {@see filename}.
11
 *
12
 * Application configuration example:
13
 *
14
 * ```php
15
 * return [
16
 *     'profiler' => [
17
 *         'targets' => [
18
 *             [
19
 *                 '__class' => Yiisoft\Profile\FileTarget::class,
20
 *                 //'filename' => '@runtime/profiling/{date}-{time}.txt',
21
 *             ],
22
 *         ],
23
 *         // ...
24
 *     ],
25
 *     // ...
26
 * ];
27
 * ```
28
 */
29
final class FileTarget extends Target
30
{
31
    /**
32
     * @var string file path or [path alias](guide:concept-aliases). File name may contain the placeholders,
33
     * which will be replaced by computed values. The supported placeholders are:
34
     *
35
     * - '{ts}' - profiling completion timestamp.
36
     * - '{date}' - profiling completion date in format 'ymd'.
37
     * - '{time}' - profiling completion time in format 'His'.
38
     *
39
     * The directory containing the file will be automatically created if not existing.
40
     * If target file is already exist it will be overridden.
41
     */
42
    private string $filename;
43
44
    /**
45
     * @var int the permission to be set for newly created directories.
46
     * This value will be used by PHP chmod() function. No umask will be applied.
47
     * Defaults to 0775, meaning the directory is read-writable by owner and group,
48
     * but read-only for other users.
49
     */
50
    private int $dirMode = 0775;
51
52 1
    public function __construct(string $filename = '@runtime/profiling/{date}-{time}.txt')
53
    {
54 1
        $this->filename = $filename;
55
    }
56
57 1
    public function export(array $messages): void
58 1
    {
59
        $memoryPeakUsage = memory_get_peak_usage();
60 1
61
        // TODO: make sure it works with RoadRunner and alike servers
62 1
        $totalTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
63
        $text = "Total processing time: {$totalTime} ms; Peak memory: {$memoryPeakUsage} B. \n\n";
64 1
65
        $text .= implode("\n", array_map([$this, 'formatMessage'], $messages));
66
67 1
        $filename = $this->resolveFilename();
68
69 1
        if (file_exists($filename)) {
70 1
            FileHelper::unlink($filename);
71
        } else {
72
            $filePath = dirname($filename);
73
74 1
            if (!is_dir($filePath)) {
75 1
                FileHelper::createDirectory($filePath, $this->dirMode);
76
            }
77
        }
78
79
        file_put_contents($filename, $text);
80
    }
81
82 1
    /**
83
     * Resolves value of {@see filename} processing path alias and placeholders.
84 1
     *
85 1
     * @return string actual target filename.
86
     */
87
    private function resolveFilename(): string
88
    {
89
        return preg_replace_callback(
90
            '/{\\w+}/',
91
            static function ($matches) {
92 1
                switch ($matches[0]) {
93
                    case '{ts}':
94 1
                        return time();
95
                    case '{date}':
96 1
                        return gmdate('ymd');
97
                    case '{time}':
98
                        return gmdate('His');
99
                }
100
                return $matches[0];
101
            },
102
            $this->filename
103
        );
104
    }
105
106 1
    /**
107
     * Formats a profiling message for display as a string.
108
     *
109
     * @param Message $message the profiling message to be formatted.
110
     * The message structure follows that in {@see Profiler::$messages}.
111
     *
112
     * @return string the formatted message.
113
     */
114
    private function formatMessage(Message $message): string
115
    {
116
        return date('Y-m-d H:i:s', (int)$message->context('beginTime'))
117 1
            . " [{$message->context('duration')} ms][{$message->context('memoryDiff')} B][{$message->level()}] {$message->message()}"
118
            . __METHOD__;
119 1
    }
120
}
121