Passed
Push — master ( 0ba500...61251f )
by Alexander
02:59
created

FileTarget::export()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3.0052

Importance

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