首页 > 其他分享 >监控调用接口记录日志

监控调用接口记录日志

时间:2023-05-22 17:22:45浏览次数:33  
标签:调用 string get Column 接口 set new 日志 public

1、监控中间件
public class OuterApiMonitorMiddleware : IMiddleware
{
    //private readonly ILogger<OuterApiMonitorMiddleware> _logger;
    private readonly IOuterApiLogger _apiLog;
    public OuterApiMonitorMiddleware(/*ILogger<OuterApiMonitorMiddleware> logger,*/ IOuterApiLogger apiLog)
    {
        //_logger = logger;
        _apiLog = apiLog;
    }

    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        var path = context.Request.Path.Value ?? string.Empty;

        //注意:这里重点,对访问地址是/PRO/INTEGRATION开头的自动记录log
        if (!path.StartsWith("/PRO/INTEGRATION", StringComparison.OrdinalIgnoreCase))
        {
            await next.Invoke(context);
            return;
        }

        await Monitor(context, next, path);
    }

    /// <summary>
    /// 监控接口调用
    /// </summary>
    private async Task Monitor(HttpContext context, RequestDelegate next, string path)
    {
        var stopWatch = Stopwatch.StartNew();

        var start = DateTime.Now;
        DateTime end;
        Exception exception = null;
        var requestBody = string.Empty;
        var responseBody = string.Empty;

        try
        {
            requestBody = await new StreamReader(context.Request.Body).ReadToEndAsync();
            context.Request.Body.Position = 0;

            var originalResponseBody = context.Response.Body;
            try
            {
                using var swapStream = new MemoryStream();
                context.Response.Body = swapStream;

                await next(context);

                context.Response.Body.Seek(0, SeekOrigin.Begin);

                using var s= new StreamReader(context.Response.Body);
                responseBody = await s.ReadToEndAsync();

                context.Response.Body.Seek(0, SeekOrigin.Begin);
                await swapStream.CopyToAsync(originalResponseBody);
            }
            finally
            {
                context.Response.Body = originalResponseBody;
            }
        }
        catch (Exception e)
        {
            exception = e;
        }

        stopWatch.Stop();
        end = DateTime.Now;

        await Logger(context, requestBody, responseBody, (long)stopWatch.ElapsedMilliseconds, start, end, exception);
    }

    /// <summary>
    /// 记录日志
    /// </summary>
    private async Task Logger(HttpContext context, string requestBody, string responseBody, long elapsed, DateTime start, DateTime end, Exception exception)
    {
        var entry = new ProOuterApiLog
        {
            Level = Microsoft.Extensions.Logging.LogLevel.Information,
            TimeStamp = DateTime.Now,
            Ip = context.Request.HttpContext.GetClientUserIp(),
            Header = $"{{Authorization:{context.Request.Headers["Authorization"]},Last_Working_Object_Id:{context.Request.Headers["Last_Working_Object_Id"]}}}",
            Host = context.Request.Host.ToString(),
            Url = context.Request.Path,
            QueryString = context.Request.QueryString.ToString(),
            RequestBody = requestBody,
            ResponseBody = responseBody,
            StartTime = start,
            EndTime = end,
            ElapsedTime = elapsed,
            Message = "",
            Exception = exception?.ToString() ?? "",
            RequestId = context.Request.HttpContext.TraceIdentifier
        };

        await _apiLog.HttpRequest(entry);
    }
}
2、记录日志
public class OuterApiLogger : IOuterApiLogger
{
    private readonly ILogger<OuterApiLogger> _logger;
    private readonly IWebHostEnvironment _environment;
    private readonly IProOuterApiLogDAL _dal;//这个是DAL层,方便写sql
    private readonly IHttpContextAccessor _httpContextAccessor;

