cybex/laravel-query-tracer

为你的模型查询添加堆栈跟踪。

1.0.1 2022-02-11 20:16 UTC

README

Laravel Query Tracer

Latest Version on Packagist Packagist Downloads Github build status GitHub pull-requests GitHub issues Laravel Version

Sample Query with Trace

查询的堆栈跟踪。

如果你曾经想知道日志中的特定查询是从哪里来的,或者想要轻松追踪导致慢查询的代码,这个包就是为你准备的。

Laravel Query Tracer 集成到你的 Eloquent 中,并添加它找到的最有用的堆栈帧信息,不仅添加了类、文件、行号、函数名和被调用的函数,还添加了相关的源代码部分。

安装

你可以通过 composer 安装此包

composer require cybex/laravel-query-tracer

用法

要激活查询跟踪器,只需将以下行添加到你的 .env 文件中

QUERY_TRACER_ENABLED=true

完成此操作后,所有模型查询都将包含一个包含有用信息的注释,以定位查询的来源。

评估查询的最简单方法是安装 Laravel TelescopeLaravel Debugbar 或任何其他将日志和查询显示出来的包。

配置

可以使用以下命令发布 query-tracer.php 配置文件

php artisan vendor:publish --provider="Cybex\QueryTracer\QueryTracerServiceProvider" --tag="config"

你可以自定义配置文件内注释中解释的各种选项。

此外,也可以使用环境设置来设置一些选项,你可以根据需要将这些设置放入你的 .env 文件中。

可用的选项及其对应的 env 设置和默认值如下

操作模式

Query Tracer 提供两种不同的操作模式,这两种模式在如何集成到框架中的方式上有所不同。如果你在 Laravel TelescopeLaravel Debugbar 中本地调试查询,你将想要使用 default 模式。如果你希望跟踪出现在数据库服务器上,例如慢查询日志或任何其他服务器日志中,你必须使用 scoped 模式。

默认模式

default 模式下,Query Tracer 覆盖了 Laravel 数据库连接类的日志记录方法。在这种模式下,SQL 注释会在你的 DB 服务器上执行查询后添加到查询中,因此不会出现在服务器上。此外,你可以通过 trace.logArray 启用将跟踪信息添加到每个 QueryLog 条目的功能

       "query" => "select * from `pages` where `pages`.`parent_id` in (1, 2, 3, 4, 5, 6)",
       "bindings" => [],
       "time" => 0.41,
       "trace" => [
         "call" => "App\Models\Page::get()",
         "class" => "Illuminate\Database\Eloquent\Builder",
         "file" => "/app/Base/Helpers/ApplicationHelper.php",
         "function" => "{closure}()",
         "line" => 132,
         "source" => """
             0129      function getMenu()\n
             0130      {\n
             0131          return cache()->remember('menu', 60, function () {\n
           * 0132              return \App\Models\Page::where('parent_id', null)->with('children')->get();\n
             0133          });\n
             0134      }\n
             0135  }
           """,
       ],

默认情况下,键名为 trace,但可以使用 trace.logArray.key 选项重命名。

作用域模式

scoped 模式下,Query Tracer 为你的每个模型附加一个全局作用域,该作用域将添加一个 where 1 到每个查询,并附加带有跟踪信息的 SQL 注释。因此,每个查询在执行前都会被修改,因此会出现在所有日志中。注意,在 scoped 模式下添加跟踪到 QueryLog 不会起作用,因为日志方法不会被覆盖。

可用的跟踪值

query-tracer.trace.logArray.valuesquery-tracer.trace.sqlComment.template 选项配置了将包含在 QueryLog 数组中和 SQL 注释中的值。这两个选项可用的值相同;唯一的区别是,你需要在 SQL 模板中使用它们之前在它们前面加上 @

以下值可用于使用

调用

触发查询的调用,包括其参数的摘要。

调用执行的对象的类。

编译

