C:\xampp\htdocs\landing\wp-content\plugins\amp\src\BackgroundTask\MonitorCssTransientCaching.php


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
<?php
/**
 * Class MonitorCssTransientCaching.
 *
 * @package AmpProject\AmpWP
 */

namespace AmpProject\AmpWP\BackgroundTask;

use 
AMP_Options_Manager;
use 
AmpProject\AmpWP\Option;
use 
DateTimeImmutable;
use 
DateTimeInterface;
use 
Exception;

/**
 * Monitor the CSS transient caching to detect and remedy issues.
 *
 * This checks whether there's excessive cycling of CSS cached stylesheets and disables transient caching if so.
 *
 * @package AmpProject\AmpWP
 * @since 2.0
 * @internal
 */
final class MonitorCssTransientCaching extends CronBasedBackgroundTask {

    
/**
     * Name of the event to schedule.
     *
     * @var string
     */
    
const EVENT_NAME 'amp_monitor_css_transient_caching';

    
/**
     * Key to use to persist the time series in the WordPress options table.
     *
     * @var string
     */
    
const TIME_SERIES_OPTION_KEY 'amp_css_transient_monitor_time_series';

    
/**
     * Default threshold to use for problem detection in number of transients per day.
     *
     * This is set high to avoid false positives and only trigger on high-traffic sites that exhibit serious problems.
     *
     * @var float
     */
    
const DEFAULT_THRESHOLD 5000.0;

    
/**
     * Sampling range in days to calculate the moving average from.
     *
     * @var int
     */
    
const DEFAULT_SAMPLING_RANGE 14;

    
/**
     * Register the service with the system.
     *
     * @return void
     */
    
public function register() {
        
add_action'amp_plugin_update', [ $this'handle_plugin_update' ] );
        
parent::register();
    }

    
/**
     * Get the interval to use for the event.
     *
     * @return string An existing interval name. Valid values are 'hourly', 'twicedaily' or 'daily'.
     */
    
protected function get_interval() {
        return 
self::DEFAULT_INTERVAL_DAILY;
    }

    
/**
     * Get the event name.
     *
     * This is the "slug" of the event, not the display name.
     *
     * Note: the event name should be prefixed to prevent naming collisions.
     *
     * @return string Name of the event.
     */
    
protected function get_event_name() {
        return 
self::EVENT_NAME;
    }

    
/**
     * Process a single cron tick.
     *
     * @todo This has arbitrary arguments to allow for testing, as we don't have dependency injection for services.
     *       With dependency injection, we could for example inject a Clock object and mock it for testing.
     *
     * @param DateTimeInterface $date            Optional. Date to use for timestamping the processing (for testing).
     * @param int               $transient_count Optional. Count of transients to use for the processing (for testing).
     * @return void
     * @throws Exception If a date could not be instantiated.
     */
    
public function processDateTimeInterface $date null$transient_count null ) {
        if ( 
wp_using_ext_object_cache() || $this->is_css_transient_caching_disabled() ) {
            return;
        }

        if ( 
null === $date ) {
            
$date = new DateTimeImmutable();
        }

        if ( 
null === $transient_count ) {
            
$transient_count $this->query_css_transient_count();
        }

        
$date_string $date->format'Ymd' );
        
$time_series $this->get_time_series();

        
$time_series$date_string ] = $transient_count;
        
ksort$time_series );

        
$sampling_range $this->get_sampling_range();
        
$time_series    array_slice$time_series, - $sampling_rangenulltrue );

        
$this->persist_time_series$time_series );

        
$moving_average $this->calculate_average$time_series );

        if ( 
$moving_average 0.0 && $moving_average > (float) $this->get_threshold() ) {
            
$this->disable_css_transient_caching();
        }
    }

    
/**
     * Check whether transient caching of stylesheets is disabled.
     *
     * @return bool Whether transient caching of stylesheets is disabled.
     */
    
private function is_css_transient_caching_disabled() {
        return 
AMP_Options_Manager::get_optionOption::DISABLE_CSS_TRANSIENT_CACHINGfalse );
    }

    
/**
     * Disable transient caching of stylesheets.
     */
    
