Rest接口/Nginx日志记录和采集

文章目录

  • 一、Rest接口日志
  • 二、Nginx日志
  • 三、采集日志
  • 四、夜莺查看Nginx日志
  • 五、夜莺查看Rest接口日志


一、Rest接口日志

  • 记录日志字典定义
接口URL接口名称,类别,入参全记录,出参全记录,入参字段1:中文名1/入参字段2:中文名2,出参字段1:中文名1
/test/api/login账户登录,登录,false,false,accountName:账户名,accessToken:Token/expiresTime:有效期/person.name:姓名
/test/api/role/findById查询角色,应用,true,true,role.roleId:角色ID,role.roleName:角色名
  • RestLogAspect.java
package cn.test.manage.config.aspect;import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;/*** @description Rest接口日志记录*/
@Aspect
@Component
public class RestLogAspect {private static Log logger = LogFactory.getLog(RestLogAspect.class);@Resourceprivate RedisTemplate redisTemplate;@Value("${server.servlet.application-display-name}")private String system;private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'+08:00'");private static DecimalFormat df = new DecimalFormat ("#.##");@Pointcut("execution(public * cn.test.manage.web.rest.*.*.*(..))")private void pointcut() {}@Around(value = "pointcut()")public Object log(ProceedingJoinPoint joinPoint) throws Throwable {Date date = new Date();Object result = joinPoint.proceed();try {// 第一个参数固定为请求参数,第二个参数固定为HttpServletRequestHttpServletRequest request = (HttpServletRequest) joinPoint.getArgs()[1];// 从字典获取需要记录日志的接口Object dict = redisTemplate.opsForHash().get("DICT_", system + "_logs" + "." + request.getRequestURI());if (dict == null || StringUtils.isEmpty(dict.toString())) {return result;}JSONObject json = new JSONObject();json.put("logtype", "customize");                           // 固定标识, 用于日志采集json.put("client", request.getRemoteAddr());                // 客户端IPjson.put("host", request.getRemoteHost());                  // 服务端IPjson.put("port", request.getServerPort());                  // 服务端端口json.put("starttime", sdft.format(date));                   // 接口开始时间json.put("url", request.getRequestURI());                   // 接口URLjson.put("system", system);                                 // 系统名称setArgInfo(json, joinPoint.getArgs()[0], result, dict.toString());// 获取tokenString token = request.getParameter("token");if (StringUtils.isEmpty(token) || "null".equals(token)) {token = request.getHeader("Authorization");if (token != null && token.startsWith("Bearer ")) {token = token.substring(7);}}json.put("token", token);                                   // tokenString accountId = (String) redisTemplate.opsForValue().get("token-" + token);if (accountId != null) {Map<String, String> map = (Map<String, String>) redisTemplate.opsForValue().get(accountId);if (map != null) {json.put("accountid", map.get("accountId"));        // 账户IDjson.put("accountname", map.get("accountName"));    // 账户名json.put("username", map.get("name"));              // 用户名}}// 接口代码执行时间,会小于响应时间json.put("resptime", df.format((double)(new Date().getTime()-date.getTime())/1000));logger.info("\n"+JSONObject.toJSONString(json));} catch (Exception e) {logger.error(e);}return result;}/*** 设置参数信息*/private void setArgInfo(JSONObject json, Object request, Object response, String argstr) {String requeststr = JSONObject.toJSONString(request);String responsestr = JSONObject.toJSONString(response);JSONObject requestObject = JSONObject.parseObject(requeststr);JSONObject responseObject = JSONObject.parseObject(responsestr);String[] args = argstr.split(",");json.put("apidesc", args[0]);                               // 接口描述json.put("apitype", args[1]);                               // 接口类型if (responseObject.getString("operateSuccess") == null || "false".equals(responseObject.getString("operateSuccess"))) {json.put("level", "ERROR");                             // 日志级别} else {json.put("level", "INFO");}json.put("msg", responseObject.getString("operateSuccess") + " " + responseObject.getString("msg"));if ("true".equals(args[2])) {json.put("request", requeststr);                        // 请求完整内容}if ("true".equals(args[3])) {json.put("response", responsestr);                      // 响应完整内容}json.put("req", getInfo(json, requestObject, args[4]));     // 请求概要内容json.put("resp", getInfo(json, responseObject, args[5]));   // 响应概要内容}/*** 获取参数概要信息,集合只取第一个元素*/private String getInfo(JSONObject json, JSONObject object, String argstr) {String str = "";for (String obj : argstr.split("/")) {Object jsonObject = object;String fields = obj.split(":")[0];String desc = obj.split(":")[1];for (String field : fields.split("\\.")) {if (jsonObject instanceof JSONObject) {jsonObject = ((JSONObject) jsonObject).get(field);} else if (jsonObject instanceof JSONArray)  {while (jsonObject instanceof JSONArray) {jsonObject = ((JSONArray) jsonObject).get(0);}jsonObject = ((JSONObject) jsonObject).get(field);} else {logger.info(jsonObject);break;}}str += desc + ": " + jsonObject + ", ";}str = str.endsWith(", ") ? str.substring(0,str.length()-2) : str;return str;}
}

