]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - classes/Memcached_DataObject.php
Merge branch 'master' into testing
[quix0rs-gnu-social.git] / classes / Memcached_DataObject.php
index bc4c3a000ce11a732bc495e878fc018854dcd79d..0836c2019f82486232f196a977b25f0563318f5d 100644 (file)
@@ -330,6 +330,10 @@ class Memcached_DataObject extends Safe_DataObject
      */
     function _query($string)
     {
+        if (common_config('db', 'annotate_queries')) {
+            $string = $this->annotateQuery($string);
+        }
+
         $start = microtime(true);
         $result = parent::_query($string);
         $delta = microtime(true) - $start;
@@ -342,6 +346,70 @@ class Memcached_DataObject extends Safe_DataObject
         return $result;
     }
 
+    /**
+     * Find the first caller in the stack trace that's not a
+     * low-level database function and add a comment to the
+     * query string. This should then be visible in process lists
+     * and slow query logs, to help identify problem areas.
+     * 
+     * Also marks whether this was a web GET/POST or which daemon
+     * was running it.
+     *
+     * @param string $string SQL query string
+     * @return string SQL query string, with a comment in it
+     */
+    function annotateQuery($string)
+    {
+        $ignore = array('annotateQuery',
+                        '_query',
+                        'query',
+                        'get',
+                        'insert',
+                        'delete',
+                        'update',
+                        'find');
+        $ignoreStatic = array('staticGet',
+                              'pkeyGet',
+                              'cachedQuery');
+        $here = get_class($this); // if we get confused
+        $bt = debug_backtrace();
+
+        // Find the first caller that's not us?
+        foreach ($bt as $frame) {
+            $func = $frame['function'];
+            if (isset($frame['type']) && $frame['type'] == '::') {
+                if (in_array($func, $ignoreStatic)) {
+                    continue;
+                }
+                $here = $frame['class'] . '::' . $func;
+                break;
+            } else if (isset($frame['type']) && $frame['type'] == '->') {
+                if ($frame['object'] === $this && in_array($func, $ignore)) {
+                    continue;
+                }
+                if (in_array($func, $ignoreStatic)) {
+                    continue; // @fixme this shouldn't be needed?
+                }
+                $here = get_class($frame['object']) . '->' . $func;
+                break;
+            }
+            $here = $func;
+            break;
+        }
+
+        if (php_sapi_name() == 'cli') {
+            $context = basename($_SERVER['PHP_SELF']);
+        } else {
+            $context = $_SERVER['REQUEST_METHOD'];
+        }
+
+        // Slip the comment in after the first command,
+        // or DB_DataObject gets confused about handling inserts and such.
+        $parts = explode(' ', $string, 2);
+        $parts[0] .= " /* $context $here */";
+        return implode(' ', $parts);
+    }
+
     // Sanitize a query for logging
     // @fixme don't trim spaces in string literals
     function sanitizeQuery($string)
@@ -505,6 +573,9 @@ class Memcached_DataObject extends Safe_DataObject
         if ($this->id) {
             $id .= ':' . $this->id;
         }
+        if ($message instanceof PEAR_Error) {
+            $message = $message->getMessage();
+        }
         throw new ServerException("[$id] DB_DataObject error [$type]: $message");
     }