{"id":12214,"date":"2010-03-02T17:39:27","date_gmt":"2010-03-02T15:39:27","guid":{"rendered":"https:\/\/mamchenkov.net\/wordpress\/?p=12214"},"modified":"2010-03-02T17:39:27","modified_gmt":"2010-03-02T15:39:27","slug":"monitoring-php-errors-warnings-and-notices","status":"publish","type":"post","link":"https:\/\/mamchenkov.net\/wordpress\/2010\/03\/02\/monitoring-php-errors-warnings-and-notices\/","title":{"rendered":"Monitoring PHP errors, warnings, and notices"},"content":{"rendered":"<!-- google_ad_section_start -->\n<p>There are a number of ways to monitor PHP errors, warnings, and notices. \u00a0 You can have your application code trigger some error handling, you can use PHP built-in methods, you can have some scripts running in the background\u00a0analyzing logs, etc. \u00a0While you already probably do some of it, here is something that you&#8217;ll find handy.<\/p>\n<p>First of all, don&#8217;t log all PHP noise into a single file. \u00a0 You can easy make separate logs for each project. \u00a0Somewhere at the top of your project, when it only starts loading, add the following configuration settings:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\nini_set('error_reporting', E_ALL);\r\nini_set('log_errors', '1');\r\nini_set('error_log', '\/path\/to\/project\/logs\/php_errors.log');\r\nini_set('display_errors', '0');\r\n<\/pre>\n<p>This will enable logging of all errors, warnings, and notices into a file that you specified.  And, at the same time, it will disable the display of all the logs to your visitors (something that you should definitely do for a production server).<\/p>\n<p>One you&#8217;ve done that, you&#8217;ll notice another problem.  If your application is of any considerable size and\/or if it uses a lot of third-party code, you&#8217;ll get buried in all those warnings and notices.  The file will quickly become very large and boring and leave your attention span.  Not good.  While you can fight the size of the file with a tool like logrotate, the boredom is a more serious problem.  The same notices and warnings appear over and over and over.   You&#8217;ll fix some of them and the others will stay there forever.  What you need as a way to have a quick overview of what is broken and what is noisy.<\/p>\n<p>Today I wrote a quick cronjob to do just that.  Here it is in all its entirety.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\n#!\/bin\/bash\r\n\r\n# This script parses the project PHP errors logs every hour, creates the summary of all\r\n# errors\/warnings\/notices\/etc and emails that summary to the email specified below.\r\n\r\nEMAIL=&quot;me@here.com&quot;\r\nSUBJECT=&quot;here.com PHP errors summary for the last hour&quot;\r\nPHP_ERRORS_FILE=&quot;\/path\/to\/project\/logs\/php_errors.log&quot;\r\n\r\n# The log starts with timestamp like &#x5B;01-Mar-2010 12:48:56]. Timestamp + 1 stamp occupy about 24 bytes\r\nONE_HOUR_AGO=`date +'&#x5B;%d-%b-%Y %H:' -d '1 hour ago'`\r\n\r\n# We only need that double backslash because date pattern uses square bracket\r\ngrep &quot;^\\\\$ONE_HOUR_AGO&quot; $PHP_ERRORS_FILE | cut -b 24- | sort | uniq -c | sort -n -r | mail -s &quot;$SUBJECT&quot; $EMAIL\r\n<\/pre>\n<p>You can drop this file into <em>\/etc\/cron.hourly\/report_php_errors.sh<\/em>, change permissions to executable, and wait for the next run of hourly scripts.  If you&#8217;ve updated the variables inside the script to reflect the correct email address and path to log file, you&#8217;ll get an email every hour which will look something like this:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nFrom: cron@your.host\r\nTo: me@here.com\r\nSubject: here.com PHP errors summary for the last hour\r\n\r\n  14 PHP Notice:  Use of undefined constant PEAR_LOG_DEBUG - assumed 'PEAR_LOG_DEBUG' in \/some\/path\/to\/some\/file.php on line 17\r\n    12 PHP Notice:  Undefined index:  is_printed in \/path\/to\/something.php on line 2035\r\n     9 PHP Notice:  Undefined index:  blah in \/some\/foo\/bar.php on line 42\r\n     7 PHP Notice:  Undefined offset:  1 in \/some\/verifier\/script.php on line 120\r\n<\/pre>\n<p>The email will not be limited to 3 or 4 lines.  It will actually contain each and every individual notice, error, and warning that occurred during the last hour in your project.  The list will be sorted by how often each warning occurred, with the most frequent entries at the top.<\/p>\n<p>With this list you can start fixing your most frequently seen problems, and you can also notice weird activity much faster than just checking the log file and hoping to catch it with your own eyes.<\/p>\n<p>Enjoy!<\/p>\n<!-- google_ad_section_end -->\n","protected":false},"excerpt":{"rendered":"<!-- google_ad_section_start -->\n<p>There are a number of ways to monitor PHP errors, warnings, and notices. \u00a0 You can have your application code trigger some error handling, you can use PHP built-in methods, you can have some scripts running in the background\u00a0analyzing logs, etc. \u00a0While you already probably do some of it, here is something that you&#8217;ll find &hellip; <a href=\"https:\/\/mamchenkov.net\/wordpress\/2010\/03\/02\/monitoring-php-errors-warnings-and-notices\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Monitoring PHP errors, warnings, and notices<\/span><\/a><\/p>\n<!-- google_ad_section_end -->\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_links_to":"","_links_to_target":""},"categories":[1,18,133],"tags":[127,38],"keyring_services":[],"class_list":["post-12214","post","type-post","status-publish","format-standard","hentry","category-general","category-programming","category-sysadmin","tag-monitoring","tag-php"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":28553,"url":"https:\/\/mamchenkov.net\/wordpress\/2018\/05\/07\/php-application-logging-with-amazon-cloudwatch-logs-and-monolog\/","url_meta":{"origin":12214,"position":0},"title":"PHP application logging with Amazon CloudWatch Logs and Monolog","author":"Leonid Mamchenkov","date":"May 7, 2018","format":false,"excerpt":"AWS Developer Blog ran this post a while back - \"PHP application logging with Amazon CloudWatch Logs and Monolog\", in which they show how to use Monolog and Amazon CloudWatch together in any PHP application.\u00a0 It goes beyond a basic configuration of connecting the two, all the way into setting\u2026","rel":"","context":"In &quot;All&quot;","block_context":{"text":"All","link":"https:\/\/mamchenkov.net\/wordpress\/category\/general\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/mamchenkov.net\/wordpress\/wp-content\/uploads\/2018\/05\/php-aws-500x254.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":21711,"url":"https:\/\/mamchenkov.net\/wordpress\/2014\/04\/28\/monolog-logging-for-php-5-3\/","url_meta":{"origin":12214,"position":1},"title":"Monolog &#8211; Logging for PHP 5.3+","author":"Leonid Mamchenkov","date":"April 28, 2014","format":"link","excerpt":"Monolog - Logging for PHP 5.3+","rel":"","context":"In &quot;All&quot;","block_context":{"text":"All","link":"https:\/\/mamchenkov.net\/wordpress\/category\/general\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":25030,"url":"https:\/\/mamchenkov.net\/wordpress\/2015\/12\/10\/weird-php-error-output-bug\/","url_meta":{"origin":12214,"position":2},"title":"Weird PHP error output bug","author":"Leonid Mamchenkov","date":"December 10, 2015","format":false,"excerpt":"We came across this PHP bug at work today. \u00a0But before you go and read it, let me show you a use case. \u00a0See, if you can spot the problem. We had a cron job script which looked something like this (shortened for clarity): [code lang=\"bash\"] #!\/bin\/bash # ... a\u2026","rel":"","context":"In &quot;All&quot;","block_context":{"text":"All","link":"https:\/\/mamchenkov.net\/wordpress\/category\/general\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":42426,"url":"https:\/\/mamchenkov.net\/wordpress\/2019\/04\/09\/chrome-extensions-php-console-and-javascript-errors-notifier\/","url_meta":{"origin":12214,"position":3},"title":"Chrome Extensions: PHP Console and JavaScript Errors Notifier","author":"Leonid Mamchenkov","date":"April 9, 2019","format":false,"excerpt":"Here are a couple of handy Google Chrome extensions that I came across the other day. PHP Console PHP Console can display PHP errors and var dumps in the Google Chrome Developer Console and notification popups. It can also execute PHP code remotely, with the help of this server side\u2026","rel":"","context":"In &quot;All&quot;","block_context":{"text":"All","link":"https:\/\/mamchenkov.net\/wordpress\/category\/general\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/mamchenkov.net\/wordpress\/wp-content\/uploads\/2019\/04\/javascript-error-notifier.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/mamchenkov.net\/wordpress\/wp-content\/uploads\/2019\/04\/javascript-error-notifier.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/mamchenkov.net\/wordpress\/wp-content\/uploads\/2019\/04\/javascript-error-notifier.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":27113,"url":"https:\/\/mamchenkov.net\/wordpress\/2016\/12\/12\/quick-and-easy-introduction-into-php-mess-detector-phpmd\/","url_meta":{"origin":12214,"position":4},"title":"Quick and easy introduction into PHP Mess Detector (PHPMD)","author":"Leonid Mamchenkov","date":"December 12, 2016","format":false,"excerpt":"PHP Mess Detector is yet another one of those tools that help to keep the code base manageable and clean. \u00a0Here's the description straight from the site: What PHPMD does is: It takes a given PHP source code base and look for several potential problems within that source. These problems\u2026","rel":"","context":"In &quot;All&quot;","block_context":{"text":"All","link":"https:\/\/mamchenkov.net\/wordpress\/category\/general\/"},"img":{"alt_text":"PHP mess detector","src":"https:\/\/i0.wp.com\/mamchenkov.net\/wordpress\/wp-content\/uploads\/2016\/12\/mess-detector-500x99.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":24640,"url":"https:\/\/mamchenkov.net\/wordpress\/2015\/08\/24\/exceptions-and-errors-in-php-7\/","url_meta":{"origin":12214,"position":5},"title":"Exceptions and Errors in PHP 7","author":"Leonid Mamchenkov","date":"August 24, 2015","format":false,"excerpt":"\"An Exceptional Change in PHP 7.0\" blog post describes nicely what are the changes to exceptions and error handling in the upcoming PHP 7. \u00a0Among simple descriptions, there is this reference chart: [code light=\"true\"] \\Throwable \u251c\u2500\u2500 \\Exception (implements \\Throwable) \u2502 \u251c\u2500\u2500 \\LogicException (extends \\Exception) \u2502 \u2502 \u251c\u2500\u2500 \\BadFunctionCallException (extends \\LogicException)\u2026","rel":"","context":"In &quot;All&quot;","block_context":{"text":"All","link":"https:\/\/mamchenkov.net\/wordpress\/category\/general\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_sharing_enabled":true,"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/mamchenkov.net\/wordpress\/wp-json\/wp\/v2\/posts\/12214","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mamchenkov.net\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mamchenkov.net\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mamchenkov.net\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mamchenkov.net\/wordpress\/wp-json\/wp\/v2\/comments?post=12214"}],"version-history":[{"count":0,"href":"https:\/\/mamchenkov.net\/wordpress\/wp-json\/wp\/v2\/posts\/12214\/revisions"}],"wp:attachment":[{"href":"https:\/\/mamchenkov.net\/wordpress\/wp-json\/wp\/v2\/media?parent=12214"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mamchenkov.net\/wordpress\/wp-json\/wp\/v2\/categories?post=12214"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mamchenkov.net\/wordpress\/wp-json\/wp\/v2\/tags?post=12214"},{"taxonomy":"keyring_services","embeddable":true,"href":"https:\/\/mamchenkov.net\/wordpress\/wp-json\/wp\/v2\/keyring_services?post=12214"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}