在ThinkPHP生产环境中配置日志时,需要重点关注稳定性、性能和安全。以下是最佳实践配置方案:
生产环境推荐配置 (config/log.php
)
return [
'default' => env('log.channel', 'stack'),
'channels' => [
// 组合通道(核心配置)
'stack' => [
'type' => 'stack',
'channels' => ['daily', 'error_file', 'emergency'],
],
// 按日分割的常规日志
'daily' => [
'type' => 'file',
'path' => runtime_path('logs/daily'),
'level' => ['info', 'notice', 'warning'],
'max_files' => 30, // 保留30天
'file_size' => 10485760, // 10MB分割文件
'json' => false,
'format' => '[%s][%s] %s %s', // 简化格式
],
// 错误日志单独通道
'error_file' => [
'type' => 'file',
'path' => runtime_path('logs/error'),
'level' => ['error', 'critical'],
'max_files' => 90, // 保留90天
'apart_level' => true, // 每个级别单独文件
'file_size' => 20971520, // 20MB分割
'json' => true, // JSON格式便于分析
],
// 紧急事件单独处理
'emergency' => [
'type' => 'file',
'path' => runtime_path('logs/emergency'),
'level' => ['emergency'],
'max_files' => 365, // 保留1年
],
// 数据库日志(审计需要)
'audit' => [
'type' => 'database',
'table' => 'system_logs',
'connection' => 'log_db',
'level' => ['info', 'notice'],
'ignore_fields' => ['password', 'token'], // 忽略敏感字段
],
// 外部日志服务
'cloud' => [
'type' => 'custom',
'driver' => \app\log\driver\CloudLogger::class, // 自定义驱动
'level' => ['error', 'emergency'],
'endpoint' => 'https://log.example.com/api',
]
]
];
关键配置说明
1. 日志分级存储策略
'stack' => [
'type' => 'stack',
'channels' => ['daily', 'error_file', 'emergency'],
]
- 优势:不同级别日志分离存储
- 日志分布:
- 常规日志:30天轮转
- 错误日志:90天保留
- 紧急日志:1年保留
2. 性能优化配置
'daily' => [
'file_size' => 10485760, // 10MB分割文件
'max_files' => 30, // 最多保留30个文件
],
- 避免大文件:超过10MB自动分割
- 自动清理:仅保留最近30天日志
3. 安全增强措施
'database' => [
'ignore_fields' => ['password', 'token'], // 过滤敏感数据
],
在自定义格式化类中添加过滤:
class SafeLogFormatter {
protected function format($msg, $type, $context) {
// 过滤敏感信息
$context = array_filter($context, function($key) {
return !in_array($key, ['password', 'credit_card']);
}, ARRAY_FILTER_USE_KEY);
return json_encode(['msg'=>$msg, 'ctx'=>$context]);
}
}
4. 高可用方案
'cloud' => [
'type' => 'custom',
'driver' => \app\log\driver\CloudLogger::class,
]
自定义云日志驱动示例:
class CloudLogger {
public function save(array $log) {
try {
// 主服务写入
$this->sendToElasticSearch($log);
} catch (\Exception $e) {
// 失败时写入本地备份
Log::channel('local_fallback')->error($log);
}
}
}
5. 日志文件权限控制
在入口文件(public/index.php
)添加:
// 设置日志目录权限 (640)
umask(0027);
.env 环境变量配置
# 日志默认通道
LOG_CHANNEL=stack
# 错误通知阈值
LOG_ERROR_THRESHOLD=50
# 云日志配置
LOG_CLOUD_ENDPOINT=https://logs.prod.example.com
LOG_CLOUD_KEY=your_api_key_here
生产环境最佳实践
-
日志监控报警:
// 在全局异常处理中 report(function (\Throwable $e) { Log::channel('error_file')->error($e->getMessage()); // 每小时错误超过阈值报警 if (Log::getErrorCount() > env('LOG_ERROR_THRESHOLD', 50)) { Alert::sendToOpsTeam(); } });
-
日志压缩归档:
# 每日凌晨压缩旧日志 0 2 * * * find /path/to/runtime/logs -name "*.log" -mtime +30 -exec gzip {} \;
-
访问控制(Nginx):
location ~ ^/runtime/logs/ { deny all; return 403; }
-
性能关键位置禁用日志:
// 高并发接口中 public function paymentNotify() { // 临时关闭日志 Log::close(); // 业务逻辑... // 恢复日志 Log::init(); }
灾难恢复方案
-
双写策略:
'channels' => [ 'local_and_cloud' => [ 'type' => 'stack', 'channels' => ['daily', 'cloud'], ] ]
-
日志完整性校验:
class LogVerifier { public static function verifyIntegrity($logFile) { $hash = md5_file($logFile); file_put_contents($logFile.'.md5', $hash); } }
-
关键操作审计跟踪:
Log::channel('audit')->info('用户权限变更', [ 'operator' => Auth::id(), 'target_user' => $userId, 'changes' => $permissionChanges, 'ip' => request()->ip() ]);
验证配置是否生效
创建校验路由:
Route::get('log-check', function() {
// 测试各级别日志
Log::debug('Debug test - should not appear in prod');
Log::info('Info message');
Log::error('Error test');
Log::emergency('Emergency test!');
// 检查日志目录结构
$tree = shell_exec('tree '.runtime_path('logs'));
return '<pre>Log test completed. Directory structure:\n'.$tree;
})->middleware('auth:admin');
生产环境日志配置的核心原则:
- 分级存储:不同级别日志分离处理
- 生命周期管理:自动轮转和清理
- 安全防护:敏感数据过滤和访问控制
- 灾难恢复:本地+云端的双保险方案
- 性能优化:避免日志成为系统瓶颈
遵循这些原则可确保在生产环境中既保留足够的排查线索,又不会影响系统性能和安全性。