protected function log(
        $query,
        $parameters,
        $startTimestamp,
        $exception = null
    ) {
        $endTimestamp = time();

        $duration = $endTimestamp - $startTimestamp;

        $user = \Phramework\Phramework::getUser();

        $user_id = ($user ? $user->id : null);

        //Get request URI
        list($URI) = \Phramework\URIStrategy\URITemplate::URI();

        //Get request method
        $method = \Phramework\Phramework::getMethod();

        $debugBacktrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);

        //Function used by database adapter
        $adapterFunction = $debugBacktrace[1]['function'];

        //Remove current log function call
        //Remove QueryLogAdapter execute* function call
        array_splice($debugBacktrace, 0, 2);

        foreach ($debugBacktrace as $k => &$v) {
            if (isset($v['class'])) {
                $class = $v['class'];
                $function = $v['function'];

                //Check if matrix has an entry for this class
                if (property_exists($this->matrix, $class)) {
                    $matrixEntry = $this->matrix->{$class};

                    if (is_object($matrixEntry) || is_array($matrixEntry)) {
                        //If vector, then is vector contains values for multiple methods of this class

                        //Work with objects
                        if (is_array($matrixEntry)) {
                            $matrixEntry = (object)$matrixEntry;
                        }

                        if (property_exists($matrixEntry, $function)) {
                            //If non positive value, dont log current query
                            if (!$matrixEntry->{$function}) {
                                return self::LOG_INGORED;
                            }
                        }
                    } else {
                        //scalar, this entry has a single value for all methods of this class

                        //If non positive value, dont log current query
                        if (!$matrixEntry) {
                            return self::LOG_INGORED;
                        }
                    }
                }

                $v = $v['class'] . '::' . $v['function'];
            } else {
                $v = $v['function'];
            }
        }

        $schemaTable = (
            $this->schema //if schema is set
            ? '"' . $this->schema . '"."' . $this->table . '"'
            : '"' . $this->table . '"'
        );

        //Insert query log record into table
        return $this->logAdapter->execute(
            'INSERT INTO ' . $schemaTable .
            '(
                "request_id",
                "query",
                "parameters",
                "start_timestamp",
                "duration",
                "function",
                "URI",
                "method",
                "additional_parameters",
                "call_trace",
                "user_id",
                "exception"
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
            [
                \Phramework\Phramework::getRequestUUID(),
                $query,
                (
                    $parameters
                    ? json_encode($parameters)
                    : null
                ),
                $startTimestamp,
                $duration,
                $adapterFunction,
                $URI,
                $method,
                (
                    $this->additionalParameters
                    ? json_encode($this->additionalParameters)
                    : null
                ),
                json_encode($debugBacktrace),
                $user_id,
                (
                    $exception
                    ? serialize(QueryLog::flattenExceptionBacktrace($exception))
                    : null
                )
            ]
        );
    }