.NetCore6.0实现ActionFilter过滤器记录接口请求日志

文章目录

  • 目的
  • 实现案例:
    • 一.首先我们新建一个WebApi项目
    • 二.配置 appsettings.json 文件,配置日志存放路径
    • 三.创建 Model 文件夹,创建AppConfig类和ErrorLog类
      • 1.在AppConfig类中编写一个GetConfigInfo方法获取配置文件中的值
      • 2.在ErrorLog类中,实现往日志文件中书写接口日志的操作
    • 四.创建Filter文件夹,创建ActionFilter实现行动过滤器,实现记录接口日志
    • 五.在 Program 中配置行动过滤器 ActionFilter
    • 六.创建一个接口,调试执行一下
  • 结果

目的

使用ActionFilter记录接口请求日志

实现案例:

一.首先我们新建一个WebApi项目

在这里插入图片描述

在这里插入图片描述
开发环境,我们去掉HTTPS配置
在这里插入图片描述

二.配置 appsettings.json 文件,配置日志存放路径

在这里插入图片描述

{"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"AppConfig": {"DirectoryPath": "项目本地日志存放路径"},"AllowedHosts": "*"
}

三.创建 Model 文件夹,创建AppConfig类和ErrorLog类

在这里插入图片描述

1.在AppConfig类中编写一个GetConfigInfo方法获取配置文件中的值

/// <summary>
/// 获取.NetCore配置文件信息
/// </summary>
public class AppConfig
{public static string GetConfigInfo(string Key){var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("appsettings.json");IConfigurationRoot configuration = builder.Build();string configStr = configuration.GetSection($"{Key}").Value;if (!string.IsNullOrWhiteSpace(configStr)){return configStr;}return null;}}

2.在ErrorLog类中,实现往日志文件中书写接口日志的操作

public class ErrorLog
{//获取日志文件路径private static string DirectoryPath = AppConfig.GetConfigInfo("AppConfig:DirectoryPath");/// <summary>/// 写入操作日志到文件中/// </summary>/// <param name="moduleName">模块名字</param>/// <param name="message">错误文本信息</param>/// <param name="ex">异常</param>public static void Write(string message, Exception ex){string directoryPath = $@"{DirectoryPath}{DateTime.Now.ToString("yyyyMMdd")}"; // 目标目录路径if (!Directory.Exists(directoryPath)){// 如果目录不存在,则新建文件夹Directory.CreateDirectory(directoryPath);}string filePath = directoryPath + $@"\{DateTime.Now.ToString("yyyyMMddHH")}.log"; // 目标文件路径if (!File.Exists(filePath)){// 如果文件不存在,则创建文件using (File.Create(filePath)){//Console.WriteLine("文件已创建");}}LogToFile(filePath, message);}/// <summary>/// 写入操作日志到文件中/// </summary>/// <param name="moduleName">模块名字</param>/// <param name="ex">异常</param>public static void Write(string moduleName, Exception ex){Write(moduleName, moduleName, ex);}/// <summary>/// 写入过程数据或说明到文件中,以便跟踪/// </summary>/// <param name="moduleName">模块名字</param>/// <param name="ex">异常</param>public static void Write(string message){Write(String.Empty, message, null);}/// <summary>/// 文本写入/// </summary>/// <param name="logMessage"></param>private static void LogToFile(string logFilePath, string logMessage){using (StreamWriter sw = File.AppendText(logFilePath)){sw.WriteLine($"{logMessage}");}}
}

四.创建Filter文件夹,创建ActionFilter实现行动过滤器,实现记录接口日志

在这里插入图片描述

