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

目的

使用ActionFilter记录接口请求日志

实现案例:

仓库地址:https://gitee.com/hgcjd/WebApiFilter

一.首先我们新建一个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 moduleName,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>(); // 注册 ActionFilter

builder.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>>();
#endregion

var 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行动过滤器搭建成功,之后这个框架的接口请求就都会携带日志了

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值