Append REQUEST_URI to database queries (#2729)
authorTim Düsterhus <timwolla@googlemail.com>
Sun, 7 Oct 2018 11:17:19 +0000 (13:17 +0200)
committerAlexander Ebert <ebert@woltlab.com>
Sun, 7 Oct 2018 11:17:19 +0000 (13:17 +0200)
* Append REQUEST_URI to database queries

This might come in handy to debug long running queries in
production.

Idea stolen from: https://chris-lamb.co.uk/projects/django-append-url-to-sql

* Add ENABLE_PRODUCTION_DEBUG_MODE option

* Save a substr() if ENABLE_PRODUCTION_DEBUG_MODE is off

com.woltlab.wcf/option.xml
wcfsetup/install/files/lib/system/database/Database.class.php
wcfsetup/install/lang/de.xml
wcfsetup/install/lang/en.xml

index 0e4f78b18c141d0dd038e589c398feda644764ce..00c6364239dcf7e90c7121399fd18476c7d9b6f2 100644 (file)
                                <optiontype>boolean</optiontype>
                                <defaultvalue>0</defaultvalue>
                        </option>
+                       <option name="enable_production_debug_mode">
+                               <categoryname>module.development</categoryname>
+                               <optiontype>boolean</optiontype>
+                               <defaultvalue>1</defaultvalue>
+                       </option>
                        <option name="enable_benchmark">
                                <categoryname>module.development</categoryname>
                                <optiontype>boolean</optiontype>
index ae412051bcdf14c019e6c80e228b6a0240b1f067..d9c7af4d392c74aaa17079eb2f5a99957164a748 100644 (file)
@@ -240,7 +240,22 @@ abstract class Database {
                $statement = $this->handleLimitParameter($statement, $limit, $offset);
                
                try {
-                       $pdoStatement = $this->pdo->prepare($statement);
+                       // Append routing information of the current request as a comment.
+                       // This allows the system administrator to find offending requests
+                       // in MySQL's slow query log and / or MySQL's process list.
+                       // Note: This is meant to be run unconditionally in production to be
+                       //       useful. Thus the code to retrieve the request information
+                       //       must be absolutely lightweight.
+                       $requestInformation = '';
+                       if (ENABLE_PRODUCTION_DEBUG_MODE && isset($_SERVER['REQUEST_URI'])) {
+                               $requestInformation = substr($_SERVER['REQUEST_URI'], 0, 90);
+                               if (isset($_REQUEST['className']) && isset($_REQUEST['actionName'])) {
+                                       $requestInformation .= ' ('.$_REQUEST['className'].':'.$_REQUEST['actionName'].')';
+                               }
+                               $requestInformation = substr($requestInformation, 0, 180);
+                       }
+                       
+                       $pdoStatement = $this->pdo->prepare($statement.($requestInformation ? " -- ".$this->pdo->quote($requestInformation) : ''));
                        
                        return new $this->preparedStatementClassName($this, $pdoStatement, $statement);
                }
index a1b42b2478469b14db72ac977e25a992e7bb8ccc..ad47dcc7ff78f5dd6e91ab35a4c2334a14da6582 100644 (file)
                <item name="wcf.acp.option.show_version_number"><![CDATA[Versionsnummer der Software im Copyright-Hinweis anzeigen]]></item>
                <item name="wcf.acp.option.enable_debug_mode"><![CDATA[Debug-Modus aktivieren]]></item>
                <item name="wcf.acp.option.enable_debug_mode.description"><![CDATA[Aktiviert ausführliche Fehlerberichte. Diese Option sollte im Live-Betrieb abgeschaltet werden.]]></item>
+               <item name="wcf.acp.option.enable_production_debug_mode"><![CDATA[Problemanalyse im Live-Betrieb]]></item>
+               <item name="wcf.acp.option.enable_production_debug_mode.description"><![CDATA[Hängt die aktuelle URL an Datenbankabfragen an, um diese im Log des Datenbankservers einfacher identifizieren zu können.]]></item>
                <item name="wcf.acp.option.external_link_rel_nofollow"><![CDATA[Externe Links mit dem Attribut „rel="nofollow"“ versehen]]></item>
                <item name="wcf.acp.option.external_link_rel_nofollow.description"><![CDATA[Das Attribut „rel="nofollow"“ weist Suchmaschinen an, einen bestimmten Link auf einer Seite zu ignorieren.]]></item>
                <item name="wcf.acp.option.external_link_target_blank"><![CDATA[Externe Links in neuem Fenster öffnen]]></item>
index 8c49ecb8cd083f9f11efafbf5807376b5aed857c..7cd0a940b0802e32d2f0db5f5fd8bbb23f12c25f 100644 (file)
                <item name="wcf.acp.option.show_version_number"><![CDATA[Display version number in copyright notice]]></item>
                <item name="wcf.acp.option.enable_debug_mode"><![CDATA[Enable debug mode]]></item>
                <item name="wcf.acp.option.enable_debug_mode.description"><![CDATA[Enables extensive error messages, it should always be disabled in production environments!]]></item>
+               <item name="wcf.acp.option.enable_production_debug_mode"><![CDATA[Problem analysis in production environments]]></item>
+               <item name="wcf.acp.option.enable_production_debug_mode.description"><![CDATA[Appends the current URL to database queries to assist looking them up in the database server’s log files.]]></item>
                <item name="wcf.acp.option.external_link_rel_nofollow"><![CDATA[Append the attribute “rel="nofollow"” to all external links]]></item>
                <item name="wcf.acp.option.external_link_rel_nofollow.description"><![CDATA[The attribute “rel="nofollow"” tells search engines to disregard external links.]]></item>
                <item name="wcf.acp.option.external_link_target_blank"><![CDATA[Open external links in a new window]]></item>