这里我们引入Newtonsoft.Json包
在这里插入图片描述

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using Newtonsoft.Json;
using System.Diagnostics;
using System.Text.Json;
using Microsoft.Extensions.Primitives;
using WebApiTest.Model;
using System.Net.Http.Json;namespace WebApiTest.Filter
{/// <summary>/// 方法过滤器/// </summary>public class ActionFilter : IActionFilter{/// <summary>/// 监控日志/// </summary>public static ILogger LoggerMonitor { get; set; }/// <summary>/// 错误日志/// </summary>public static ILogger LoggerError { get; set; }private Stopwatch _stopwatch;/// <summary>/// 创建请求日志文本/// </summary>/// <param name="method"></param>/// <param name="controllerName"></param>/// <param name="actionName"></param>/// <param name="actionArgs"></param>/// <returns></returns>private static string CreateRequestLogText(string method, string controllerName, string actionName, string requestHead, string requestBody){StringBuilder sb = new StringBuilder();sb.Append($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")} 请求{method}/{controllerName}/{actionName}接口,请求Head:{requestHead}\n");sb.Append($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")} 请求{method}/{controllerName}/{actionName}接口,请求Body:{requestBody}\n");return sb.ToString();}	/// <summary>/// 创建响应日志文本/// </summary>/// <param name="method"></param>/// <param name="controllerName"></param>/// <param name="actionName"></param>/// <param name="result"></param>/// <returns></returns>private static string CreateResponseLogText(string method, string controllerName, string actionName, object result){StringBuilder sb = new StringBuilder();sb.Append($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")} 完成请求{method}/{controllerName}/{actionName}接口,返回结果:");if (result != null){sb.Append($"{JsonConvert.SerializeObject(result)}");}else{sb.Append($"无");}return sb.ToString();}/// <summary>/// 方法执行前,记录接口请求参数/// </summary>/// <param name="context"></param>/// <exception cref="NotImplementedException"></exception>public async void OnActionExecuting(ActionExecutingContext context){ErrorLog.Write("==================================================================================================================================");_stopwatch = new Stopwatch();_stopwatch.Start();//throw new NotImplementedException();if (LoggerMonitor != null){//记录请求参数日志ControllerActionDescriptor desc = context.ActionDescriptor as ControllerActionDescriptor;if (desc != null){Dictionary<string, object> headers = new Dictionary<string, object>();var requestHeaders = context.HttpContext.Request.Headers;// 访问请求中的 header 信息foreach (var header in requestHeaders){headers.Add(header.Key, header.Value);}var requestHead = JsonConvert.SerializeObject(headers);Dictionary<string, object> bodys = new Dictionary<string, object>();var actionArguments = context.ActionArguments;// 访问请求中的参数foreach (var argument in actionArguments){//dic.Add(argument.Key, argument.Value);var parameter = JsonConvert.DeserializeObject<Dictionary<string, object>>(argument.Value.ToString());foreach (var item in parameter){bodys.Add(item.Key, item.Value);}}var requestBody = JsonConvert.SerializeObject(bodys);var logText = CreateRequestLogText(context.HttpContext.Request.Method, desc.ControllerName, desc.ActionName, requestHead, requestBody);LoggerMonitor.LogDebug(logText);ErrorLog.Write(logText);}}}//方法执行后,记录接口请求结果public void OnActionExecuted(ActionExecutedContext context){//throw new NotImplementedException();_stopwatch.Stop();long elaspsedMillisedconds = _stopwatch.ElapsedMilliseconds;string msg = $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")} 接口执行时间:{elaspsedMillisedconds}毫秒";//ErrorLog.Write(msg);if (context.Exception != null){// 记录异常日志if (LoggerError != null){LoggerError.LogError(context.Exception, context.Exception.Message);ErrorLog.Write($@"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")} 接口异常:{JsonConvert.SerializeObject(context.Exception)}");ErrorLog.Write($@"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")} 异常提示信息:{JsonConvert.SerializeObject(context.Exception.Message)}");}}if (LoggerMonitor != null){// 记录请求结果日志ControllerActionDescriptor desc = context.ActionDescriptor as ControllerActionDescriptor;if (desc != null){ObjectResult rst = context.Result as ObjectResult;object rstValue = rst != null ? rst.Value : null;var logText = CreateResponseLogText(context.HttpContext.Request.Method,desc.ControllerName,desc.ActionName,rstValue);LoggerMonitor.LogDebug(logText);ErrorLog.Write(logText);}}ErrorLog.Write(msg);ErrorLog.Write("==================================================================================================================================");}}
}

五.在 Program 中配置行动过滤器 ActionFilter

在这里插入图片描述

using Microsoft.AspNetCore.Mvc.Filters;
using WebApiTest.Filter;var builder = WebApplication.CreateBuilder(args);var configuration = builder.Configuration;
// Add services to the container.builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();#region 接口行动过滤器
// Add services to the container.
builder.Services.AddSingleton<IActionFilter>(new ActionFilter()); // 初始化 LoggerMonitor
builder.Services.AddSingleton<IActionFilter>(new ActionFilter()); // 初始化 LoggerError
builder.Services.AddScoped<ActionFilter>(); // 注册 ActionFilterbuilder.Services.AddControllers(options => {options.Filters.Add(new ActionFilter());
});var serviceProvider = builder.Services.BuildServiceProvider();
ActionFilter.LoggerError = serviceProvider.GetRequiredService<ILogger<ActionFilter>>();
ActionFilter.LoggerMonitor = serviceProvider.GetRequiredService<ILogger<ActionFilter>>();
#endregionvar app = builder.Build();// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{app.UseSwagger();app.UseSwaggerUI();
}app.UseAuthorization();app.MapControllers();app.Run();

