Passed
Push — v1 ( 7780c4...c3c032 )
by Andrew
14:46 queued 07:19
created

ProfileTarget::collect()   B

Complexity

Conditions 7
Paths 9

Size

Total Lines 29
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 18
dl 0
loc 29
rs 8.8333
c 0
b 0
f 0
cc 7
nc 9
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 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...
16
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...
17
18
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
19
 * @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...
20
 * @package   Webperf
0 ignored issues
show
Coding Style introduced by
Tag value indented incorrectly; expected 1 spaces but found 3
Loading history...
21
 * @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...
22
 */
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...
23
class ProfileTarget extends Target
24
{
25
26
    const PROFILE_CATEGORIES = [
27
        'database' => [
28
            'prefix' => 'yii\db',
29
        ],
30
        'twig' => [
31
            'prefix' => 'craft\web\twig\Template',
32
        ],
33
        'other' => [
34
            'prefix' => 'webperf-other',
35
        ],
36
    ];
37
38
    // Public Properties
39
    // =========================================================================
40
41
    public $stats = [];
42
43
    // Public Methods
44
    // =========================================================================
45
46
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
47
     * @inheritdoc
48
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
49
    public function init()
50
    {
51
        parent::init();
52
        foreach (self::PROFILE_CATEGORIES as $key => $value) {
53
            $this->stats[$key] = [
54
                'count' => 0,
55
                'duration' => 0.0,
56
                'memory' => 0,
57
            ];
58
        }
59
    }
60
61
    /**
62
     * Processes the given log messages.
63
     * This method will filter the given messages with [[levels]] and [[categories]].
64
     * And if requested, it will also export the filtering result to specific medium (e.g. email).
65
     * @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...
66
     * of each message.
0 ignored issues
show
Coding Style introduced by
Parameter comment not aligned correctly; expected 24 spaces but found 1
Loading history...
67
     * @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...
68
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
69
    public function collect($messages, $final)
70
    {
71
        // Bail if either values are null
72
        if (($messages === null) || ($this->messages === null)) {
73
            return;
74
        }
75
        // Merge in any messages intended for us
76
        $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...
77
            $this->messages,
78
            static::filterMessages($messages, $this->getLevels(), $this->categories, $this->except)
79
        );
80
        // Calculate the timings from the messages, and then reset them
81
        $timings = $this->calculateTimings($this->messages);
82
        $this->messages = [];
83
        // Loop through and tally up all of the timings
84
        foreach ($timings as $timing) {
85
            $cat = 'other';
86
            foreach (self::PROFILE_CATEGORIES as $key => $value) {
87
                if (strpos($timing['category'], $value['prefix']) === 0) {
88
                    $cat = $key;
89
                }
90
            }
91
            $this->stats[$cat]['count']++;
92
            $this->stats[$cat]['duration'] += (float)$timing['duration'] * 1000;
93
            $this->stats[$cat]['memory'] += (int)$timing['memoryDiff'];
94
        }
95
        if ($final) {
96
            $this->export();
97
            Webperf::$plugin->beacons->includeCraftBeacon();
98
        }
99
    }
100
101
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
102
     * @inheritdoc
103
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
104
    public function export()
105
    {
106
    }
107
108
    // Protected Methods
109
    // =========================================================================
110
111
    /**
112
     * Calculates the elapsed time for the given log messages.
113
     * @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...
114
     * @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...
115
     * `info`, `category`, `timestamp`, `trace`, `level`, `duration`, `memory`, `memoryDiff`.
116
     * The `memory` and `memoryDiff` values are available since version 2.0.11.
117
     */
118
    protected function calculateTimings($messages): array
119
    {
120
        $timings = [];
121
        $stack = [];
122
123
        foreach ($messages as $i => $log) {
124
            list($token, $level, $category, $timestamp, $traces) = $log;
125
            $memory = isset($log[5]) ? $log[5] : 0;
126
            $log[6] = $i;
127
            $hash = md5(json_encode($token));
128
            if ($level == Logger::LEVEL_PROFILE_BEGIN) {
129
                $stack[$hash] = $log;
130
            } elseif ($level == Logger::LEVEL_PROFILE_END) {
131
                if (isset($stack[$hash])) {
132
                    $timings[$stack[$hash][6]] = [
133
                        'category' => $stack[$hash][2],
134
                        'timestamp' => $stack[$hash][3],
135
                        'level' => count($stack) - 1,
136
                        'duration' => $timestamp - $stack[$hash][3],
137
                        'memory' => $memory,
138
                        'memoryDiff' => $memory - (isset($stack[$hash][5]) ? $stack[$hash][5] : 0),
139
                    ];
140
                    unset($stack[$hash]);
141
                }
142
            }
143
        }
144
145
        return array_values($timings);
146
    }
147
}
148