private function disable_css_transient_caching() {
        
AMP_Options_Manager::update_optionOption::DISABLE_CSS_TRANSIENT_CACHINGtrue );
    }

    
/**
     * Query the number of transients containing cache stylesheets.
     *
     * @return int Count of transients caching stylesheets.
     */
    
public function query_css_transient_count() {
        global 
$wpdb;

        return (int) 
$wpdb->get_var(
            
"SELECT COUNT(*) FROM {$wpdb->options} WHERE option_name LIKE '_transient_amp-parsed-stylesheet%'"
        
);
    }

    
/**
     * Handle update to plugin.
     *
     * @param string $old_version Old version.
     */
    
public function handle_plugin_update$old_version ) {
        
// Reset the disabling of the CSS caching subsystem when updating from versions 1.5.0 or 1.5.1.
        
if ( version_compare$old_version'1.5.0''>=' ) && version_compare$old_version'1.5.2''<' ) ) {
            
AMP_Options_Manager::update_optionOption::DISABLE_CSS_TRANSIENT_CACHINGfalse );
        }
    }

    
/**
     * Get the time series stored in the WordPress options table.
     *
     * @return int[] Time series with the count of transients per day.
     */
    
public function get_time_series() {
        return (array) 
get_optionself::TIME_SERIES_OPTION_KEY, [] );
    }

    
/**
     * Get the default threshold to use.
     *
     * @return float Default threshold to use.
     */
    
public function get_default_threshold() {
        return 
self::DEFAULT_THRESHOLD;
    }

    
/**
     * Get the default sampling range to use.
     *
     * @return int Default sampling range to use.
     */
    
public function get_default_sampling_range() {
        return 
self::DEFAULT_SAMPLING_RANGE;
    }

    
/**
     * Persist the time series in the database.
     *
     * @param int[] $time_series Associative array of integers with the key being a date string and the value the count
     *                           of transients.
     */
    
private function persist_time_series$time_series ) {
        
update_optionself::TIME_SERIES_OPTION_KEY$time_seriesfalse );
    }

    
/**
     * Calculate the average for the provided time series.
     *
     * Note: The single highest value is discarded to calculate the average, so as to avoid a single outlier causing the
     * threshold to be reached.
     *
     * @param int[] $time_series Associative array of integers with the key being a date string and the value the count
     *                           of transients.
     * @return float Average value for the provided time series.
     */
    
private function calculate_average$time_series ) {
        
$sum                   array_sum$time_series );
        
$sum_without_outlier   $sum max$time_series );
        
$count_without_outlier count$time_series ) - 1;

        if ( 
$count_without_outlier <= ) {
            return 
0.0;
        }

        return 
$sum_without_outlier $count_without_outlier;
    }

    
/**
     * Get the threshold to check the moving average against.
     *
     * This can be filtered via the 'amp_css_transient_monitoring_threshold' filter.
     *
     * @return float Threshold to use.
     */
    
private function get_threshold() {

        
/**
         * Filters the threshold to use for disabling transient caching of stylesheets.
         *
         * @since 1.5.0
         *
         * @param int $threshold Maximum average number of transients per day.
         */
        
$threshold = (float) apply_filters'amp_css_transient_monitoring_threshold'self::DEFAULT_THRESHOLD );

        return 
$threshold 0.0 $threshold self::DEFAULT_THRESHOLD;
    }

    
/**
     * Get the sampling range to limit the time series to for calculating the moving average.
     *
     * This can be filtered via the 'amp_css_transient_monitoring_sampling_range' filter.
     *
     * @return int Sampling range to use.
     */
    
private function get_sampling_range() {

        
/**
         * Filters the sampling range to use for monitoring the transient caching of stylesheets.
         *
         * @since 1.5.0
         *
         * @param int $sampling_rage Sampling range in number of days.
         */
        
$sampling_range = (int) apply_filters'amp_css_transient_monitoring_sampling_range'self::DEFAULT_SAMPLING_RANGE );

        return 
$sampling_range $sampling_range self::DEFAULT_SAMPLING_RANGE;
    }
}
x

Windows NT KPTV 6.2 build 9200 (Windows Server 2012 Datacenter Edition) i586