六.创建一个接口,调试执行一下

在这里插入图片描述

using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;namespace WebApiTest.Controllers
{[ApiController][Route("Home")]public class HomeController : ControllerBase{[HttpGet][Route("Index")]public string Index(){return JsonConvert.SerializeObject(new { code = 0,data=true,msg="成功"});}}
}

在这里插入图片描述

接口请求成功,接着我们查看appsettings.json中配置的路径文件中,日志的记录情况

在这里插入图片描述

结果

.NetCore6.0项目,ActionFilter行动过滤器搭建成功,之后这个框架的接口请求就都会携带日志了

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

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

相关文章

供应josef约瑟DL-24C电流继电器 额定电流3A 整定范围0.5-2A 电气控制必备元件

电流继电器是一种特殊的电子控制器件&#xff0c;具有控制系统和被控制系统&#xff0c;它使用较小的电流去控制较大的电流&#xff0c;起到自动开关的作用。以下是电流继电器的特征&#xff1a; 承载大电流&#xff1a;电流继电器可以承载大电流&#xff0c;通常能够承受数十…

SpringBoot集成Docker

Docker是一个开源的应用容器引擎&#xff0c;它允许开发者将应用及其依赖打包到一个可移植的容器中。 一、依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://ww…

大语言模型(LLM):每个专业人士的完美助手

「大语言模型&#xff08;LLM&#xff09;革命」&#xff1a;ChatGPT如何引领工作效率新篇章 在不断发展的技术领域&#xff0c;像 ChatGPT 这样的大型语言模型 (LLM) 已成为各行业专业人士不可或缺的工具。 这篇博文探讨了大语言模型&#xff08;LLM&#xff09;在专业环境中的…

GDPU Java 天码行空2

实验2 类与封装性 文章目录 实验2 类与封装性&#xff08;一&#xff09;实验目的&#xff08;二&#xff09;实验内容和步骤&#xff08;1&#xff09;建立学生类和测试类。学生类中有成员变量&#xff1a;姓名&#xff0c;年龄&#xff1b;成员方法&#xff1a;学习&#xff…

程序逻辑控制

1.java的三大结构 可以说java的这三大结构包括其中的语句跟c语言上的基本上都是一样的。现在就当重新复习一遍吧&#xff01; 1.顺序结构 2.分支结构 if语句 跟c语言的语法一模一样。就直接看文案了。 switch语句 java中的switch语句跟c语言中的switch几乎相同&#xff0c;…

AtCoder Beginner Contest 343 A~F

A.Wrong Answer&#xff08;模拟&#xff09; 题意&#xff1a; 给你两个整数 A A A和 B B B&#xff0c;它们介于 0 0 0和 9 9 9之间。 输出任何一个介于 0 0 0和 9 9 9之间且不等于 A B AB AB的整数。 分析&#xff1a; 按题意判断并输出一个整数即可。 代码&#xff…

qnx display

05-SA8155 QNX Display框架及代码分析(1)_openwfd-CSDN博客 backlight p: 0 t: 0 00000 SHD -----ONLINE----- 2024/03/06 13:49:22.046 backlight p:1060958 t: 1 00000 ERR backlight_be[backlight_be.c:284]: pthread_create enter 2024/03/06 13…

python基础练习题目

1. 根据身高体重&#xff0c;判断人的胖瘦 描述&#xff1a; 通过身高和体重&#xff0c;判断一个人的胖瘦。国际上一般采用BMI体重指数&#xff0c;计算公式为BMI 体重 / 身高2(保留小数点后1位)&#xff0c;参考标准如下&#xff1a;‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪…

SpringBoot集成RocketMQ

RocketMQ是一个纯Java、分布式、队列模型的开源消息中间件&#xff0c;前身是MetaQ&#xff0c;是阿里参考Kafka特点研发的一个队列模型的消息中间件&#xff0c;后开源给apache基金会成为了apache的顶级开源项目&#xff0c;具有高性能、高可靠、高实时、分布式特点。 环境搭…

对VisionPro的认识,CogPMAlingTool模板匹配工具练习

