Passed
Pull Request — master (#2)
by Wilmer
01:23
created

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