zoukankan      html  css  js  c++  java
  • web api 记录请求

    前段时间在开发一个协议站点供客户端(Android/IOS)使用,因业务需要统计各协议的调用频率。将记录以日志的形式记录在日志系统中。

      简单分析了一下,技术方案大致分为两种:

      方案A:每个业务模块需要埋点的协议单独埋点。

      方案B:封装一个HttpModule。记录所有的请求。

      方案A与方案B的优缺点就不在分析了。在我们的项目有两个个小组做类似的协议站点,我们采用的是方案B。而另外的一个小组采用方案A。

      在此我重点说一下采用的方案B的理由:

        1、麻烦一个人,一个人开发完毕后,其他人不再去花时间增加记录。统一记录。

        2、方便排错,还可以做请求参数与输出参数的记录,也不用在业务中记录返回的值。业务开发只关心业务即可。记录业务中的常规日志即可。

      代码比较简单。与协议之间走的是Post请求发送Json串。请求串全在Request.InputStream中。两个文件一个处理请求(Handle.cs),一个获取数据(CatchTextStream.cs)

    Handle.cs

    using System;
    using System.IO;
    using System.Web;
    using Logs;
    
    namespace HttpModule.Api
    {
        public class Handle : IHttpModule
        {
            private string json = string.Empty;
            private string requestItemKey = "request.json";
            private string responseItemKey = "response.json";
            void IHttpModule.Dispose()
            {
            }
    
            void IHttpModule.Init(HttpApplication context)
            {
                context.BeginRequest += new EventHandler(beginRequest);
                context.EndRequest += new EventHandler(endRequest);
            }
            private void beginRequest(object sender, EventArgs e)
            {
                HttpApplication application = (HttpApplication)sender;
                var context = application.Context;
                if (context == null)
                {
                    return;
                }
    
                //排除不需要的链接
                if (context.Request.InputStream.Length > 0)
                {
                    context.Response.Filter = new CatchTextStream(context.Response.Filter, responseItemKey);
                    context.Request.InputStream.Position = 0; //设置流的位置
                    StreamReader reader = new StreamReader(context.Request.InputStream); //request请求流
                    string json = reader.ReadToEnd();
                    context.Request.InputStream.Seek(0, SeekOrigin.End);//重置流读取位置,如果不重置在方法中无法获取json串
                    context.Request.RequestContext.HttpContext.Items[requestItemKey] = json;
                }
                else//只记录请求参数
                {
                    _log.Info("请求url:" + context.Request.Url);
                }
    
            }
            private void endRequest(object sender, EventArgs e)
            {
                HttpApplication application = (HttpApplication)sender;
                var context = application.Context;
                if (context.Request.RequestContext.HttpContext.Items.Contains(requestItemKey))
                {
                    string requestJson = context.Request.RequestContext.HttpContext.Items[requestItemKey].ToString();
                    string responseJson = context.Request.RequestContext.HttpContext.Items[responseItemKey].ToString();
                    //当前请求状态 返回值中带code:0表示协议请求成功 status=日志系统使用标识,1=请求正常返回,0=请求异常
                    int status = responseJson.Contains(""code":"0"") ? 1 : 0;
                    writeLog(context.Request.Url.LocalPath, requestJson, "return=" + responseJson, status);
    
                }
    
            }
    
            private void writeLog(string url, string parms, string msg, int status)
            {
                var entity = new Logs.LogRecord("站点名称", LogLevelType.Monitor, url)
                {
                    ParasNameValue = parms,
                    ErrMessage = msg,
                    Status = status
                };
                Logs.LogNetHelper.WriteLog(entity);
            }
        }
    }

    注:Logs包为公司项目封装的通用记录方法。

    CatchTextStream.cs

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading.Tasks;
    using System.Web;
    
    namespace HttpModule.Api
    {
        class CatchTextStream : Stream
        {
            private Stream output;
            private List<byte> _listByte = new List<byte>();
            private string _itemKey;
            public CatchTextStream(Stream s, string itemKey)
            {
                _itemKey = itemKey;
                output = s;
            }
            public override bool CanRead
            {
                get { return output.CanRead; }
            }
    
    
            public override bool CanSeek
            {
                get { return output.CanSeek; }
            }
    
    
            public override bool CanWrite
            {
                get { return output.CanWrite; }
            }
    
    
            public override void Flush()
            {
    
                output.Flush();
                if (_listByte.Any())
                {
                    var utf8 = Encoding.UTF8;
                    string json = utf8.GetString(_listByte.ToArray(), 0, _listByte.Count);
                    HttpContext.Current.Request.RequestContext.HttpContext.Items[_itemKey] = json;
                }
            }
    
    
            public override long Length
            {
                get { return output.Length; }
            }
    
    
            public override long Position
            {
                get { return output.Position; }
                set { output.Position = value; }
            }
    
    
            public override int Read(byte[] buffer, int offset, int count)
            {
                return output.Read(buffer, offset, count);
            }
    
    
            public override long Seek(long offset, SeekOrigin origin)
            {
                return output.Seek(offset, origin);
            }
    
    
            public override void SetLength(long value)
            {
                output.SetLength(value);
            }
    
    
            public override void Write(byte[] buffer, int offset, int count)
            {
                output.Write(buffer, offset, count);
                if (HttpContext.Current != null)
                {
                    if (HttpContext.Current.Request.RequestContext.HttpContext.Items.Contains(_itemKey))
                    {
                        var temp = buffer.Skip(offset).Take(count);
                        _listByte.AddRange(temp);
                    }
                }
            }
        }
    }

    接下来在Web.config配置Modules即可。

    <modules runAllManagedModulesForAllRequests="true">
          <!--记录请求日志-->
          <add name="apilog" type="HttpModule.Api.Handle,HttpModule.Api" />
     </modules>
  • 相关阅读:
    hdu 2112 (最短路+map)
    poj 1502 最短路+坑爹题意
    poj 1696 Space Ant (极角排序)
    poj 1410 线段相交判断
    使用本地光盘安装Microsoft .NET Framework 3.5 for Win8.1/WinServer2012R2
    Excel REPT函数使用
    tomcat7配置虚拟目录
    Tomcat 7.0的配置
    js去除空格
    JAVABEAN连接各数据库
  • 原文地址:https://www.cnblogs.com/pengei/p/5924188.html
Copyright © 2011-2022 走看看