Passed
Push — develop ( 277eb8...5d2df0 )
by Andrew
03:26
created

ProfileTarget::collect()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 25
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 25
rs 9.4222
c 0
b 0
f 0
cc 5
nc 8
nop 2
1
<?php
2
/**
3
 * Webperf plugin for Craft CMS 3.x
4
 *
5
 * Monitor the performance of your webpages through real-world user timing data
6
 *
7
 * @link      https://nystudio107.com
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
8
 * @copyright Copyright (c) 2018 nystudio107
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
9
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
10
11
namespace nystudio107\webperf\log;
12
13
use nystudio107\webperf\Webperf;
14
15
use Craft;
0 ignored issues
show
Bug introduced by
The type Craft was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
17
use yii\log\Target;
0 ignored issues
show
Bug introduced by
The type yii\log\Target was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
use yii\log\Logger;
0 ignored issues
show
Bug introduced by
The type yii\log\Logger was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
20
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
21
 * @author    nystudio107
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @package tag
Loading history...
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 4
Loading history...
22
 * @package   Webperf
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 3
Loading history...
23
 * @since     1.0.0
0 ignored issues
show
Coding Style introduced by
The tag in position 3 should be the @author tag
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 3 spaces but found 5
Loading history...
24
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
25
class ProfileTarget extends Target
26
{
27
28
    const PROFILE_CATEGORIES = [
29
        'database' => [
30
            'prefix' => 'yii\db',
31
        ],
32
        'twig' => [
33
            'prefix' => 'craft\web\twig\Template',
34
        ],
35
        'other' => [
36
            'prefix' => 'webperf-other',
37
        ],
38
    ];
39
40
    // Public Properties
41
    // =========================================================================
42
43
    public $stats = [];
44
45
    // Public Methods
46
    // =========================================================================
47
48
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
49
     * @inheritdoc
50
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
51
    public function init()
52
    {
53
        parent::init();
54
        foreach (self::PROFILE_CATEGORIES as $key => $value) {
55
            $this->stats[$key] = [
56
                'count' => 0,
57
                'duration' => 0.0,
58
                'memory' => 0,
59
            ];
60
        }
61
    }
62
63
    /**
64
     * Processes the given log messages.
65
     * This method will filter the given messages with [[levels]] and [[categories]].
66
     * And if requested, it will also export the filtering result to specific medium (e.g. email).
67
     * @param array $messages log messages to be processed. See [[Logger::messages]] for the structure
0 ignored issues
show
Coding Style introduced by
There must be exactly one blank line before the tags in a doc comment
Loading history...
68
     * of each message.
0 ignored issues
show
Coding Style introduced by
Parameter comment not aligned correctly; expected 24 spaces but found 1
Loading history...
69
     * @param bool $final whether this method is called at the end of the current application
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
70
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
71
    public function collect($messages, $final)
72
    {
73
        // Merge in any messages intended for us
74
        $this->messages = array_merge(
0 ignored issues
show
Bug Best Practice introduced by
The property messages does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
75
            $this->messages,
76
            static::filterMessages($messages, $this->getLevels(), $this->categories, $this->except)
77
        );
78
        // Calculate the timings from the messages, and then reset them
79
        $timings = $this->calculateTimings($this->messages);
80
        $this->messages = [];
81
        // Loop through and tally up all of the timings
82
        foreach ($timings as $timing) {
83
            $cat = 'other';
84
            foreach (self::PROFILE_CATEGORIES as $key => $value) {
85
                if (strpos($timing['category'], $value['prefix']) === 0) {
86
                    $cat = $key;
87
                }
88
            }
89
            $this->stats[$cat]['count']++;
90
            $this->stats[$cat]['duration'] += (float)$timing['duration'] * 1000;
91
            $this->stats[$cat]['memory'] += (int)$timing['memoryDiff'];
92
        }
93
        if ($final) {
94
            $this->export();
95
            Webperf::$plugin->beacons->includeCraftBeacon();
96
        }
97
    }
98
99
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
100
     * @inheritdoc
101
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
102
    public function export()
103
    {
104
    }
105
106
    // Protected Methods
107
    // =========================================================================
108
109
    /**
110
     * Calculates the elapsed time for the given log messages.
111
     * @param array $messages the log messages obtained from profiling
0 ignored issues
show
Coding Style introduced by
There must be exactly one blank line before the tags in a doc comment
Loading history...
Coding Style introduced by
Tag value indented incorrectly; expected 2 spaces but found 1
Loading history...
112
     * @return array timings. Each element is an array consisting of these elements:
0 ignored issues
show
Coding Style introduced by
Tag cannot be grouped with parameter tags in a doc comment
Loading history...
113
     * `info`, `category`, `timestamp`, `trace`, `level`, `duration`, `memory`, `memoryDiff`.
114
     * The `memory` and `memoryDiff` values are available since version 2.0.11.
115
     */
116
    protected function calculateTimings($messages): array
117
    {
118
        $timings = [];
119
        $stack = [];
120
121
        foreach ($messages as $i => $log) {
122
            list($token, $level, $category, $timestamp, $traces) = $log;
123
            $memory = isset($log[5]) ? $log[5] : 0;
124
            $log[6] = $i;
125
            $hash = md5(json_encode($token));
126
            if ($level == Logger::LEVEL_PROFILE_BEGIN) {
127
                $stack[$hash] = $log;
128
            } elseif ($level == Logger::LEVEL_PROFILE_END) {
129
                if (isset($stack[$hash])) {
130
                    $timings[$stack[$hash][6]] = [
131
                        'category' => $stack[$hash][2],
132
                        'timestamp' => $stack[$hash][3],
133
                        'level' => count($stack) - 1,
134
                        'duration' => $timestamp - $stack[$hash][3],
135
                        'memory' => $memory,
136
                        'memoryDiff' => $memory - (isset($stack[$hash][5]) ? $stack[$hash][5] : 0),
137
                    ];
138
                    unset($stack[$hash]);
139
                }
140
            }
141
        }
142
143
        return array_values($timings);
144
    }
145
}
146