Laravel怎么记录操作日志_Laravel用户行为日志追踪【介绍】
你的Lara vel操作日志,真的能追到人吗?先抛个问题:现在跑着的项目,如果业务方要求你查「上周三这个用户到底删了哪条订单记录」,你能在两分钟内精准定位吗?如果答案没那么笃定,多半是日志系统这块还有优化的空间。问题一:直接用 Log 类记日志?用户根本对不上人直接用 Log::info() 记录日
你的Lara vel操作日志,真的能追到人吗?
先抛个问题:现在跑着的项目,如果业务方要求你查「上周三这个用户到底删了哪条订单记录」,你能在两分钟内精准定位吗?如果答案没那么笃定,多半是日志系统这块还有优化的空间。

问题一:直接用 Log 类记日志?用户根本对不上人
直接用 Log::info() 记录日志,确实方便,但说句实话,这里头有个不小的坑——它只记下了日志内容和时间,关于上下文几乎一片空白:没有用户ID、没有请求详情,操作目标(比如到底改了哪条记录)更是无从谈起。真要追查问题,基本只能靠猜。
怎么解决?核心思路就一条:把所有日志的入口收拢到一个统一的服务类里来,比如 UserActivityLogger。
- 在构造日志的时候,强制带上用户ID:
auth()->id() - 抓取请求来源:
request()->ip()、request()->fullUrl() - 标明操作的业务目标:比如修改了某条
$post,就传$post->id - 至于敏感字段,比如密码、手机号这些,记得脱敏。直接报
'password' => '***'即可,干净又安全。
这样一来,「谁在什么时间、对什么资源、干了什么」这条链路才算真正打通。
问题二:DB::table('activity_logs') 手动插,性能拉胯,事务里还容易丢
用原生SQL插入日志,看似可控,但有个很隐蔽的陷阱:一旦包裹在数据库事务里,事务回滚,日志也跟着一块儿消失了。要是用户刚删了一条订单,日志却因为回滚没留下,审计直接断档,排查起来就费劲了。
实操建议:
- 如果必须用同步写,请在事务提交之后再执行日志插入:
DB::commit()之后再来写。或者更稳的做法是使用DB::unprepared()绕过当前事务。 - 但更推荐的方案是将日志落库异步化——把日志写入任务推到队列里去,无论是
database队列还是redis队列都行。主流程只管处理业务,日志让后台进程慢慢消化,丝毫不影响响应速度。 - 表结构的设计至少覆盖这些字段:
user_id、action(比如存个字符串'updated_post'就挺直观)、subject_type和subject_id指向操作对象、再加上ip、user_agent。
问题三:光靠监听 Eloquent 事件?大量操作根本收不到
很多人习惯监听 eloquent.updated 这类事件来抓模型变更,这确实能覆盖大部分CRUD操作。但真实场景下,有大量行为是不经过模型的:登录、登出、菜单点击、Excel文件导出、API token刷新……这些操作 Eloquent 事件完全收不到,日志记录就会出现大片盲区。
最佳实践是多元方案并行:
- 对核心动作手动触发日志:比如在
AuthController@login方法里,显式调用UserActivityLogger::log('logged_in')。 - 写一个全局或局部的中间件,比如
LogUserActivity,在handle()里判断请求方法(POST/PUT/DELETE)以及当前用户是否已登录,自动进行日志记录。 - 说到底,别把宝押在一个单一事件源上。事件监听 + 中间件拦截 + 显式手动调用,三者混搭,按场景选择最稳妥的方案。
问题四:查日志慢如牛?多半是没加索引
上线两周后,突然发现查某个用户的操作记录居然要等8秒,EXPLAIN 一跑,全表扫描——这就是忘了给 user_id 和 created_at 加联合索引的后果。
解决方法很简单,但从一开始就得想好:
- 建表迁移里,务必加上
$table->index(['user_id', 'created_at'])。如果业务里经常按操作类型查(比如查「最近登出过多少次」),再加个index(['action', 'created_at'])。 - 当单表数据量超过100万行,就该考虑分表了。按月份分(比如
activity_logs_202404),再用视图或查询路由来聚合,性能会明显改善。 - 另外,不要在日志查询里
JOIN users表来拿用户名。写日志的时候顺手存一个user_name快照字段进去,查询时直接取,省掉一次关联,速度自然就上去了。
但别忘了,最容易被忽略的其实是「日志写入的时机」。同步写入磁盘最稳,但慢;异步写入快,可要是进程突然崩溃,最后几条日志可能就丢了。这个取舍没有银弹,完全取决于业务容忍度:金融类操作必须同步落盘,后台管理类操作则可以接受秒级延迟。


































