Laravel对接SLS日志服务

server/2024/11/27 3:28:02/

SLS_0">Laravel对接SLS日志服务(写入和读取)

1、下载阿里云的sdk

php">#通过composer下载
composer require  alibabacloud/aliyun-log-php-sdk#对应的git仓库 
https://github.com/aliyun/aliyun-log-php-sdk

2、创建sdk请求的service

php"><?phpnamespace App\Services;use Aliyun_Log_Client;
use Aliyun_Log_Models_LogItem;
use Aliyun_Log_Models_PutLogsRequest;
use Aliyun_Log_Models_GetLogsRequest;
use Aliyun_Log_Models_GetHistogramsRequest;
use Exception;
use Illuminate\Support\Facades\Log;class SLSTimeSeriesService
{protected $client;protected $project;protected $logstore;public function __construct(){// 从配置中获取凭证$endpoint = env('ALIYUN_SLS_ENDPOINT');$accessKeyId = env('ALIYUN_ACCESS_KEY_ID');$accessKeySecret = env('ALIYUN_ACCESS_KEY_SECRET');// 验证配置if (!$endpoint || !$accessKeyId || !$accessKeySecret) {throw new Exception('SLS configuration is missing');}// 初始化客户端$this->client = new Aliyun_Log_Client($endpoint, $accessKeyId, $accessKeySecret);$this->project = env('ALIYUN_SLS_PROJECT');$this->logstore = env('ALIYUN_SLS_LOGSTORE');}/*** 查询日志(带分页和排序)*/public function getLogs($query = '', $from = null, $to = null, $page = 1, $perPage = 10, $sort = 'desc', $sortField = '__time__'){try {$from = $from ?: time() - 3600;$to = $to ?: time();// 计算偏移量$offset = ($page - 1) * $perPage;// 获取总数$histogramRequest = new Aliyun_Log_Models_GetHistogramsRequest($this->project,$this->logstore,$from,$to,'',$query ?: '*');$histogramResponse = $this->client->getHistograms($histogramRequest);$total = $histogramResponse->getTotalCount();// 创建日志查询请求$request = new Aliyun_Log_Models_GetLogsRequest($this->project,$this->logstore,$from,$to,'',$query ?: '*',1000,  // 先获取较多数据以便排序0,true);// 执行查询$response = $this->client->getLogs($request);$logs = $response->getLogs();// 处理日志数据$formattedLogs = [];foreach ($logs as $log) {$contents = $log->getContents();$contents['log_time'] = date('Y-m-d H:i:s', $log->getTime());$formattedLogs[] = $contents;}// 自定义排序if ($sortField !== '__time__') {usort($formattedLogs, function($a, $b) use ($sortField, $sort) {// 确保字段存在$valueA = isset($a[$sortField]) ? $a[$sortField] : '';$valueB = isset($b[$sortField]) ? $b[$sortField] : '';// 如果是数字字符串,转换为数字比较if (is_numeric($valueA) && is_numeric($valueB)) {$valueA = (float)$valueA;$valueB = (float)$valueB;}// 根据排序方向比较if ($sort === 'asc') {return $valueA <=> $valueB;}return $valueB <=> $valueA;});}// 应用分页$formattedLogs = array_slice($formattedLogs, $offset, $perPage);// 返回结果return ['logs' => $formattedLogs,'pagination' => ['total' => $total,'per_page' => $perPage,'current_page' => $page,'last_page' => ceil($total / $perPage),'from' => $offset + 1,'to' => $offset + count($formattedLogs)]];} catch (Exception $e) {Log::error('SLS Get Error: ' . $e->getMessage());throw $e;}}/*** 写入日志*/public function putLogs($data){try {// 确保所有值都是字符串$contents = [];foreach ($data as $key => $value) {$contents[$key] = is_array($value) ? json_encode($value) : (string)$value;}// 创建日志内容$logItem = new Aliyun_Log_Models_LogItem();$logItem->setTime(time());$logItem->setContents($contents);// 创建请求$request = new Aliyun_Log_Models_PutLogsRequest($this->project,$this->logstore,'test_topic','',[$logItem]);// 发送日志$response = $this->client->putLogs($request);return true;} catch (Exception $e) {Log::error('SLS Put Error: ' . $e->getMessage());throw $e;}}/*** 查询所有日志(不分页)* @param string $query 查询条件* @param int|null $from 开始时间* @param int|null $to 结束时间* @return array* 循环,速度慢,不推荐使用*/public function getAllLogs($query = '', $from = null, $to = null, $sort = 'desc', $sortField = '__time__'){try {$from = $from ?: time() - 3600;$to = $to ?: time();// 构建查询语句$searchQuery = !empty($query) ? $query : '*';$allLogs = [];$offset = 0;$limit = 100;  // 每次获取100条do {// 创建日志查询请求$request = new Aliyun_Log_Models_GetLogsRequest($this->project,$this->logstore,$from,$to,'',             // topic$searchQuery,   // 查询语句$limit,         // 每次获取数量$offset,        // 当前偏移量$sort === 'desc' // 是否倒序);// 执行查询$response = $this->client->getLogs($request);$logs = $response->getLogs();$count = count($logs);// 处理本批次的日志数据foreach ($logs as $log) {$contents = $log->getContents();// 解析 value 字段if (isset($contents['__value__']) && is_string($contents['__value__'])) {try {$decodedValue = json_decode($contents['__value__'], true);if (json_last_error() === JSON_ERROR_NONE) {$contents['__value__'] = $decodedValue;}} catch (\Exception $e) {// 保持原值}}$contents['log_time'] = date('Y-m-d H:i:s', $log->getTime());$allLogs[] = $contents;}// 更新偏移量$offset += $count;// 如果返回的数据少于限制数,说明已经没有更多数据if ($count < $limit) {break;}} while (true);// 如果需要按其他字段排序if ($sortField !== '__time__') {usort($allLogs, function($a, $b) use ($sortField, $sort) {$valueA = isset($a[$sortField]) ? $a[$sortField] : '';$valueB = isset($b[$sortField]) ? $b[$sortField] : '';if (is_numeric($valueA) && is_numeric($valueB)) {$valueA = (float)$valueA;$valueB = (float)$valueB;}return $sort === 'asc' ?($valueA <=> $valueB) :($valueB <=> $valueA);});}return ['logs' => $allLogs,'total' => count($allLogs),'query_info' => ['query' => $searchQuery,'from' => date('Y-m-d H:i:s', $from),'to' => date('Y-m-d H:i:s', $to),'sort_field' => $sortField,'sort_order' => $sort,'total_batches' => ceil($offset / $limit)]];} catch (Exception $e) {
//            Log::error('SLS Get All Logs Error', [
//                'error' => $e->getMessage(),
//                'query' => $searchQuery ?? '',
//                'from' => date('Y-m-d H:i:s', $from),
//                'to' => date('Y-m-d H:i:s', $to),
//                'offset' => $offset ?? 0
//            ]);throw $e;}}/*** 查询所有日志(不分页)* @param $query* @param $from* @param $to* @param $userId* @param $sortOrder* @return array* sql limit的方式,有排序限制,速度快*/public function getAllLogsSql($query = '', $from = null, $to = null, $userId = null, $sortOrder = 'ASC'){try {$from = $from ?: time() - 3600; // 默认查询最近1小时$to = $to ?: time();// 获取总数,会消耗一定的时间,数量越大,消耗的时间越多,如果想节约时间,可以设置一个最大值类型10W之类的
//            $histogramRequest = new Aliyun_Log_Models_GetHistogramsRequest(
//                $this->project,
//                $this->logstore,
//                $from,
//                $to,
//                '',
//                $query ?: '*'
//            );
//
//            $histogramResponse = $this->client->getHistograms($histogramRequest);
//            $total = $histogramResponse->getTotalCount();
//            $maxResults = $total; // 一次性拉取的最大数量$maxResults = 100000; // 一次性拉取的最大数量// 构建基础查询语句$searchQuery = !empty($query) ? $query : '*';// 如果有 user_id 条件,添加筛选if ($userId) {
//                $searchQuery .= sprintf(" AND user_id='%s'", $userId);$searchQuery .= sprintf(" AND user_id=%d", (int)$userId);}//            Log::info('Starting Query', [
//                'query' => $searchQuery,
//                'from' => date('Y-m-d H:i:s', $from),
//                'to' => date('Y-m-d H:i:s', $to),
//                'sortOrder' => $sortOrder,
//            ]);// SQL 查询语句,按时间排序$sqlQuery = sprintf("%s | SELECT * ORDER BY __time__ %s LIMIT %d",$searchQuery,strtoupper($sortOrder), // ASC 或 DESC$maxResults);//            Log::info('Executing SQL Query', [
//                'query' => $sqlQuery,
//                'from' => date('Y-m-d H:i:s', $from),
//                'to' => date('Y-m-d H:i:s', $to),
//            ]);// 发送请求$request = new Aliyun_Log_Models_GetLogsRequest($this->project,$this->logstore,$from,$to,'',             // topic$sqlQuery,      // 查询语句0,              // batchSize 无用0,              // offset 无用false           // 不自动排序(已通过 SQL 排序));$response = $this->client->getLogs($request);$logs = $response->getLogs();$allLogs = [];// 处理返回的日志数据foreach ($logs as $log) {$contents = $log->getContents();// 解析 value 字段if (isset($contents['__value__']) && is_string($contents['__value__'])) {try {$decodedValue = json_decode($contents['__value__'], true);if (json_last_error() === JSON_ERROR_NONE) {$contents['__value__'] = $decodedValue;}} catch (\Exception $e) {// 保持原值}}$contents['log_time'] = date('Y-m-d H:i:s', $log->getTime());$allLogs[] = $contents;}//            Log::info('Query Completed', [
//                'fetched' => count($allLogs),
//                'total_expected' => $maxResults,
//            ]);return ['logs' => $allLogs,'total' => count($allLogs),'query_info' => ['query' => $searchQuery,'from' => date('Y-m-d H:i:s', $from),'to' => date('Y-m-d H:i:s', $to),'total_fetched' => count($allLogs),'sort_order' => $sortOrder,]];} catch (Exception $e) {
//            Log::error('SLS Query Error', [
//                'error' => $e->getMessage(),
//                'query' => $searchQuery ?? '',
//                'from' => date('Y-m-d H:i:s', $from),
//                'to' => date('Y-m-d H:i:s', $to),
//                'sort_order' => $sortOrder,
//            ]);throw $e;}}
}

3、创建config配置

php"># config/sls.config
<?php
return ['aliyun' => ['access_key_id' => env('ALIYUN_ACCESS_KEY_ID'),'access_key_secret' => env('ALIYUN_ACCESS_KEY_SECRET'),'sls' => ['endpoint' => env('ALIYUN_SLS_ENDPOINT'),'project' => env('ALIYUN_SLS_PROJECT'),'logstore' => env('ALIYUN_SLS_LOGSTORE'),],],
];

4、从阿里云获取对应的配置填写在env

php"># .env,同阿里云账号下的服务器是允许内网访问的
ALIYUN_SLS_ENDPOINT=cn-shenzhen.log.aliyuncs.com
#内网
#ALIYUN_SLS_ENDPOINT=cn-shenzhen-intranet.log.aliyuncs.com
ALIYUN_SLS_PROJECT=
ALIYUN_ACCESS_KEY_ID=
ALIYUN_ACCESS_KEY_SECRET=
ALIYUN_SLS_LOGSTORE=

5、创建控制器进行验证

php"><?phpnamespace App\Http\Controllers\Api;use App\Http\Controllers\Controller;
use App\Jobs\Sugar;
use App\Services\SLSTimeSeriesService;
use Exception;
use Illuminate\Http\Request;class MetricsController extends Controller
{protected $slsService;// 定义允许排序的字段// 定义允许排序的字段和默认排序方式protected $allowedSortFields = ['__time__',      // 日志时间'__tag__:__receive_time__', // 接收时间'timestamp',     // 自定义时间戳'user_id',     // 自定义时间戳];public function __construct(SLSTimeSeriesService $slsService){$this->slsService = $slsService;}/*** 写入日志*/public function store(Request $request){try {$data = ['event' => 'user_login','user_id' => (string)$request->input('user_id', '1'),'ip' => $request->ip(),'timestamp' => (string)time(),'request_data' => $request->all()];$this->slsService->putLogs($data);return response()->json(['success' => true,'message' => 'Log stored successfully']);} catch (Exception $e) {return response()->json(['success' => false,'message' => $e->getMessage()], 500);}}//分页查询public function index(Request $request){try {// 构建查询条件$conditions = [];if ($request->has('user_id')) {$conditions[] = 'user_id = "' . $request->user_id . '"';}if ($request->has('event')) {$conditions[] = 'event = "' . $request->event . '"';}// 获取排序参数$sortField = $request->input('sort_by', '__time__'); // 默认使用日志时间排序$sortOrder = $request->input('sort', 'desc');// 验证排序字段if (!in_array($sortField, $this->allowedSortFields)) {$sortField = '__time__';}// 验证排序方向$sortOrder = strtolower($sortOrder) === 'asc' ? 'asc' : 'desc';// 构建基本查询$query = !empty($conditions) ? implode(' and ', $conditions) : '*';// 获取分页参数$page = (int)$request->input('page', 1);$perPage = (int)$request->input('per_page', 10);// 时间范围$from = $request->input('from') ? strtotime($request->input('from')) : time() - 3600;$to = $request->input('to') ? strtotime($request->input('to')) : time();// 记录查询参数// 获取数据$result = $this->slsService->getLogs($query,$from,$to,$page,$perPage,$sortOrder,$sortField);return response()->json(['success' => true,'data' => $result['logs'],'pagination' => $result['pagination'],'query_info' => ['query' => $query,'conditions' => $conditions,'sort' => ['field' => $sortField,'order' => $sortOrder],'from' => date('Y-m-d H:i:s', $from),'to' => date('Y-m-d H:i:s', $to)]]);} catch (Exception $e) {return response()->json(['success' => false,'message' => $e->getMessage(),'query_info' => ['query' => $query ?? '*','conditions' => $conditions ?? []]], 500);}}/*** @param Request $request* @return array* @throws Exception* 循环查询,速度慢,排序无限制,不分页*/public function all(Request $request){// 时间范围$from = $request->input('from') ? strtotime($request->input('from')) : time() - 3600;$to = $request->input('to') ? strtotime($request->input('to')) : time();// 自定义排序$result = $this->slsService->getAllLogs('*',$from,$to,'desc','timestamp');return $result;}/*** @param Request $request* @return array* @throws Exception* sql查询,速度快,排序有限制,需要有索引才能查询出来,不分页*/public function allSql(Request $request){$user_id = $request->input('user_id') ?? '';// 时间范围$from = $request->input('from') ? strtotime($request->input('from')) : time() - 3600;$to = $request->input('to') ? strtotime($request->input('to')) : time();$result = $this->slsService->getAllLogsSql('*',$from,$to,$user_id,'desc');return $result;}
}

6、效果如下
在这里插入图片描述
在这里插入图片描述


http://www.ppmy.cn/server/145225.html

相关文章

安装 Docker(使用国内源)

一、安装Docker-ce 1、下载阿里云的repo源 [rootlocalhost ~]# yum install yum-utils -y && yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo && yum makecache # 尝试列出 docker-ce 的版本 [rootlocalh…

Python绘制太极八卦

文章目录 系列目录写在前面技术需求1. 图形绘制库的支持2. 图形绘制功能3. 参数化设计4. 绘制控制5. 数据处理6. 用户界面 完整代码代码分析1. rset() 函数2. offset() 函数3. taiji() 函数4. bagua() 函数5. 绘制过程6. 技术亮点 写在后面 系列目录 序号直达链接爱心系列1Pyth…

【测试工具JMeter篇】JMeter性能测试入门级教程(二)出炉,测试君请各位收藏了!!!

上篇文章&#xff1a;CSDN 我们介绍了JMeter的一些原理介绍&#xff0c;以及安装配置和启动流程&#xff0c;本文我们就来讲讲JMeter如何使用。 一、JMeter目录结构组成 1. 根目录 Jmeter安装包解压后的根目录如下图&#xff1a; 1.1 backups目录&#xff1a;脚本备份目录&am…

HTML5 视频 Vedio 标签详解

HTML5 引入了 <video> 标签&#xff0c;允许开发者在网页中直接嵌入视频文件&#xff0c;而不需要依赖第三方插件。本文将全面介绍 <video> 标签的各种属性&#xff0c;并通过实例代码详细说明其用法。 一、基础用法 1. 基本结构 HTML5 中使用 <video> 标…

sqlmap学习,打靶sqli-labs.(1-19)

前言&#xff1a;用于学习sqlmap的简单使用&#xff0c;使用sqli-labs靶场进行测试。 当然,在实战中,考虑的更多&#xff0c;例如如何隐藏自己(特征码),编码加解密、sqlmap抓包调试分析等... 不过那些都是后话&#xff0c;太遥远...基础NO.1&#xff01;&#xff01; 先贴上我…

PyQt的安装和再PyCharm中的配置

安装 pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple pip install pyqt5-tools -i https://pypi.tuna.tsinghua.edu.cn/simple配置 QtDesigner Name&#xff1a;自己取 Program&#xff1a;上面的路径 Working directory&#xff1a;$FileDir$PyUic Name&am…

如何定制谷歌浏览器的外观主题

在数字化时代&#xff0c;浏览器已成为我们日常生活中不可或缺的一部分。谷歌浏览器&#xff0c;以其快速、稳定和丰富的扩展程序而广受用户喜爱。但你知道吗&#xff1f;除了强大的功能外&#xff0c;谷歌浏览器还允许用户通过定制外观主题来打造更加个性化的浏览体验。本文将…

【ArcGISPro】使用AI提取要素-土地分类(sentinel2)

Sentinel2数据处理 【ArcGISPro】Sentinel-2数据处理-CSDN博客 土地覆盖类型分类 处理结果