    public OuterApiLogger(ILogger<OuterApiLogger> logger, IWebHostEnvironment environment, IProOuterApiLogDAL dal, IHttpContextAccessor httpContextAccessor)
    {
        _logger = logger;
        _environment = environment;
        _dal = dal;
        _httpContextAccessor = httpContextAccessor;
    }

    public async Task HttpRequest(ProOuterApiLog entry)
    {
        await Insert(entry);
    }

    public async Task Information(string message)
    {
        await Insert(new ProOuterApiLog
        {
            Level = LogLevel.Information,
            Message = message,
        });
    }

    public async Task Warning(string message)
    {
        await Insert(new ProOuterApiLog
        {
            Level = LogLevel.Warning,
            Message = message,
        });
    }

    public async Task Error(string message, Exception exception = null)
    {
        await Insert(new ProOuterApiLog
        {
            Level = LogLevel.Error,
            Message = message,
            Exception = exception?.ToString()
        });
    }

    public async Task Critical(string message)
    {
        await Insert(new ProOuterApiLog
        {
            Level = LogLevel.Critical,
            Message = message,
        });
    }

    private async Task Insert(ProOuterApiLog entry)
    {

        var request = _httpContextAccessor.HttpContext?.Request;

        var parameters = new List<SugarParameter>
        {
            new SugarParameter("@level",entry.Level),
            new SugarParameter("@timestamp",DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fffffff")),
            new SugarParameter("@ip",entry.Ip ?? request.HttpContext.GetClientUserIp() ?? string.Empty),
            new SugarParameter("@header",entry.Header ?? string.Empty),
            new SugarParameter("@host",entry.Host ?? request.Host.ToString()?? string.Empty),
            new SugarParameter("@url",entry.Url ?? request?.Path?? string.Empty),
            new SugarParameter("@querystring",entry.QueryString ?? request?.QueryString.ToString() ?? string.Empty),
            new SugarParameter("@requestbody",entry.RequestBody ?? string.Empty),
            new SugarParameter("@responsebody",entry.ResponseBody ?? string.Empty),
            new SugarParameter("@starttime",entry.StartTime.ToString("yyyy-MM-dd HH:mm:ss.fffffff")),
            new SugarParameter("@endtime",entry.EndTime.ToString("yyyy-MM-dd HH:mm:ss.fffffff")),
            new SugarParameter("@elapsedtime",entry.ElapsedTime),
            new SugarParameter("@message",entry.Message ?? string.Empty),
            new SugarParameter("@exception",entry.Exception?.ToString() ?? string.Empty),
            new SugarParameter("@requestid",_httpContextAccessor.HttpContext.TraceIdentifier ?? string.Empty)
        };

        try
        {   
            await _dal.ExecuteBySql("INSERT INTO pro_outer_api_log (level,timestamp,ip,header,host,url,querystring,requestbody,responsebody,starttime,endtime,elapsedtime,message,exception,requestid) VALUES(@level,CAST(@timestamp AS timestamp(6)),@ip,@header,@host,@url,@querystring,@requestbody,@responsebody,CAST(@starttime AS timestamp(6)),CAST(@endtime AS timestamp(6)),@elapsedtime,@message,@exception,@requestid)", parameters.ToArray());
        }
        catch (Exception e)
        {
            _logger.LogError(e, "记录日志异常");
        }
    }
}
3、日志表
public class ProOuterApiLog : BaseEntity
{
    /// <summary>
    ///     日志等级
    /// </summary>
    [Column(Description = "日志等级", DataType = PGDataType.VARCHAR)]
    public LogLevel Level { get; set; }
    /// <summary>
    ///     记录时间
    /// </summary>
    [Column(Description = "记录时间")]
    public DateTime TimeStamp { get; set; }
    /// <summary>
    ///     请求IP地址
    /// </summary>
    [Column(Description = "请求IP地址")]
    public string Ip { get; set; }
    /// <summary>
    ///     请求头
    /// </summary>
    [Column(Description = "请求头")]
    public string Header { get; set; }
    /// <summary>
    ///     请求主机
    /// </summary>
    [Column(Description = "请求主机")]
    public string Host { get; set; }
    /// <summary>
    ///     请求地址
    /// </summary>
    [Column(Description = "请求地址")]
    public string Url { get; set; }
    /// <summary>
    ///     查询参数
    /// </summary>
    [Column(Description = "查询参数")]
    public string QueryString { get; set; }
    /// <summary>
    ///     请求主体
    /// </summary>
    [Column(Description = "请求主体")]
    public string RequestBody { get; set; }
    /// <summary>
    ///     响应主体
    /// </summary>
    [Column(Description = "响应主体")]
    public string ResponseBody { get; set; }
    /// <summary>
    ///     开始时间
    /// </summary>
    [Column(Description = "开始时间")]
    public DateTime StartTime { get; set; }
    /// <summary>
    ///     结束时间
    /// </summary>
    [Column(Description = "结束时间")]
    public DateTime EndTime { get; set; }
    /// <summary>
    ///     请求消耗时间,单位:毫秒
    /// </summary>
    [Column(Description = "请求消耗时间,单位:毫秒")]
    public long ElapsedTime { get; set; }
    /// <summary>
    ///     消息
    /// </summary>
    [Column(Description = "消息")]
    public string Message { get; set; }
    /// <summary>
    ///     异常
    /// </summary>
    [Column(Description = "异常")]
    public string Exception { get; set; }
    /// <summary>
    ///     请求ID
    /// </summary>
    [Column(Description = "请求ID")]
    public string RequestId { get; set; }
}


/// <summary>
/// 实体基类
/// </summary>
public class BaseEntity
{
    #region 构造函数
    /// <summary>
    /// 构造函数
    /// </summary>
    public BaseEntity()
    {
    }
    #endregion

