如何将Newrelic中MySQL(subquery)select标签替换为自定义表名标签?
解决方法
1. 监听所有数据库查询
打开app/Providers/AppServiceProvider.php,在boot()方法里注册数据库查询监听器,捕获每一条执行的SQL:
use Illuminate\Support\Facades\DB; public function boot() { DB::listen(function ($query) { $this->setNewrelicSubqueryTag($query); }); }
2. 解析子查询提取表名
在同一个服务提供者里添加私有处理方法,判断当前SQL是否为子查询,提取对应表名后调用Newrelic API设置标签:
private function setNewrelicSubqueryTag($query) { $sql = $query->sql; // 匹配子查询中的表名,正则可根据实际SQL写法调整 if (preg_match('/FROM\s*\(SELECT.*?FROM\s+`?(\w+)`?/is', $sql, $matches)) { $tableName = $matches[1]; // 确认Newrelic扩展正常加载 if (function_exists('newrelic_add_custom_parameter')) { // 给当前请求添加自定义参数,Newrelic中可查看 newrelic_add_custom_parameter('subquery_table', $tableName); } // 若要直接修改Newrelic显示的查询名称,使用以下代码 if (function_exists('newrelic_name_transaction')) { $customName = "MySQL subquery_{$tableName} select"; newrelic_name_transaction($customName); } } }
3. 适配不同子查询结构
如果你的子查询是IN (SELECT ...)格式,将正则表达式替换为:
if (preg_match('/IN\s*\(SELECT.*?FROM\s+`?(\w+)`?/is', $sql, $matches)) { $tableName = $matches[1]; // 后续处理逻辑同上 }
4. 性能优化小技巧
若系统查询量较大,可只对慢查询做标记,避免正则解析带来的性能损耗:
// 仅处理执行时间超过100ms的查询 if ($query->time > 100) { // 这里放入解析和打标签的逻辑 }
5. 手动精准标记法
如果用Eloquent编写子查询,可给查询构造器添加自定义宏,手动指定表名,避免正则解析的不确定性:
在AppServiceProvider的boot()方法中添加:
use Illuminate\Database\Query\Builder; Builder::macro('tagSubqueryForNewrelic', function ($tableName) { if (function_exists('newrelic_add_custom_parameter')) { newrelic_add_custom_parameter('subquery_table', $tableName); } return $this; });
编写子查询时直接调用该宏:
// 标记子查询关联表名为users $userSubquery = User::select('id')->where('active', true)->tagSubqueryForNewrelic('users'); $orders = Order::whereIn('user_id', $userSubquery)->get();
内容的提问来源于stack exchange,提问作者Ashish Bhanderi
相关产品推荐
相关产品推荐