二、Nginx日志

  • nginx.conf 中日志配置
		# 日志配置open_log_file_cache max=1000 inactive=20s valid=1m min_uses=3;#  客户端地址 时间 协议 响应状态 响应字节数 响应时间 客户端log_format main '{"logtype":"customize",'				# 固定标识, 用于日志采集'"starttime":"$time_iso8601",'					# 日志写入时间'"url":"$uri",'									# 请求的URL'"protocol":"$server_protocol",'					# 请求使用的协议'"upgrade":"$http_upgrade",'						# 是否升级 WebSocket'"status":"$status",'							# 响应状态'"host": "$http_host",'							# 服务端地址(客户端请求的)'"client": "$remote_addr",'						# 客户端地址'"reqsize": $request_length,'					# 请求内容大小(byte)'"respsize": $bytes_sent,'						# 响应内容大小 byte)'"resptime": $request_time,'						# 响应时间(s)'"connnum": $connection_requests,' 				# 当前通过一个连接获得的请求数量'"agent": "$http_user_agent"}';					# 用户终端代理access_log /var/log/nginx/access.log main buffer=32k flush=5s;error_log /var/log/nginx/error.log warn;

三、采集日志

  • filebeat.yml
filebeat.inputs:
- type: filestreampaths:- /home/nginx/logs/access.logtags: ["nginx-access"]processors:- decode_json_fields:fields: ["message"]target: "nginx"max_depth: 1- type: filestreampaths:- /home/nginx/logs/error.logtags: ["nginx-error"]- type: filestreampaths:- /home/docker/logs/*tags: ["crontab-log"]- type: filestreampaths:- /home/logs/test/all.logtags: ["test"]processors:- decode_json_fields:fields: ["message"]target: "test"max_depth: 1output.elasticsearch:hosts: ["192.168.1.12:9200"]preset: balancedprotocol: "http"username: "elastic"password: "123456"indices:- index: filebeat-6.13-nginx-%{+yyyy.MM}when.contains: {tags: nginx, nginx.logtype: customize}- index: filebeat-6.13-ser-%{+yyyy.MM}when.contains: {tags: test, test.logtype: customize}- index: filebeat-6.13-%{+yyyy.MM}setup.template.settings:index.number_of_shards: 1index.codec: best_compressionprocessors:- drop_fields:fields: ["log","host","input","agent","ecs"]
  • filebeat服务重启
sudo systemctl restart filebeat
sudo systemctl status filebeat

四、夜莺查看Nginx日志

  • 日志分析 > 索引模式 > 创建索引模式

在这里插入图片描述

  • 日志分析 > 索引模式 > 编辑 字段别名

在这里插入图片描述

  • 日志分析 > 即时查询

在这里插入图片描述

五、夜莺查看Rest接口日志

  • 日志分析 > 索引模式 > 创建索引模式

在这里插入图片描述- 日志分析 > 索引模式 > 编辑 字段别名

在这里插入图片描述

  • 日志分析 > 即时查询

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/1402.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis 逻辑过期策略设计思路

引言&#xff1a; 当我们平常使用Redis缓存的时候&#xff0c;会出现一种场景&#xff0c; redis的key到过期时间了&#xff0c;总是需要到数据库里面去查一遍数据再set回redis&#xff0c;这个时候如果数据库响应比较慢&#xff0c;那么就会造成用户等待&#xff0c;如果刚好…

09 JavaScript学习:对象

对象的概念 在计算机科学中&#xff0c;对象是一种数据结构&#xff0c;用于存储数据和方法&#xff08;也称为函数&#xff09;。对象可以包含属性&#xff08;也称为成员变量&#xff09;和方法&#xff08;也称为成员函数&#xff09;&#xff0c;通过这些属性和方法可以描述…

【微信小程序】解决分页this.setData数据量太大的限制问题

1、原始方法&#xff0c;每请求一页都拿到之前的数据concat一下后整体再setData loadData() {let that thislet data {}data.page this.data.pagedata.size this.data.sizefindAll(data).then(res > {if (res.data.code 1) {this.setData({dataList: this.data.dataLi…

android开发 多进程的基本了解

目录 如何开启多进程?理解多进程模式的运行机制 如何开启多进程? 给四大组件在androidMenifest中指定android:precess <activityandroid:name".ThreeActivity"android:exported"false"android:process"com.my.process.three.remote" />…

如何查询下载自然资源相关的法律法规

自然资源部门户网站- 政策法规库 (https://f.mnr.gov.cn/) 以查询下载“节约用水条例”为例&#xff1a;输入标题&#xff0c;点击检索&#xff0c;出现对应的检索结果&#xff1a; 打开详细&#xff0c;可以看到节约用水条例的详细内容&#xff1a; 点击文后的打印或者下载&a…

如何使用PHPStudy+Cloudreve搭建个人云盘并实现无公网IP远程访问——“cpolar内网穿透”

文章目录 1、前言2、本地网站搭建2.1 环境使用2.2 支持组件选择2.3 网页安装2.4 测试和使用2.5 问题解决 3、本地网页发布3.1 cpolar云端设置3.2 cpolar本地设置 4、公网访问测试5、结语 1、前言 自云存储概念兴起已经有段时间了&#xff0c;各互联网大厂也纷纷加入战局&#…

python爬虫开发能力需要哪些

Python爬虫开发能力需要以下几个方面的知识和技能&#xff1a; Python基础&#xff1a;你需要熟悉Python的语法和编程基础&#xff0c;包括变量、数据类型、控制结构、函数、模块等。此外&#xff0c;了解Python面向对象编程的概念和实践也是很有帮助的。网络编程&#xff1a;…

day48_servlet

今日内容 周一 0 复习上周 1 本周计划 2 MVC和三层架构 3 Login案例 4 请求转发 5 重定向 0 复习昨日 1 jdbc五大步骤 注册驱动(反射)获得连接获得执行sql对象执行SQL关流 2 什么是SQL注入 通过SQL关键词,在执行SQL时出现不正常的情况 3 PreparedStatement怎么使用,有什么特点 …

刷题之Leetcode19题(超级详细)

19.删除链表的倒数第N个节点 力扣题目链接(opens new window)https://leetcode.cn/problems/remove-nth-node-from-end-of-list/ 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 进阶&#xff1a;你能尝试使用一趟扫描实现吗&#x…

react09 hooks(useState)

react-09 hooks&#xff08;useState&#xff09; hooks组件&#xff08;函数组件动态化&#xff09; 其本质就是函数组件&#xff0c;引用一些hooks方法&#xff0c;用来在函数组件中进行例如状态管理&#xff0c;模拟类组件的生命周期等&#xff0c;只能运用到函数组件中 ho…

代码随想录算法训练营第三十二天|122.买卖股票的最佳时机II,55. 跳跃游戏,45.跳跃游戏II

目录 122.买卖股票的最佳时机II思路代码 55. 跳跃游戏思路代码 45.跳跃游戏II思路代码 122.买卖股票的最佳时机II 题目链接&#xff1a;122.买卖股票的最佳时机II 文档讲解&#xff1a;代码随想录 视频讲解&#xff1a;贪心算法也能解决股票问题&#xff01;LeetCode&#xff1…

项目管理-项目成本管理

目录 一、成本管理概述 二、成本估算 2.1 定义 2.2 成本估算方法 2.2.1 自顶向下的估算 2.2.1.1 估算方法 2.2.1.2 优点 2.2.1.3 缺点 2.2.2 自底向上的估算 2.2.2.1 估算方法 2.2.2.2 优点 2.2.2.3 缺点 2.2.3 差别估算法 三、成本预算 3.1 定义 3.2 成本预算的…

使用 optimum 使得 embedding 生成速度提高 5 倍(和原生 sentence transformer 模型对比)

今天偶然刷到了 Accelerate Sentence Transformers with Hugging Face Optimum (philschmid.de) 看到可以是用 optimum 调用 onnx API 加速 embedding 模型在 CPU 上的推理速度&#xff0c;而且相比之前&#xff1a; 使用 onnx 使得 embedding 生成速度提高 4 倍&#xff08…

ccfcsp201312-2 ISBN号码

注意&#xff1a;50分 -- u10&#xff0c;最后一位为X 代码&#xff1a; #include <bits/stdc.h> using namespace std; string s; int a[12]; int main() {cin >> s;a[1] s[0] - 0;a[2] s[2] - 0;a[3] s[3] - 0;a[4] s[4] - 0;a[5] s[6] - 0;a[6] s[7] - …

C++ STL 概述

目录 什么是 STLSTL 的组成迭代器常用容器算法函数对象 什么是 STL STL ( The C Standard Template Library )&#xff0c;C标准模板库&#xff0c;是一个算法、数据结构和其他组件的集合&#xff0c;可用于简化C程序的开发。STL提供了一系列的 容器 (container)&#xff0c;如…

深入理解安卓ARouter:集成与应用

摘要 在Android开发中&#xff0c;页面间的导航和参数传递是一个重要的组成部分。ARouter&#xff08;Android Router&#xff09;是一个轻量级、模块化的路由框架&#xff0c;旨在简化页面间的跳转和参数传递。本文将详细介绍安卓ARouter的概述、集成步骤、优劣分析及应用场景…

Jupyter Notebook更改默认打开的浏览器和工作目录

Jupyter Notebook更改工作目录 打开cmd&#xff0c;输入&#xff1a;jupyter notebook --generate-config&#xff0c;可以得到Jupyter Notebook配置文件的路径&#xff0c;找到路径下的jupyter_notebook_config.py文件&#xff0c;用记事本或者Sublime打开文件 找到&#xff…

统一SQL-支持unpivot列转行

统一SQL介绍 https://www.light-pg.com/docs/LTSQL/current/index.html 源和目标 源数据库&#xff1a;Oracle 目标数据库&#xff1a;TDSQL-MySQL 操作目标 在Oracle中&#xff0c;可以使用unpivot将列转换成行&#xff0c;在TDSQL-MySQL中没有对应的功能&#xff0c;由…

HDMI to TYPE-C芯片|HDMI2.0转TYPE-C转接器方案|CS5802设计方案|ASL CS5802

CS5802输入端可以是1080P、4K30、4K60HZ这三种规格,输出的接口可以是TYPE-C信号接口,或者是TYPE-C信号接口,输入端HDMI由4路信号组成&#xff0c;支持1.62Gbps、2.7Gbps、5.4Gbps链路速率。内置可选SSC功能可降低EMI的干扰状况。 ASL CS5802芯片概述&#xff1a; 符合HDMI规范…

定时任务 作业调度框架

单体 Cron: 特点&#xff1a;Linux和类Unix系统中的一个内置工具。功能&#xff1a;通过crontab文件配置&#xff0c;可以定期执行脚本或命令。 Spring Scheduler: 特点&#xff1a;Spring框架的一部分。功能&#xff1a;允许在Spring应用程序中创建定时任务&#xff0c;支持注…