什么是VisionPro&#xff1f; 在认识VisionPro之前我们需要先熟悉一下图片的各种格式 这里我们可以参考来自githubcurry博主的文章 图片各种格式的区别以及计算机如何存储图片 VisionPro 是由世界领先的机器视觉公司 Cognex 开发的一款专业机器视觉软件。它提供了强大的图像…

【一】【SQL Server】如何运用SQL Server中查询设计器通关数据库期末查询大题

职工考勤20170320 职工考勤20170320数据库展示 职工考勤表展示 职务代码表展示 一、基本操作 代码方式&#xff1a; --第一大题、基本操作 ALTER TABLE [dbo].[职工考勤表] DROP COLUMN [照片];EXEC sp_rename dbo.职工考勤表.职工编号, 工号, COLUMN;ALTER TABLE 职工考勤表 A…

华为HQoS配置案例

HQoS基于层次化调度&#xff0c;cpe上支持三级队列&#xff1a; level3流队列&#xff1a;每个用户的同类业务是一个业务流&#xff0c;针对每个用户不同的业务流进行队列调度&#xff0c;流队列一般与业务类型对应&#xff08;EF、AF、BE等&#xff09;。 level2用户队列&…

2024年安卓开发者跳槽指南,音视频时代你还不会NDK开发

正式加入字节跳动&#xff0c;分享一点面试小经验 今天正式入职了字节跳动。工号超吉利&#xff0c;尾数是3个6。然后办公环境也很好&#xff0c;这边一栋楼都是办公区域。公司内部配备各种小零食、饮料&#xff0c;还有免费的咖啡。15楼还有健身房。而且公司包三餐来着。下午…

【YOLO v5 v7 v8 v9小目标改进】新CNN架构 InceptionNeXt:怎么让大卷积核既好用又快

新CNN架构 InceptionNeXt&#xff1a;怎么让大卷积核既好用又快 提出背景问题: 如何提高大核心卷积的效率&#xff0c;同时保持或提升模型性能&#xff1f; 改进思路MetaNeXtInception深度卷积InceptionNeXt 小目标涨点YOLO v5 魔改YOLO v7 魔改YOLO v8 魔改YOLO v9 魔改 提出背…

RUUFFY、由利、希亦内衣洗衣机怎么样?测评对比谁更好?

我们传统的洗衣机其实并不可以用来清洗内衣裤&#xff0c;以及袜子这类小型的衣物&#xff0c;容易出现细菌的交叉感染&#xff0c;而且传统洗衣机单单清洗这些小件衣物并不划算&#xff0c;需要很多的水量&#xff0c;有些全自动的大型洗衣机需要更多的衣物同时清洗才能正常工…

110. 平衡二叉树【简单】

110. 平衡二叉树【简单】 题目描述&#xff1a; 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点的左右两个子树的高度差的绝对值不超过 1 。 示例 1&#xff1a; 输入&#xff1a;r…

IDEA修改git提交者的信息

git提交后&#xff0c;idea会记录下提交人的信息&#xff0c;如果不修改提交人信息的话&#xff0c;会有一个默认值。避免每次提交都要填提交人信息&#xff0c;直接设置成自己想要的默认值&#xff0c;该怎么操作&#xff1f; 提交的时候在这里修改提交人信息 避免每次都去设置…

和鲸科技受邀参与湖南省气象信息中心开展人工智能研究型业务支撑平台学术交流

为推进湖南省机器学习统一平台建设&#xff0c;2 月 29 日&#xff0c;湖南省气象信息中心开展学术讲座活动&#xff0c;活动由中心副主任冯冼主持&#xff0c;中心业务骨干、湖南省气象台、湖南分院等技术人员参加。 本次讲座邀请上海和今信息科技有限公司&#xff08;简称“…

【企业动态】欢迎法国客户来访东胜物联,深入探讨智能化合作

本周&#xff0c;来自法国的客户莅临我司工厂进行实地参观考察。客户是一家历史悠久的设备供应商&#xff0c;其产品涵盖冷链、餐饮、农业等多个行业应用领域&#xff0c;正致力于从传统设备向智能设备转型&#xff0c;希望将设备接入物联网。在此次访问中&#xff0c;他们参观…

fastapi_mail发送邮件,邮件附件文件重命名

当fastapi_mail发送邮件的时候&#xff0c;想对附件的名称进行重命名 以下是fastapi_mail下的schemas.py的源码 import os from enum import Enum from mimetypes import MimeTypes from typing import Dict, List, Optional, Unionfrom pydantic import BaseModel, EmailStr,…