zoukankan      html  css  js  c++  java
  • 无侵入方面编程-用HttpModule+SoapExtension监视页面执行参数(一)

    先简单介绍一下项目吧,我们这个项目是用VS2003开发的,老早一个项目。WEB前端机+业务处理(WebService层)+数据库分别布置在不同的计算机上。

        现在老总有一个需求,要统计出每个页面的执行时间,以及每次调用过哪些WebService方法,调用的时间等参数。

        可行的方案有好多,但我感觉使用HttpModule+SoapExtension,可以不在改变目标系统源码的基础上,完成这项工作。也许有一天,老总说,现在不需要再统计了,我就直接配置一下,不再统计就行了。

        由于要调用WebService,我们采用编写一个SoapExtension,在它的ProcessMessage函数中,在message.Stage是 BeforeSerialize 时,记一个开始时间,并采集一些数据,在message.Stage==AfterDeserialize时,再采集一些时间等数据。最后通过HttpContext.Current.Items[WSInvokeMonitorKey]获取HttpModule的对象,把采集到的数据放在HttpModule里面。

        在HttpModule层,我们可以context的BeginRequest、PreRequestHandlerExecute、PreSendRequestContent、EndRequest中采集数据,最后写入通过Log4net写入日志文件。

        具体实现起来,应该很简单,高手可以略过了。

    先看看如何使用吧,只需在Web.Config中加一条配置:


    <configuration>
      <system.web>
         <httpModules>
            <add name="WSInvokeMonitorHttpModule" type="Hebmc.WebTools.WSInvokeMonitor.WSInvokeMonitorHttpModule,WSInvokeMonitor"/>
        </httpModules>
        <webServices>
            <soapExtensionTypes>
                <add type="Hebmc.WebTools.WSInvokeMonitor.SimpleWSInvokeMonitorExtension,WSInvokeMonitor"
                    priority="1"
                    group="0" />
            </soapExtensionTypes>
        </webServices>
     </system.web>
    </configuration>

    SoapExtension实现:


        public class SimpleWSInvokeMonitorExtension : SoapExtension
        {
            private const string WSInvokeMonitorKey = "__WSInvokeMonitorKey__";
            private WSInvokeInfo invokeInfo = new WSInvokeInfo();
            public override System.IO.Stream ChainStream(System.IO.Stream stream)
            {
                return stream;
            }

            public override object GetInitializer(Type serviceType)
            {
                return null;
            }

            public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
            {
                return null;
            }

            public override void Initialize(object initializer)
            {

            }


            public override void ProcessMessage(SoapMessage message)
            {
                if(message is SoapClientMessage)
                {
                    switch (message.Stage) 
                    {
                        case SoapMessageStage.BeforeSerialize:

                            //采集时间
                            this.invokeInfo.BeginInvokeTime = DateTime.Now;
                            //采集WebService方法名
                            this.invokeInfo.MethodName = message.MethodInfo.Name;
                            break;


                        case SoapMessageStage.AfterSerialize:
                            break;


                        case SoapMessageStage.BeforeDeserialize:
                            break;

                            // About to call methods
                        case SoapMessageStage.AfterDeserialize:

                            //采集时间
                            this.invokeInfo.EndInvokeTime = DateTime.Now;

                            PageInfo pageInfo = (PageInfo)HttpContext.Current.Items[WSInvokeMonitorKey] ;
                            if(pageInfo != null)
                            {
                                //添加到Module记录
                                pageInfo.AppendInvokeInfo(this.invokeInfo);
                            }

                            break;

                            // After Method call

                        default:
                            throw new Exception("No stage such as this");
                    }

                }
                else if(message is SoapServerMessage)
                {
                    switch (message.Stage) 
                    {
                        case SoapMessageStage.BeforeDeserialize:
                            break;

                        case SoapMessageStage.AfterDeserialize:
                            break;

                        case SoapMessageStage.BeforeSerialize:
                            break;

                        case SoapMessageStage.AfterSerialize:
                            break;

                        default:
                            throw new Exception("No stage such as this");
                    }

                }
            }


        }

    HttpModule实现:


        public class WSInvokeMonitorHttpModule : IHttpModule    
        {
            private static ILog log  = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
            private const string WSInvokeMonitorKey = "__WSInvokeMonitorKey__";
            HttpApplication httpApp = null;

            #region IHttpModule 成员

            public void Init(HttpApplication webApp)
            {
                this.httpApp = webApp;

                //注册事件 
                this.httpApp.BeginRequest+=new EventHandler(context_BeginRequest);
                this.httpApp.PreRequestHandlerExecute+=new EventHandler(httpApp_PreRequestHandlerExecute);
                this.httpApp.PreSendRequestContent+=new EventHandler(context_PreSendRequestContent);
                this.httpApp.EndRequest+=new EventHandler(context_EndRequest);
            }

            public void Dispose()
            {
                this.httpApp.BeginRequest-=new EventHandler(context_BeginRequest);
                this.httpApp.PreSendRequestContent-=new EventHandler(context_PreSendRequestContent);
                this.httpApp.EndRequest-=new EventHandler(context_EndRequest);
            }

            #endregion







            private void context_BeginRequest(object sender, EventArgs e)
            {
                HttpApplication webApp = sender as HttpApplication;
                if(webApp != null)
                {
                    PageInfo pageInfo = null;
                    
                    //开始时,设置数据对象,将来采集到的数据都放在这里
                    webApp.Context.Items[WSInvokeMonitorKey] = pageInfo = new PageInfo();

                    //采集路径
                    pageInfo.PageUri = webApp.Context.Request.Url.ToString();
                }
                
            }

            private void httpApp_PreRequestHandlerExecute(object sender, EventArgs e)
            {
                HttpApplication webApp = sender as HttpApplication;
                if(webApp != null)
                {
                    Page page = webApp.Context.Handler as Page;
                    if(page != null)
                    {
                        PageInfo pageInfo = (PageInfo)webApp.Context.Items[WSInvokeMonitorKey];
                        if(pageInfo != null)
                        {
                            //采集处理类名,及时间
                            pageInfo.TypeName = page.GetType().FullName;
                            pageInfo.PreRequestHandlerExecuteTime = DateTime.Now;
                        }
                    }

                }
            }

            private void context_PreSendRequestContent(object sender, EventArgs e)
            {
                HttpApplication webApp = sender as HttpApplication;
                if(webApp != null)
                {
                    Page page = webApp.Context.Handler as Page;
                    if(page != null)
                    {
                        PageInfo pageInfo = (PageInfo)webApp.Context.Items[WSInvokeMonitorKey];
                        if(pageInfo != null)
                        {
                            try
                            {
                                //采集时间
                                pageInfo.PreSendRequestContentTime = DateTime.Now;

                                if(log.IsInfoEnabled)
                                {
                                    //记日志
                                    string xmlData = string.Empty;
                                    XmlSerializer xs = new XmlSerializer(typeof(PageInfo));
                                    StringBuilder sb = new StringBuilder();
                                    using(MemoryStream ms = new MemoryStream())
                                    {
                                        XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.UTF8);
                                        xtw.Formatting = Formatting.None;
                                        xs.Serialize(xtw, pageInfo);
                                        

                                        ms.Position = 0;

                                        StreamReader sr = new StreamReader(ms, Encoding.UTF8);
                                        xmlData = sr.ReadToEnd();
                                    }

                                    TimeSpan tsExecute = pageInfo.EndRequestTime - pageInfo.BeginRequestTime;
                                    log.InfoFormat("{0},{1},{2}MS,{3},{4},{5}", 
                                        pageInfo.BeginRequestTime, 
                                        pageInfo.TypeName, 
                                        tsExecute.TotalMilliseconds, 
                                        pageInfo.WSInvokeCount,
                                        pageInfo.PageUri, 
                                        xmlData);

                                }
                            }
                            catch (System.Exception ex)
                            {
                                log.Error(ex);
                            }
                        }
                    }
                }
            }

            private void context_EndRequest(object sender, EventArgs e)
            {
                HttpApplication webApp = sender as HttpApplication;
                if(webApp != null)
                {
                    Page page = webApp.Context.Handler as Page;
                    if(page != null)
                    {
                        PageInfo pageInfo = (PageInfo)webApp.Context.Items[WSInvokeMonitorKey];
                        if(pageInfo != null)
                        {
                            //采集时间
                            pageInfo.EndRequestTime = DateTime.Now;
                        }


                    }
                }
            }

        }

    用到的数据类:


    namespace Hebmc.WebTools.WSInvokeMonitor.Data
    {
        [Serializable]
        public class PageInfo
        {
            private string typeName;
            private string pageUri;
            private DateTime beginRequestTime = DateTime.Now;
            private DateTime preRequestHandlerExecuteTime = DateTime.Now;
            private DateTime endRequestTime = DateTime.Now;
            private DateTime preSendRequestContentTime = DateTime.Now;
            private ArrayList wsInvokeInfoList = new ArrayList();

            /// <summary>
            /// 类名
            /// </summary>
            public string TypeName
            {
                get { return typeName; }
                set { typeName = value; }
            }

            /// <summary>
            /// 页面URI
            /// </summary>
            public string PageUri
            {
                get { return pageUri; }
                set { pageUri = value; }
            }

            /// <summary>
            /// 开始时间
            /// </summary>
            public System.DateTime BeginRequestTime
            {
                get { return beginRequestTime; }
                set { beginRequestTime = value; }
            }

            /// <summary>
            /// 开始处理时间
            /// </summary>
            public System.DateTime PreRequestHandlerExecuteTime
            {
                get { return preRequestHandlerExecuteTime; }
                set { preRequestHandlerExecuteTime = value; }
            }

            /// <summary>
            /// 结束处理时间
            /// </summary>
            public System.DateTime EndRequestTime
            {
                get { return endRequestTime; }
                set { endRequestTime = value; }
            }


            /// <summary>
            /// 向客户端发送数据开始时间
            /// </summary>
            public System.DateTime PreSendRequestContentTime
            {
                get { return preSendRequestContentTime; }
                set { preSendRequestContentTime = value; }
            }

            /// <summary>
            /// 调用次数
            /// </summary>
            [XmlIgnore]
            public int WSInvokeCount
            {
                get
                {
                    return this.wsInvokeInfoList.Count;
                }
            }


            /// <summary>
            /// 该页面调用的WebService信息
            /// </summary>
            public WSInvokeInfo[] WSInvokeInfos
            {
                get
                {
                    return (WSInvokeInfo[])wsInvokeInfoList.ToArray(typeof(WSInvokeInfo));
                }
                set
                {
                    wsInvokeInfoList.AddRange(value);
                }
            }

            /// <summary>
            /// 添加一个调用WebService日志
            /// </summary>
            /// <param name="info"></param>
            public void AppendInvokeInfo(WSInvokeInfo info)
            {
                wsInvokeInfoList.Add(info);
            }

            /// <summary>
            /// 序列化需要
            /// </summary>
            public PageInfo()
            {}
        }

        [Serializable]
        public class WSInvokeInfo
        {
            private string methodName;
            private DateTime beginInvokeTime = DateTime.Now;
            private DateTime endInvokeTime = DateTime.Now;

            /// <summary>
            /// 函数名
            /// </summary>
            public string MethodName
            {
                get { return methodName; }
                set { methodName = value; }
            }

            /// <summary>
            /// 开始调用时间
            /// </summary>
            public System.DateTime BeginInvokeTime
            {
                get { return beginInvokeTime; }
                set { beginInvokeTime = value; }
            }

            /// <summary>
            /// 结束调用时间
            /// </summary>
            public System.DateTime EndInvokeTime
            {
                get { return endInvokeTime; }
                set { endInvokeTime = value; }
            }




        }
    }

    OK了,这个方案还可以继续深入,可以使用SoapExtension把WebService层的采集到的数据,也拉到前端。这样便可以知道一个WebService方法执行几次数据库连接。嘿嘿。

    http://www.cnblogs.com/evlon/archive/2009/05/22/1486866.html

  • 相关阅读:
    【转+补充】在OpenCV for Android 2.4.5中使用SURF(nonfree module)
    Delphi StarOffice Framework Beta 1.0 发布
    Angular ngIf相关问题
    angularjs文档下载
    公众号微信支付开发
    公众号第三方平台开发 教程六 代公众号使用JS SDK说明
    公众号第三方平台开发 教程五 代公众号处理消息和事件
    公众号第三方平台开发 教程四 代公众号发起网页授权说明
    公众号第三方平台开发 教程三 微信公众号授权第三方平台
    公众号第三方平台开发 教程二 component_verify_ticket和accessToken的获取
  • 原文地址:https://www.cnblogs.com/chen110xi/p/5715542.html
Copyright © 2011-2022 走看看