    #region 属性
    /// <summary>
    /// ID
    /// </summary>
    [Column(IsIdentity = true, Description = "主键Id", Sort = -100)]
    public string Id { get; set; }
    /// <summary>
    /// 创建人ID
    /// </summary>
    [Column(Description = "创建人ID", Sort = 100)]
    [SugarColumn(IsOnlyIgnoreUpdate = true)]
    public string Create_UserId { get; set; }
    /// <summary>
    /// 修改人ID
    /// </summary>
    [Column(Description = "修改人ID", Sort = 101)]
    [SugarColumn(IsOnlyIgnoreInsert = true)]
    public string Modify_UserId { get; set; }
    /// <summary>
    /// 创建人
    /// </summary>
    [Column(Description = "创建人", Sort = 102)]
    [SugarColumn(IsOnlyIgnoreUpdate = true)]
    public string Create_UserName { get; set; }
    /// <summary>
    /// 修改人
    /// </summary>
    [Column(Description = "修改人", Sort = 103)]
    [SugarColumn(IsOnlyIgnoreInsert = true)]
    public string Modify_UserName { get; set; }
    /// <summary>
    /// 创建日期
    /// </summary>
    [Column(Description = "创建日期", IsNullable = true, Sort = 104)]
    [SugarColumn(IsOnlyIgnoreUpdate = true)]
    public DateTime? Create_Date { get; set; }
    /// <summary>
    /// 修改日期
    /// </summary>
    [Column(Description = "修改日期", IsNullable = true, Sort = 105)]
    [SugarColumn(IsOnlyIgnoreInsert = true)]
    public DateTime? Modify_Date { get; set; }
    /// <summary>
    /// 是否删除
    /// </summary>
    [Column(Description = "是否删除", Sort = 106)]
    public bool Is_Deleted { get; set; } = false;
    /// <summary>
    /// 自增ID,排序使用
    /// </summary>
    [Column(Description = "自增ID,排序使用", Sort = 107, DataType = PGDataType.SERIAL)]
    public long AutoIncrm_Id { get; set; }
    #endregion
}

标签:调用,string,get,Column,接口,set,new,日志,public
From: https://www.cnblogs.com/eaknow/p/17421213.html

相关文章

