Passed
Push — master ( e72ba5...492fde )
by Alexander
10:28
created

FileTarget::formatMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 7
ccs 6
cts 6
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
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 = '@runtime/profiling/{date}-{time}.txt';
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
53 1
    public function export(array $messages): void
54
    {
55 1
        $memoryPeakUsage = memory_get_peak_usage();
56
57
        // TODO: make sure it works with RoadRunner and alike servers
58 1
        $totalTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
59 1
        $text = "Total processing time: {$totalTime} ms; Peak memory: {$memoryPeakUsage} B. \n\n";
60
61 1
        $text .= implode("\n", array_map([$this, 'formatMessage'], $messages));
62
63 1
        $filename = $this->resolveFilename();
64
65 1
        if (file_exists($filename)) {
66
            unlink($filename);
67
        } else {
68 1
            $filePath = dirname($filename);
69
70 1
            if (!is_dir($filePath)) {
71 1
                FileHelper::createDirectory($filePath, $this->dirMode);
72
            }
73
        }
74
75 1
        file_put_contents($filename, $text);
76
    }
77
78
    /**
79
     * Set profiles filename
80
     *
81
     * @param string $value
82
     *
83
     * @return void
84
     *
85
     * {@see filename}
86
     */
87 1
    public function setFilename(string $value): void
88
    {
89 1
        $this->filename = $value;
90
    }
91
92
    /**
93
     * Resolves value of {@see filename} processing path alias and placeholders.
94
     *
95
     * @return string actual target filename.
96
     */
97 1
    protected function resolveFilename(): string
98
    {
99 1
        $filename = $this->filename;
100
101 1
        return preg_replace_callback('/{\\w+}/', static function ($matches) {
102
            switch ($matches[0]) {
103
                case '{ts}':
104
                    return time();
105
                case '{date}':
106
                    return gmdate('ymd');
107
                case '{time}':
108
                    return gmdate('His');
109
            }
110
            return $matches[0];
111 1
        }, $filename);
112
    }
113
114
    /**
115
     * Formats a profiling message for display as a string.
116
     *
117
     * @param array $message the profiling message to be formatted.
118
     * The message structure follows that in {@see Profiler::$messages}.
119
     *
120
     * @return string the formatted message.
121
     */
122 1
    protected function formatMessage(array $message): string
123
    {
124 1
        return date(
125 1
            'Y-m-d H:i:s',
126 1
            (int) $message['beginTime']
127 1
        ) . " [{$message['duration']} ms][{$message['memoryDiff']} B][{$message['category']}] {$message['token']}" .
128 1
        __METHOD__;
129
    }
130
}
131