仅在调用位于编译后的 Blade 视图中时设置。它包含编译视图的文件路径,而 file 包含原始 Blade 模板的名称。

文件

包含调用的文件,包括相对于项目根目录的路径。

包含调用的行的编号。

源代码

包含调用的源代码部分。列出的代码量可以通过 query-tracer.trace.includeSourceLines 设置进行配置。

自定义格式化器

您可以通过替换配置中定义的类,用您自己的实现替换源代码、调用参数、QueryLog 数组和 SQL 注释的格式化器。

参数格式化器

参数格式化器将调用参数从堆栈帧转换为可打印的表示。使用的格式化器类在 query-tracer.backtrace.argumentFormatter 中配置。参数格式化器需要实现 Cybex\QueryTracer\Interfaces\ArgumentFormatterInterface

一个非常简单的自定义参数格式化器实现,仅打印参数类型可能如下所示

<?php

namespace App\Classes;

use Cybex\QueryTracer\Interfaces\ArgumentFormatterInterface;

class CustomArgumentFormatter implements ArgumentFormatterInterface
{

    /**
     * Formats a single argument according to its type.
     *
     * @param $argument
     * @return string
     */
    public function formatArgument($argument): string
    {
        return gettype($argument);
    }


    /**
     * Formats the individual arguments for display in the call string.
     *
     * @param array $arguments
     * @return string
     */
    public function formatStackFrameArguments(array $arguments): string
    {
        return implode(
            ', ',
            array_map(
                function ($argument) {
                    return $this->formatArgument($argument);
                },
                $arguments
            )
        );
    }
}

要激活您的实现,您需要在配置中将 'argumentFormatter' => App\Classes\CustomArgumentFormatter::class 设置。

源代码格式化器

源代码格式化器负责检索给定文件的源代码,并以可打印的形式返回它。格式化器类在 query-tracer.backtrace.sourceCodeFormatter 中配置。您自己的实现必须扩展 Cybex\QueryTracer\Classes\AbstractSourceCodeFormatter

日志数组格式化器

日志数组格式化器将原始跟踪数组转换为可以附加到数据库 QueryLog 的数组。该类可以在 query-tracer.trace.logArray.formatter 中配置。您自己的实现需要扩展 Cybex\QueryTracer\Classes\AbstractTraceFormatter,它本质上只提供了一个必须返回 arraynullformat() 方法。

SQL 注释格式化器

SQL 注释格式化器格式化来自原始跟踪数组的数据,并填充在 query-tracer.trace.sqlComment.template 中配置的模板。格式化器类在 query-tracer.trace.sqlComment.formatter 中定义。与日志数组格式化器一样,您的实现需要扩展 Cybex\QueryTracer\Classes\AbstractTraceFormatter,它本质上只提供了一个必须返回 stringnullformat() 方法。

测试

composer test

需求

  • PHP: 7.3, 7.4, 8.0, 8.1
  • Laravel: 7, 8, 9

变更日志

有关最近更改的更多信息,请参阅 变更日志

已知问题

  • 如果您的跟踪中有任何问号,例如在代码列表中,QueryExceptions 将用参数绑定替换它们,从而破坏异常消息(请参阅相关 问题)。这仅是 Laravel 中的显示问题,不会影响数据库服务器上的查询执行。为了减轻这种情况,问号被替换为 UTF-8 全角问号。
  • 如果查询的来源是模板,行号始终指针对编译视图。由于编译视图对调试没有帮助,因此原始视图文件会自动解析并引用。因此,显示的源代码位置仅对非常简单的模板准确。包含、blade 组件和指令的使用可能会将原始调用移动到不同的位置。因此,总是对视图位置的行为和源代码的行号持保留态度。

贡献

请参阅CONTRIBUTING以获取详细信息。

安全漏洞

请查看我们的安全策略以了解如何报告安全漏洞。

致谢

许可证

MIT许可证(MIT)。请参阅许可证文件以获取更多信息。