  • Java调用采集拼多多根据ID获取商品详情API接口返回值说明示例,获取电商平台商品详情数
    ​     拼多多是一家基于C2B拼团营销方式主营团购的电商平台,其盈利模式由利润源、利润点、利润杠杆、利润通道和利润屏障五个要素组成的。通过锁定目标客户、关注客户价值、举办相关活动、不断拓展收入来源等经营策略,拼多多在较短的时间内得以快速成长。然而这种模式也......
  • 【JAVA】调用第三方接口发送request请求
    一、通过JDK网络类Java.net.HttpURLConnection通过统一资源定位器(java.net.URL)获取连接器(java.net.URLConnection)。设置请求的参数。发送请求。以输入流的形式获取返回内容。关闭输入流。 1、发送post请求packagecom.Run;importjava.io.*;importjava.net.HttpU......
  • python实现kafka收到消息然后在通过websockt发送给其他服务器的方法(异步调用并且收到
    importasyncioimportthreadingfromkafkaimportKafkaConsumerimportwebsocketsconnected=set()asyncdefhandler(websocket,path):connected.add(websocket)whileTrue:awaitasyncio.sleep(1)defstart_kafka():consumer=KafkaC......
  • resttemplate封装类方便调用
    1publicclassRnrFpRestTemplateUtils{23privatestaticfinalLoggerLOGGER=LoggerFactory.getLogger(RnrFpRestTemplateUtils.class);456/**7*Description:post请求Response泛型8*<br/>9*CreateDate......
  • ServletContext接口详解
    1. ServletContext是什么?  14 *  ServletContext是接口,是Servlet规范中的一员。2. ServletContext是谁实现的?14 *  Tomcat服务器(WEB服务器)实现了ServletContext接口。 *  public class org.apache.catalina.core.ApplicationContextFacade implements ServletCont......
  • 【iOS开发】UIWebView调用JS点击事件(stringByEvaluatingJavaScriptFromString)
    一、场景描述产品需求是移动端app要调用h5页面,然后监听h5代码中的某个方法,最终执行h5中的具体代码。二、具体代码.m文件@interfaceViewController()<UIWebViewDelegate>@property(nonatomic,strong)UIWebView*webView;@end@implementationViewController-(void)viewDid......
  • Java使用HttpClient以multipart/form-data向接口上传文件
    前言对接某公司的接口,涉及到资质上传等业务。需要对接他们的上传附件接口。JDK1.8httpclient4.x封装httpclient方法publicstaticStringpostFileMultiPart(Stringurl,Map<String,ContentBody>reqParam)throwsIOException{ CloseableHttpClienthttpclient=HttpCl......
  • 基于 Socket 接口实现自定义协议通信
    访问【WRITE-BUG数字空间】_[内附完整源码和文档]根据自定义的协议规范,使用Socket编程接口编写基本的网络应用软件。掌握C语言形式的Socket编程接口用法,能够正确发送和接收网络数据包开发一个客户端,实现人机交互界面和与服务器的通信开发一个服务端,实现并发处理多个客户端......
  • 5-19|记录Python调用salt代码
    #放大一importsalt.clientlocal=salt.client.LocalClient()res=local.cmd(f'{minion_id}','test.ping',timeout=10)#方法二importsalt.configimportsalt.loader__opts__=salt.config.minion_config('/etc/salt/minion')__grains__......
  • 计算机组成原理:系统总线与总线接口实验
    实验名称:3.系统总线与总线接口实验实验目的理解总线的概念及其特性。掌握控制总线的功能和应用。理解总线的功能和和典型工作流程。掌握在总线上协调ALU和外设交换数据的方法。实验设备PC机一台,TDX-CMX实验系统一套。实验预习1、阅读实验指导书,然后回答问题。本实......