mirror of
https://github.com/lkddi/Xboard.git
synced 2026-04-28 06:47:24 +08:00
refactor: replace database logging with file logging and admin audit log
This commit is contained in:
@@ -1,53 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Console\Commands;
|
|
||||||
|
|
||||||
use Illuminate\Console\Command;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
|
|
||||||
class ExportV2Log extends Command
|
|
||||||
{
|
|
||||||
protected $signature = 'log:export {days=1 : The number of days to export logs for}';
|
|
||||||
protected $description = 'Export v2_log table records of the specified number of days to a file';
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
parent::__construct();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function handle()
|
|
||||||
{
|
|
||||||
$days = $this->argument('days');
|
|
||||||
$date = Carbon::now()->subDays((float) $days)->startOfDay();
|
|
||||||
|
|
||||||
$logs = DB::table('v2_log')
|
|
||||||
->where('created_at', '>=', $date->timestamp)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
$fileName = "v2_logs_" . Carbon::now()->format('Y_m_d_His') . ".csv";
|
|
||||||
$handle = fopen(storage_path("logs/$fileName"), 'w');
|
|
||||||
|
|
||||||
// 根据您的表结构
|
|
||||||
fputcsv($handle, ['Level', 'ID', 'Title', 'Host', 'URI', 'Method', 'Data', 'IP', 'Context', 'Created At', 'Updated At']);
|
|
||||||
|
|
||||||
foreach ($logs as $log) {
|
|
||||||
fputcsv($handle, [
|
|
||||||
$log->level,
|
|
||||||
$log->id,
|
|
||||||
$log->title,
|
|
||||||
$log->host,
|
|
||||||
$log->uri,
|
|
||||||
$log->method,
|
|
||||||
$log->data,
|
|
||||||
$log->ip,
|
|
||||||
$log->context,
|
|
||||||
Carbon::createFromTimestamp($log->created_at)->toDateTimeString(),
|
|
||||||
Carbon::createFromTimestamp($log->updated_at)->toDateTimeString()
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose($handle);
|
|
||||||
$this->info("日志成功导出到: " . storage_path("logs/$fileName"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use App\Models\Log;
|
use App\Models\AdminAuditLog;
|
||||||
use App\Models\StatServer;
|
use App\Models\StatServer;
|
||||||
use App\Models\StatUser;
|
use App\Models\StatUser;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
@@ -43,6 +43,6 @@ class ResetLog extends Command
|
|||||||
{
|
{
|
||||||
StatUser::where('record_at', '<', strtotime('-2 month', time()))->delete();
|
StatUser::where('record_at', '<', strtotime('-2 month', time()))->delete();
|
||||||
StatServer::where('record_at', '<', strtotime('-2 month', time()))->delete();
|
StatServer::where('record_at', '<', strtotime('-2 month', time()))->delete();
|
||||||
Log::where('created_at', '<', strtotime('-1 month', time()))->delete();
|
AdminAuditLog::where('created_at', '<', strtotime('-3 month', time()))->delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
namespace App\Http\Controllers\V2\Admin;
|
namespace App\Http\Controllers\V2\Admin;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Log as LogModel;
|
use App\Models\AdminAuditLog;
|
||||||
use App\Utils\CacheKey;
|
use App\Utils\CacheKey;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
@@ -23,37 +23,10 @@ class SystemController extends Controller
|
|||||||
'schedule' => $this->getScheduleStatus(),
|
'schedule' => $this->getScheduleStatus(),
|
||||||
'horizon' => $this->getHorizonStatus(),
|
'horizon' => $this->getHorizonStatus(),
|
||||||
'schedule_last_runtime' => Cache::get(CacheKey::get('SCHEDULE_LAST_CHECK_AT', null)),
|
'schedule_last_runtime' => Cache::get(CacheKey::get('SCHEDULE_LAST_CHECK_AT', null)),
|
||||||
'logs' => $this->getLogStatistics()
|
|
||||||
];
|
];
|
||||||
return $this->success($data);
|
return $this->success($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取日志统计信息
|
|
||||||
*
|
|
||||||
* @return array 各级别日志的数量统计
|
|
||||||
*/
|
|
||||||
protected function getLogStatistics(): array
|
|
||||||
{
|
|
||||||
// 初始化日志统计数组
|
|
||||||
$statistics = [
|
|
||||||
'info' => 0,
|
|
||||||
'warning' => 0,
|
|
||||||
'error' => 0,
|
|
||||||
'total' => 0
|
|
||||||
];
|
|
||||||
|
|
||||||
if (class_exists(LogModel::class) && LogModel::count() > 0) {
|
|
||||||
$statistics['info'] = LogModel::where('level', 'INFO')->count();
|
|
||||||
$statistics['warning'] = LogModel::where('level', 'WARNING')->count();
|
|
||||||
$statistics['error'] = LogModel::where('level', 'ERROR')->count();
|
|
||||||
$statistics['total'] = LogModel::count();
|
|
||||||
|
|
||||||
return $statistics;
|
|
||||||
}
|
|
||||||
return $statistics;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getQueueWorkload(WorkloadRepository $workload)
|
public function getQueueWorkload(WorkloadRepository $workload)
|
||||||
{
|
{
|
||||||
return $this->success(collect($workload->get())->sortBy('name')->values()->toArray());
|
return $this->success(collect($workload->get())->sortBy('name')->values()->toArray());
|
||||||
@@ -125,34 +98,26 @@ class SystemController extends Controller
|
|||||||
})->count();
|
})->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSystemLog(Request $request)
|
public function getAuditLog(Request $request)
|
||||||
{
|
{
|
||||||
$current = $request->input('current') ? $request->input('current') : 1;
|
$current = max(1, (int) $request->input('current', 1));
|
||||||
$pageSize = $request->input('page_size') >= 10 ? $request->input('page_size') : 10;
|
$pageSize = max(10, (int) $request->input('page_size', 10));
|
||||||
$level = $request->input('level');
|
|
||||||
$keyword = $request->input('keyword');
|
|
||||||
|
|
||||||
$builder = LogModel::orderBy('created_at', 'DESC')
|
$builder = AdminAuditLog::with('admin:id,email')
|
||||||
->when($level, function ($query) use ($level) {
|
->orderBy('id', 'DESC')
|
||||||
return $query->where('level', strtoupper($level));
|
->when($request->input('action'), fn($q, $v) => $q->where('action', $v))
|
||||||
})
|
->when($request->input('admin_id'), fn($q, $v) => $q->where('admin_id', $v))
|
||||||
->when($keyword, function ($query) use ($keyword) {
|
->when($request->input('keyword'), function ($q, $keyword) {
|
||||||
return $query->where(function ($q) use ($keyword) {
|
$q->where(function ($q) use ($keyword) {
|
||||||
$q->where('data', 'like', '%' . $keyword . '%')
|
$q->where('uri', 'like', '%' . $keyword . '%')
|
||||||
->orWhere('context', 'like', '%' . $keyword . '%')
|
->orWhere('request_data', 'like', '%' . $keyword . '%');
|
||||||
->orWhere('title', 'like', '%' . $keyword . '%')
|
|
||||||
->orWhere('uri', 'like', '%' . $keyword . '%');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$total = $builder->count();
|
$total = $builder->count();
|
||||||
$res = $builder->forPage($current, $pageSize)
|
$res = $builder->forPage($current, $pageSize)->get();
|
||||||
->get();
|
|
||||||
|
|
||||||
return response([
|
return response(['data' => $res, 'total' => $total]);
|
||||||
'data' => $res,
|
|
||||||
'total' => $total
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getHorizonFailedJobs(Request $request, JobRepository $jobRepository)
|
public function getHorizonFailedJobs(Request $request, JobRepository $jobRepository)
|
||||||
@@ -176,125 +141,4 @@ class SystemController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 清除系统日志
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
*/
|
|
||||||
public function clearSystemLog(Request $request)
|
|
||||||
{
|
|
||||||
$request->validate([
|
|
||||||
'days' => 'integer|min:0|max:365',
|
|
||||||
'level' => 'string|in:info,warning,error,all',
|
|
||||||
'limit' => 'integer|min:100|max:10000'
|
|
||||||
], [
|
|
||||||
'days.required' => '请指定要清除多少天前的日志',
|
|
||||||
'days.integer' => '天数必须为整数',
|
|
||||||
'days.min' => '天数不能少于1天',
|
|
||||||
'days.max' => '天数不能超过365天',
|
|
||||||
'level.in' => '日志级别只能是:info、warning、error、all',
|
|
||||||
'limit.min' => '单次清除数量不能少于100条',
|
|
||||||
'limit.max' => '单次清除数量不能超过10000条'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$days = $request->input('days', 30); // 默认清除30天前的日志
|
|
||||||
$level = $request->input('level', 'all'); // 默认清除所有级别
|
|
||||||
$limit = $request->input('limit', 1000); // 默认单次清除1000条
|
|
||||||
|
|
||||||
try {
|
|
||||||
$cutoffDate = now()->subDays($days);
|
|
||||||
|
|
||||||
// 构建查询条件
|
|
||||||
$query = LogModel::where('created_at', '<', $cutoffDate->timestamp);
|
|
||||||
|
|
||||||
if ($level !== 'all') {
|
|
||||||
$query->where('level', strtoupper($level));
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取要删除的记录数量
|
|
||||||
$totalCount = $query->count();
|
|
||||||
|
|
||||||
if ($totalCount === 0) {
|
|
||||||
return $this->success([
|
|
||||||
'message' => '没有找到符合条件的日志记录',
|
|
||||||
'deleted_count' => 0,
|
|
||||||
'total_count' => $totalCount
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 分批删除,避免单次删除过多数据
|
|
||||||
$deletedCount = 0;
|
|
||||||
$batchSize = min($limit, 1000); // 每批最多1000条
|
|
||||||
|
|
||||||
while ($deletedCount < $limit && $deletedCount < $totalCount) {
|
|
||||||
$remainingLimit = min($batchSize, $limit - $deletedCount);
|
|
||||||
|
|
||||||
$batchQuery = LogModel::where('created_at', '<', $cutoffDate->timestamp);
|
|
||||||
if ($level !== 'all') {
|
|
||||||
$batchQuery->where('level', strtoupper($level));
|
|
||||||
}
|
|
||||||
|
|
||||||
$idsToDelete = $batchQuery->limit($remainingLimit)->pluck('id');
|
|
||||||
|
|
||||||
if ($idsToDelete->isEmpty()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$batchDeleted = LogModel::whereIn('id', $idsToDelete)->delete();
|
|
||||||
$deletedCount += $batchDeleted;
|
|
||||||
|
|
||||||
// 避免长时间占用数据库连接
|
|
||||||
if ($deletedCount < $limit && $deletedCount < $totalCount) {
|
|
||||||
usleep(100000); // 暂停0.1秒
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->success([
|
|
||||||
'message' => '日志清除完成',
|
|
||||||
'deleted_count' => $deletedCount,
|
|
||||||
'total_count' => $totalCount,
|
|
||||||
'remaining_count' => max(0, $totalCount - $deletedCount)
|
|
||||||
]);
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return $this->fail(ResponseEnum::HTTP_ERROR, null, '清除日志失败:' . $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取日志清除统计信息
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
* @return \Illuminate\Http\JsonResponse
|
|
||||||
*/
|
|
||||||
public function getLogClearStats(Request $request)
|
|
||||||
{
|
|
||||||
$days = $request->input('days', 30);
|
|
||||||
$level = $request->input('level', 'all');
|
|
||||||
|
|
||||||
try {
|
|
||||||
$cutoffDate = now()->subDays($days);
|
|
||||||
|
|
||||||
$query = LogModel::where('created_at', '<', $cutoffDate->timestamp);
|
|
||||||
if ($level !== 'all') {
|
|
||||||
$query->where('level', strtoupper($level));
|
|
||||||
}
|
|
||||||
|
|
||||||
$stats = [
|
|
||||||
'days' => $days,
|
|
||||||
'level' => $level,
|
|
||||||
'cutoff_date' => $cutoffDate->format(format: 'Y-m-d H:i:s'),
|
|
||||||
'total_logs' => LogModel::count(),
|
|
||||||
'logs_to_clear' => $query->count(),
|
|
||||||
'oldest_log' => LogModel::orderBy('created_at', 'asc')->first(),
|
|
||||||
'newest_log' => LogModel::orderBy('created_at', 'desc')->first(),
|
|
||||||
];
|
|
||||||
|
|
||||||
return $this->success($stats);
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return $this->fail(ResponseEnum::HTTP_ERROR, null, '获取统计信息失败:' . $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,23 +2,59 @@
|
|||||||
|
|
||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use App\Models\AdminAuditLog;
|
||||||
use Closure;
|
use Closure;
|
||||||
|
|
||||||
class RequestLog
|
class RequestLog
|
||||||
{
|
{
|
||||||
/**
|
private const SENSITIVE_KEYS = ['password', 'token', 'secret', 'key', 'api_key'];
|
||||||
* Handle an incoming request.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Http\Request $request
|
|
||||||
* @param \Closure $next
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function handle($request, Closure $next)
|
public function handle($request, Closure $next)
|
||||||
{
|
{
|
||||||
if ($request->method() === 'POST') {
|
if ($request->method() !== 'POST') {
|
||||||
$path = $request->path();
|
return $next($request);
|
||||||
info("POST {$path}");
|
}
|
||||||
};
|
|
||||||
return $next($request);
|
$response = $next($request);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$admin = $request->user();
|
||||||
|
if (!$admin || !$admin->is_admin) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$action = $this->resolveAction($request->path());
|
||||||
|
$data = collect($request->all())->except(self::SENSITIVE_KEYS)->toArray();
|
||||||
|
|
||||||
|
AdminAuditLog::insert([
|
||||||
|
'admin_id' => $admin->id,
|
||||||
|
'action' => $action,
|
||||||
|
'method' => $request->method(),
|
||||||
|
'uri' => $request->getRequestUri(),
|
||||||
|
'request_data' => json_encode($data, JSON_UNESCAPED_UNICODE),
|
||||||
|
'ip' => $request->getClientIp(),
|
||||||
|
'created_at' => time(),
|
||||||
|
'updated_at' => time(),
|
||||||
|
]);
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
\Log::warning('Audit log write failed: ' . $e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveAction(string $path): string
|
||||||
|
{
|
||||||
|
// api/v2/{secure_path}/user/update → user.update
|
||||||
|
$path = preg_replace('#^api/v[12]/[^/]+/#', '', $path);
|
||||||
|
// gift-card/create-template → gift_card.create_template
|
||||||
|
$path = str_replace('-', '_', $path);
|
||||||
|
// user/update → user.update, server/manage/sort → server_manage.sort
|
||||||
|
$segments = explode('/', $path);
|
||||||
|
$method = array_pop($segments);
|
||||||
|
$resource = implode('_', $segments);
|
||||||
|
|
||||||
|
return $resource . '.' . $method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -218,10 +218,8 @@ class AdminRoute
|
|||||||
$router->get('/getQueueStats', [SystemController::class, 'getQueueStats']);
|
$router->get('/getQueueStats', [SystemController::class, 'getQueueStats']);
|
||||||
$router->get('/getQueueWorkload', [SystemController::class, 'getQueueWorkload']);
|
$router->get('/getQueueWorkload', [SystemController::class, 'getQueueWorkload']);
|
||||||
$router->get('/getQueueMasters', '\\Laravel\\Horizon\\Http\\Controllers\\MasterSupervisorController@index');
|
$router->get('/getQueueMasters', '\\Laravel\\Horizon\\Http\\Controllers\\MasterSupervisorController@index');
|
||||||
$router->get('/getSystemLog', [SystemController::class, 'getSystemLog']);
|
|
||||||
$router->get('/getHorizonFailedJobs', [SystemController::class, 'getHorizonFailedJobs']);
|
$router->get('/getHorizonFailedJobs', [SystemController::class, 'getHorizonFailedJobs']);
|
||||||
$router->post('/clearSystemLog', [SystemController::class, 'clearSystemLog']);
|
$router->any('/getAuditLog', [SystemController::class, 'getAuditLog']);
|
||||||
$router->get('/getLogClearStats', [SystemController::class, 'getLogClearStats']);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update
|
// Update
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace App\Logging;
|
|
||||||
|
|
||||||
class MysqlLogger
|
|
||||||
{
|
|
||||||
public function __invoke(array $config){
|
|
||||||
return tap(new \Monolog\Logger('mysql'), function ($logger) {
|
|
||||||
$logger->pushHandler(new MysqlLoggerHandler());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace App\Logging;
|
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Monolog\Handler\AbstractProcessingHandler;
|
|
||||||
use Monolog\Logger;
|
|
||||||
use App\Models\Log as LogModel;
|
|
||||||
use Monolog\LogRecord;
|
|
||||||
|
|
||||||
class MysqlLoggerHandler extends AbstractProcessingHandler
|
|
||||||
{
|
|
||||||
public function __construct($level = Logger::DEBUG, bool $bubble = true)
|
|
||||||
{
|
|
||||||
parent::__construct($level, $bubble);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function write(LogRecord $record): void
|
|
||||||
{
|
|
||||||
$record = $record->toArray();
|
|
||||||
try {
|
|
||||||
if (isset($record['context']['exception']) && is_object($record['context']['exception'])) {
|
|
||||||
$record['context']['exception'] = (array)$record['context']['exception'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$record['request_data'] = request()->all();
|
|
||||||
|
|
||||||
$log = [
|
|
||||||
'title' => $record['message'],
|
|
||||||
'level' => $record['level_name'],
|
|
||||||
'host' => $record['extra']['request_host'] ?? request()->getSchemeAndHttpHost(),
|
|
||||||
'uri' => $record['extra']['request_uri'] ?? request()->getRequestUri(),
|
|
||||||
'method' => $record['extra']['request_method'] ?? request()->getMethod(),
|
|
||||||
'ip' => request()->getClientIp(),
|
|
||||||
'data' => json_encode($record['request_data']),
|
|
||||||
'context' => json_encode($record['context']),
|
|
||||||
'created_at' => $record['datetime']->getTimestamp(),
|
|
||||||
'updated_at' => $record['datetime']->getTimestamp(),
|
|
||||||
];
|
|
||||||
|
|
||||||
LogModel::insert($log);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
// Log::channel('daily')->error($e->getMessage().$e->getFile().$e->getTraceAsString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class AdminAuditLog extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'v2_admin_audit_log';
|
||||||
|
protected $dateFormat = 'U';
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'timestamp',
|
||||||
|
'updated_at' => 'timestamp',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function admin()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'admin_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Log extends Model
|
|
||||||
{
|
|
||||||
use \App\Scope\FilterScope;
|
|
||||||
protected $table = 'v2_log';
|
|
||||||
protected $dateFormat = 'U';
|
|
||||||
protected $guarded = ['id'];
|
|
||||||
protected $casts = [
|
|
||||||
'created_at' => 'timestamp',
|
|
||||||
'updated_at' => 'timestamp'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
+6
-54
@@ -5,40 +5,9 @@ use Monolog\Handler\SyslogUdpHandler;
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
|
|
||||||
/*
|
'default' => env('LOG_CHANNEL', 'daily'),
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Default Log Channel
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This option defines the default log channel that gets used when writing
|
|
||||||
| messages to the logs. The name specified in this option should match
|
|
||||||
| one of the channels defined in the "channels" configuration array.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'default' => 'mysql',
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Log Channels
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| Here you may configure the log channels for your application. Out of
|
|
||||||
| the box, Laravel uses the Monolog PHP logging library. This gives
|
|
||||||
| you a variety of powerful log handlers / formatters to utilize.
|
|
||||||
|
|
|
||||||
| Available Drivers: "single", "daily", "slack", "syslog",
|
|
||||||
| "errorlog", "monolog",
|
|
||||||
| "custom", "stack"
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'channels' => [
|
'channels' => [
|
||||||
'mysql' => [
|
|
||||||
'driver' => 'custom',
|
|
||||||
'via' => App\Logging\MysqlLogger::class,
|
|
||||||
],
|
|
||||||
|
|
||||||
'stack' => [
|
'stack' => [
|
||||||
'driver' => 'stack',
|
'driver' => 'stack',
|
||||||
'channels' => ['daily'],
|
'channels' => ['daily'],
|
||||||
@@ -54,36 +23,19 @@ return [
|
|||||||
'single' => [
|
'single' => [
|
||||||
'driver' => 'single',
|
'driver' => 'single',
|
||||||
'path' => storage_path('logs/laravel.log'),
|
'path' => storage_path('logs/laravel.log'),
|
||||||
'level' => 'debug',
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
],
|
],
|
||||||
|
|
||||||
'daily' => [
|
'daily' => [
|
||||||
'driver' => 'daily',
|
'driver' => 'daily',
|
||||||
'path' => storage_path('logs/laravel.log'),
|
'path' => storage_path('logs/laravel.log'),
|
||||||
'level' => 'debug',
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
'days' => 14,
|
'days' => 14,
|
||||||
],
|
],
|
||||||
|
|
||||||
'slack' => [
|
|
||||||
'driver' => 'slack',
|
|
||||||
'url' => env('LOG_SLACK_WEBHOOK_URL'),
|
|
||||||
'username' => 'Laravel Log',
|
|
||||||
'emoji' => ':boom:',
|
|
||||||
'level' => 'critical',
|
|
||||||
],
|
|
||||||
|
|
||||||
'papertrail' => [
|
|
||||||
'driver' => 'monolog',
|
|
||||||
'level' => 'debug',
|
|
||||||
'handler' => SyslogUdpHandler::class,
|
|
||||||
'handler_with' => [
|
|
||||||
'host' => env('PAPERTRAIL_URL'),
|
|
||||||
'port' => env('PAPERTRAIL_PORT'),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
|
|
||||||
'stderr' => [
|
'stderr' => [
|
||||||
'driver' => 'monolog',
|
'driver' => 'monolog',
|
||||||
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
'handler' => StreamHandler::class,
|
'handler' => StreamHandler::class,
|
||||||
'formatter' => env('LOG_STDERR_FORMATTER'),
|
'formatter' => env('LOG_STDERR_FORMATTER'),
|
||||||
'with' => [
|
'with' => [
|
||||||
@@ -93,12 +45,12 @@ return [
|
|||||||
|
|
||||||
'syslog' => [
|
'syslog' => [
|
||||||
'driver' => 'syslog',
|
'driver' => 'syslog',
|
||||||
'level' => 'debug',
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
],
|
],
|
||||||
|
|
||||||
'errorlog' => [
|
'errorlog' => [
|
||||||
'driver' => 'errorlog',
|
'driver' => 'errorlog',
|
||||||
'level' => 'debug',
|
'level' => env('LOG_LEVEL', 'debug'),
|
||||||
],
|
],
|
||||||
|
|
||||||
'deprecations' => [
|
'deprecations' => [
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('v2_admin_audit_log', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->unsignedBigInteger('admin_id')->index();
|
||||||
|
$table->string('action', 64)->index()->comment('Action identifier e.g. user.update');
|
||||||
|
$table->string('method', 10);
|
||||||
|
$table->string('uri', 512);
|
||||||
|
$table->text('request_data')->nullable();
|
||||||
|
$table->string('ip', 128)->nullable();
|
||||||
|
$table->unsignedInteger('created_at');
|
||||||
|
$table->unsignedInteger('updated_at');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('v2_admin_audit_log');
|
||||||
|
}
|
||||||
|
};
|
||||||
+1
-1
Submodule public/assets/admin updated: 01bd0b3749...86a5f20d8a
Reference in New Issue
Block a user