PluginProbe ʕ •ᴥ•ʔ
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization / 1.19.4
NitroPack – Performance, Page Speed & Cache Plugin for Core Web Vitals, CDN & Image Optimization v1.19.4
1.19.8 1.19.7 1.19.6 1.19.5 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.11.0 1.12.0 1.13.0 1.14.0 1.15.0 1.15.1 1.15.2 1.15.3 1.16.0 1.16.1 1.16.2 1.16.3 1.16.4 1.16.5 1.16.6 1.16.7 1.16.8 1.17.0 1.17.6 1.17.7 1.17.8 1.17.9 1.18.0 1.18.1 1.18.2 1.18.3 1.18.4 1.18.5 1.18.6 1.18.7 1.18.8 1.18.9 1.19.0 1.19.1 1.19.2 1.19.3 1.19.4 1.3.19 1.3.20 1.4.0 1.4.1 1.5.0 1.5.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.16 1.5.17 1.5.18 1.5.19 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.7.0 1.7.1 1.8.0 1.8.1 1.8.3 1.9.0 1.9.1 1.9.2
nitropack / classes / WordPress / Settings / Logger.php
nitropack / classes / WordPress / Settings Last commit date
AutoPurge.php 4 months ago BeaverBuilder.php 4 months ago CPTOptimization.php 4 months ago CacheWarmup.php 3 months ago CartCache.php 4 months ago Components.php 3 months ago EditorClearCache.php 4 months ago GeneratePreview.php 7 months ago HTMLCompression.php 3 months ago Logger.php 4 months ago OptimizationLevel.php 3 months ago Optimizations.php 4 months ago PurgeCache.php 4 months ago Shortcodes.php 4 months ago StockRefresh.php 2 months ago Subscription.php 4 months ago SystemReport.php 3 months ago TestMode.php 4 months ago
Logger.php
310 lines
1 <?php
2
3 namespace NitroPack\WordPress\Settings;
4
5 /**
6 * Logger Class for NitroPack WordPress plugin
7 *
8 * This class provides logging functionality with different log levels
9 */
10 class Logger {
11 /**
12 * @var mixed $siteConfig Configuration settings for the site.
13 * @var string $archive_zip_name Name of the archive zip file for logs.
14 * @var string $log_file_extension Extension of the log files.
15 */
16 public $siteConfig;
17 public $archive_zip_name;
18 public $log_file_extension;
19
20 public function __construct( $config ) {
21
22 add_action( 'wp_ajax_nitropack_set_log_level_ajax', [ $this, 'nitropack_set_log_level_ajax' ] );
23 add_action( 'wp_ajax_nitropack_archive_logs_ajax', [ $this, 'nitropack_archive_logs_ajax' ] );
24 add_action( 'wp_ajax_nitropack_download_log_ajax', [ $this, 'nitropack_download_log_ajax' ] );
25
26 $this->siteConfig = $config;
27 $this->archive_zip_name = 'nitropack_logs.zip';
28 $this->log_file_extension = 'csv';
29 }
30 /**
31 * Render the logger settings in System Report
32 */
33 public function render() {
34 $components = new Components();
35 $siteConfig = nitropack_get_site_config();
36 $minimumLogLevel = $siteConfig['minimumLogLevel'];
37 ?>
38 <div class="flex">
39 <div class="" style="flex-basis: 80%;">
40 <h3><?php esc_html_e( 'Generate Log File', 'nitropack' ); ?></h3>
41 <p><?php esc_html_e( 'Logs keep track of what is happening on your site—like when plugins are installed, posts are published, or something goes wrong. They\'re great for finding and fixing tricky problems, especially with our support\'s help. Logs are saved for up to 14 days.', 'nitropack' ); ?>
42 <a href="https://support.nitropack.io/en/articles/10243831-how-to-use-the-generate-log-file-feature-in-your-wordpress-dashboard"
43 target="_blank"><?php esc_html_e( 'Learn more', 'nitropack' ); ?></a>
44 </p>
45 </div>
46 <div class="ml-auto">
47 <?php $components->render_toggle( 'minimum-log-level-status', $minimumLogLevel ); ?>
48 </div>
49 </div>
50 <div class="logging<?php echo $minimumLogLevel ? '' : ' hidden'; ?>">
51 <div class="select-log-level">
52 <h4><?php esc_html_e( 'Select log level', 'nitropack' );
53 $components->render_tooltip( 'select-log-level', 'Select and generate log output by categorizing messages based on their urgency.' ); ?>
54 </h4>
55 <div class="radio-options-group">
56 <?php $components->render_fancy_radio( 3, 'set-log-level-error', 'set-log-level', $minimumLogLevel === 3 ? true : false, esc_html__( 'Minimal (Errors Only)', 'nitropack' ), esc_html__( 'Perfect for live websites where you can quickly spot and address serious issues without unnecessary noise.', 'nitropack' ) );
57 $components->render_fancy_radio( 2, 'set-log-level-info', 'set-log-level', $minimumLogLevel === 2 ? true : false, esc_html__( 'Moderate (Errors & Actions)', 'nitropack' ), esc_html__( 'Best used during site maintenance or troubleshooting to get a clearer view of your site\'s activities.', 'nitropack' ) );
58 $components->render_fancy_radio( 1, 'set-log-level-info', 'set-log-level', $minimumLogLevel === 1 ? true : false, esc_html__( 'Detailed (Errors, Actions & Full Details)', 'nitropack' ), esc_html__( 'Great when debugging issues with our support team. Avoid using it constantly as it is very detailed and may fill up quickly.', 'nitropack' ) ); ?>
59 </div>
60 </div>
61
62 <div class="log-table-container">
63 <table id="log-table">
64 <thead>
65 <tr>
66 <th><?php esc_html_e( 'Log Name', 'nitropack' ); ?></th>
67 <th><?php esc_html_e( 'File size', 'nitropack' ); ?></th>
68 <th><?php esc_html_e( 'Date added', 'nitropack' ); ?></th>
69 </tr>
70 </thead>
71 <tbody>
72 <?php if ( is_dir( NITROPACK_LOGS_DATA_DIR ) ) :
73 $files = scandir( NITROPACK_LOGS_DATA_DIR );
74 $files = array_filter( $files, function ($file) {
75 return pathinfo( $file, PATHINFO_EXTENSION ) === $this->log_file_extension;
76 } );
77
78 // Sort files by modification time, newest first
79 usort( $files, function ($a, $b) {
80 $filePathA = NITROPACK_LOGS_DATA_DIR . '/' . $a;
81 $filePathB = NITROPACK_LOGS_DATA_DIR . '/' . $b;
82 return filemtime( $filePathB ) - filemtime( $filePathA );
83 } );
84 if ( ! empty( $files ) ) :
85 $fileDates = [];
86 foreach ( $files as $file ) :
87 $filePath = NITROPACK_LOGS_DATA_DIR . '/' . $file;
88 $fileURL = $this->get_logs_dir_url() . $file;
89 $fileSize = filesize( $filePath );
90 $fileDate = date( "F d, Y H:i", filemtime( $filePath ) );
91 $fileDates[] = filemtime( $filePath );
92 $fileDateParts = explode( ' ', $fileDate );
93 $datePart = implode( ' ', array_slice( $fileDateParts, 0, 3 ) );
94 $timePart = $fileDateParts[3]; ?>
95 <tr>
96 <td class="file"><a href="<?php echo esc_url( $fileURL ); ?>"
97 target="_blank"><?php echo esc_html( $file ); ?></a></td>
98 <td class="file-size"><?php echo esc_html( size_format( $fileSize ) ); ?></td>
99 <td class="file-date"><?php echo "{$datePart} <div class='time'>{$timePart}</div>"; ?></td>
100 </tr>
101 <?php endforeach;
102 else :
103 echo '<tr class="no-logs"><td colspan="3">' . esc_html__( 'No error logs yet.', 'nitropack' ) . '</td></tr>';
104 endif;
105 else :
106 echo '<tr class="no-logs"><td colspan="3">' . esc_html__( 'No error logs yet.', 'nitropack' ) . '</td></tr>';
107 endif; ?>
108 </tbody>
109 </table>
110 </div>
111 <?php
112 if ( ! empty( $fileDates ) ) {
113 rsort( $fileDates );
114 $latestDate = date( "F d, Y", $fileDates[0] );
115 $earliestDate = date( "F d, Y", end( $fileDates ) );
116 ?>
117 <div class="download-all-logs">
118 <div>
119 <h3><?php esc_html_e( 'Download all logs', 'nitropack' ); ?></h3>
120 <p><?php printf( esc_html__( 'Download usage for %1$s - %2$s', 'nitropack' ), esc_html( $earliestDate ),
121 esc_html( $latestDate )
122 ); ?>
123 </p>
124 </div>
125 <?php if ( class_exists( 'ZipArchive' ) ) {
126 $components->render_button( [
127 'text' => 'Download all (.zip)',
128 'type' => 'a',
129 'href' => '',
130 'icon' => 'download.svg',
131 'classes' => 'btn btn-secondary archive-logs',
132 'attributes' => [ 'download' => '' ]
133 ] );
134 } else {
135 $components->render_button( [
136 'text' => 'Download all (.zip)',
137 'type' => 'a',
138 'href' => '',
139 'icon' => 'download.svg',
140 'classes' => 'btn btn-secondary archive-logs disabled',
141 ] );
142 } ?>
143 </div>
144 <?php if ( ! class_exists( 'ZipArchive' ) ) {
145 $components->render_notification( esc_html__( 'Bulk log downloads aren\'t available because the PHP ext-zip isn\'t enabled. Contact your hosting provider or download files individually.', 'nitropack' ), 'error' );
146 } ?>
147 <?php } ?>
148 </div>
149 <?php
150 }
151
152 /**
153 * Handles the AJAX request to set the log level for NitroPack.
154 *
155 * This method verifies the AJAX nonce, retrieves the minimum log level from the POST request,
156 * updates the site configuration with the new log level, and returns a JSON response indicating
157 * success or failure.
158 * $minimumLogLevel is set to 1 for info logs and 2 for error logs, and null if the log level is not set.
159 * @return void
160 */
161 public function nitropack_set_log_level_ajax() {
162 nitropack_verify_ajax_nonce( $_REQUEST );
163
164 $minimumLogLevel = isset( $_POST['minimum_log_level'] ) ? $_POST['minimum_log_level'] : null;
165
166 if ( $minimumLogLevel && is_numeric( $minimumLogLevel ) ) {
167 $minimumLogLevel = (int) $minimumLogLevel;
168 } else {
169 $minimumLogLevel = null;
170 }
171
172 $siteConfig = $this->siteConfig->get();
173 $configKey = \NitroPack\WordPress\NitroPack::getConfigKey();
174 $siteConfig[ $configKey ]['minimumLogLevel'] = $minimumLogLevel;
175
176 //store it as null or integer in config.json
177 $config_updated = $this->siteConfig->set( $siteConfig );
178
179 //store it as empty string or numeric string in the database
180 if ( $minimumLogLevel === null ) {
181 $minimumLogLevel = '';
182 }
183 $updated = update_option( 'nitropack-minimumLogLevel', $minimumLogLevel );
184 if ( $config_updated && $updated ) {
185
186 nitropack_json_and_exit( array( "type" => "success", "message" => nitropack_admin_toast_msgs( 'success' ) ) );
187 } else {
188 nitropack_json_and_exit( array(
189 "type" => "error",
190 "message" => nitropack_admin_toast_msgs( 'error' )
191 ) );
192 }
193 }
194
195 /**
196 * Archives log files into a zip archive and returns the archive URL via AJAX.
197 *
198 * This function is triggered via an AJAX request and performs the following steps:
199 * 1. Verifies the AJAX nonce.
200 * 2. Creates a new ZipArchive instance.
201 * 3. Iterates through the log files in the specified directory and stores mmodification date
202 * 4. Filters out non-csv files, checks if the file has been modified and adds it to the zip archive.
203 * 5. Closes the zip archive.
204 * 6. Returns a success message and the archive URL if the process is successful.
205 * 7. Returns an error message if any step fails.
206 *
207 * @return void
208 */
209
210 public function nitropack_archive_logs_ajax() {
211 nitropack_verify_ajax_nonce( $_REQUEST );
212
213 $zip = new \ZipArchive();
214 $archivePath = $this->get_archive_zip_path();
215
216 if ( $zip->open( $archivePath, \ZipArchive::CREATE | \ZipArchive::OVERWRITE ) === TRUE ) {
217 $files = new \RecursiveIteratorIterator(
218 new \RecursiveDirectoryIterator( NITROPACK_LOGS_DATA_DIR ),
219 \RecursiveIteratorIterator::LEAVES_ONLY
220 );
221
222 // Store the modification times of the existing files in the ZIP archive
223 $existingFiles = [];
224 for ( $i = 0; $i < $zip->numFiles; $i++ ) {
225 $stat = $zip->statIndex( $i );
226 $existingFiles[ $stat['name'] ] = $stat['mtime'];
227 }
228
229 foreach ( $files as $name => $file ) {
230 if ( ! $file->isDir() ) {
231 $filePath = $file->getRealPath();
232 $relativePath = substr( $filePath, strlen( NITROPACK_LOGS_DATA_DIR ) );
233
234 // Filter out non-csv files
235 if ( pathinfo( $filePath, PATHINFO_EXTENSION ) !== $this->log_file_extension )
236 continue;
237
238 // Check if the file has been modified
239 $fileMTime = filemtime( $filePath );
240 if ( ! isset( $existingFiles[ $relativePath ] ) || $fileMTime > $existingFiles[ $relativePath ] ) {
241 if ( ! $zip->addFile( $filePath, $relativePath ) ) {
242 error_log( "Failed to add file: $filePath" );
243 nitropack_json_and_exit( array(
244 "type" => "error",
245 "message" => nitropack_admin_toast_msgs( 'error' )
246 ) );
247 }
248 }
249 }
250 }
251
252 if ( ! $zip->close() ) {
253 error_log( "Failed to close zip archive: " . $archivePath );
254 nitropack_json_and_exit( array(
255 "type" => "error",
256 "message" => nitropack_admin_toast_msgs( 'error' )
257 ) );
258 }
259
260 // Check if the archive file exists
261 if ( file_exists( $archivePath ) ) {
262 $archive_url = $this->get_archive_url();
263 error_log( "Archive URL: " . $archive_url );
264
265 nitropack_json_and_exit( array( "type" => "success", "message" => nitropack_admin_toast_msgs( 'success' ), "url" => $archive_url ) );
266 } else {
267 error_log( "Archive file does not exist: " . $archivePath );
268 nitropack_json_and_exit( array(
269 "type" => "error",
270 "message" => nitropack_admin_toast_msgs( 'error' )
271 ) );
272 }
273 } else {
274 error_log( "Failed to open zip archive: " . $archivePath );
275 nitropack_json_and_exit( array(
276 "type" => "error",
277 "message" => nitropack_admin_toast_msgs( 'error' )
278 ) );
279 }
280 }
281 /**
282 * Gets the url of the log dir
283 * Example: https://website.com/wp-content/wp-content/uploads/nitropack-logs/
284 * Use the filter if you have changed the constant NITROPACK_LOGS_DATA_DIR
285 * @return string
286 */
287 public function get_logs_dir_url() {
288 $dir_url = content_url() . '/uploads/nitropack-logs/';
289 return apply_filters( 'nitropack_logs_dir_url', $dir_url );
290 }
291 /**
292 * Gets the path of the nitropack_logs.zip
293 * Example: /var/www/html/wp-content/uploads/nitropack-logs/nitropack_logs.zip
294 * @return string
295 */
296 private function get_archive_zip_path() {
297 $path = NITROPACK_LOGS_DATA_DIR . $this->archive_zip_name;
298 return $path;
299 }
300 /**
301 * Gets the path of the nitropack_logs.zip
302 * Example: https://website.com/wp-content/uploads/nitropack-logs/nitropack_logs.zip
303 * @return string
304 */
305 private function get_archive_url() {
306 $url = $this->get_logs_dir_url() . $this->archive_zip_name;
307 return $url;
308 }
309 }
310