统计WebService的调用者、调用函数、运行时间

系统WebServic分布太久了, 都不知道哪些系统在用? 调用的哪些函数?于是乎,写一个Soap Extension, 再加一个页面,来查询一下。

先看一下配制说明,和效果

web.config中

<system.web>
     <compilation debug= "true"  targetFramework= "4.0"  />
   <!--<httpHandlers>
     <add path= "dl"  type= "OA4.SOA.Impl.HttpHandler.DownloadAttach"  verb= "GET" />
   </httpHandlers>-->
   <webServices>
     <soapExtensionTypes>
       <add type= " OA4.CommonLib.Soap.TimeWatchExtension,OACommonLib"
           priority= "1"
           group = "0"  />
     </soapExtensionTypes>
   </webServices>
 
</system.web>

  

然后访问查询页面:

 

当前运行:0
 
最后记录:20,    3.0 (Call/S), 27.8 (MS/Call)
Host:10.129.255.105,  UseTime:0, Time:2012-9-4 9:15:42, name:GetCanStarFlowList,Arg:AComp:=衡水分公司, ADept:=县公司, AUser:=杨立华
Host:10.129.255.105,  UseTime:15.6249, Time:2012-9-4 9:15:42, name:GetAgendumList,Arg:sUserName:=杨立华, sCompany:=衡水分公司, sDepartment:=县公司, sDuty:=经理, sRole:=, type:=all, dbfield:=ReceiveTime, order:=ASC, pageSize:=25, pageNumber:=1, pageCount:=0, recordCount:=0
Host:10.129.255.104,  UseTime:46.8747, Time:2012-9-4 9:15:43, name:GetBillData_done,Arg:ABillID:=54533f29-8979-4b1d-adf8-b8fbf2cf7678, year:=
Host:10.129.255.104,  UseTime:0, Time:2012-9-4 9:15:43, name:GetCurrentActivityName,Arg:flowInstanceId:=54533f29-8979-4b1d-adf8-b8fbf2cf7678
Host:10.129.255.218,  UseTime:15.6249, Time:2012-9-4 9:15:43, name:GetAgendumList,Arg:sUserName:=耿书芬, sCompany:=邯郸分公司, sDepartment:=广平分公司, sDuty:=, sRole:=, type:=all, dbfield:=ReceiveTime, order:=DESC, pageSize:=20, pageNumber:=1, pageCount:=0, recordCount:=0
Host:10.129.255.216,  UseTime:15.6249, Time:2012-9-4 9:15:45, name:GetAgendumList,Arg:sUserName:=魏广芹, sCompany:=张家口分公司, sDepartment:=渠道管理中心, sDuty:=, sRole:=, type:=all, dbfield:=ReceiveTime, order:=DESC, pageSize:=20, pageNumber:=1, pageCount:=0, recordCount:=0
Host:10.129.255.104,  UseTime:46.8747, Time:2012-9-4 9:15:46, name:GetUserInfo,Arg:userName:=caoruifen_sjz
Host:10.129.255.104,  UseTime:0, Time:2012-9-4 9:15:46, name:GetDoingFlowInfo,Arg:activeInstId:=c1e1d9ef-6a8f-46e8-98d1-dedac3c6137c
Host:10.129.255.104,  UseTime:0, Time:2012-9-4 9:15:46, name:GetActiveInstInfo,Arg:activeInstID:=c1e1d9ef-6a8f-46e8-98d1-dedac3c6137c, parentBillID:=47a88d95-05db-4c24-a18c-ff41620495a0
Host:10.129.255.104,  UseTime:62.4996, Time:2012-9-4 9:15:46, name:GetBillData_done,Arg:ABillID:=e14d1f34-53b5-4824-afd9-f8207dc4bab3, year:=
Host:10.129.255.104,  UseTime:15.6249, Time:2012-9-4 9:15:46, name:UpdateRead,Arg:ActivityInstanceID:=c1e1d9ef-6a8f-46e8-98d1-dedac3c6137c
Host:10.129.255.104,  UseTime:15.6249, Time:2012-9-4 9:15:46, name:FindNextRouteReturnConnects,Arg:sFlowID:=ae76d210-85f3-403f-ba4b-485c72cbb96e, sFlowInstanceID:=e14d1f34-53b5-4824-afd9-f8207dc4bab3, sActivityID:=c16d997c-f471-49f1-adef-e64cad616d79
Host:10.129.255.104,  UseTime:234.3735, Time:2012-9-4 9:15:47, name:GetBillData_done,Arg:ABillID:=da7276c9-80af-485a-975a-f881be30b0f2, year:=2008
Host:10.129.255.105,  UseTime:15.6249, Time:2012-9-4 9:15:47, name:GetActiveInstInfo,Arg:activeInstID:=4b19dfbc-51e7-4a0f-b3ce-08e17e49f64b, parentBillID:=266d7ab5-57fe-48fc-9118-27b43d1e5f10
Host:10.129.255.105,  UseTime:46.8747, Time:2012-9-4 9:15:47, name:GetBillData_done,Arg:ABillID:=32d11123-7ab0-4757-ba57-5d3e53b8eafe, year:=
Host:10.129.255.105,  UseTime:31.2498, Time:2012-9-4 9:15:47, name:UpdateRead,Arg:ActivityInstanceID:=4b19dfbc-51e7-4a0f-b3ce-08e17e49f64b
Host:10.129.255.105,  UseTime:0, Time:2012-9-4 9:15:47, name:FindNextRouteReturnConnects,Arg:sFlowID:=ae76d210-85f3-403f-ba4b-485c72cbb96e, sFlowInstanceID:=32d11123-7ab0-4757-ba57-5d3e53b8eafe, sActivityID:=12e9306a-5107-493f-8ac9-8966011bd0fc
Host:10.129.255.104,  UseTime:0, Time:2012-9-4 9:15:47, name:GetCurrentActivityName,Arg:flowInstanceId:=da7276c9-80af-485a-975a-f881be30b0f2
Host:10.129.255.104,  UseTime:0, Time:2012-9-4 9:15:47, name:GetWordField,Arg:flowInstID:=da7276c9-80af-485a-975a-f881be30b0f2
Host:10.129.255.104,  UseTime:0, Time:2012-9-4 9:15:47, name:SaveFavorite,Arg:userName:=张翔凯, flowInstID:=7d03a4a1-07ff-4bdc-b2a4-cb381fec357f

  

 

实现代码:Soap

using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;
using  System.Web.Services.Protocols;
using  System.Web;
using  System.Collections.Specialized;
using  System.Collections.Concurrent;
using  System.Collections;
using  log4net;
using  System.Threading;
 
namespace  OA4.CommonLib.Soap
{
     public  class  TimeWatchExtension : SoapExtension
     {
         protected  static  ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
 
         private  static  ConcurrentDictionary<Guid, WSInvokeInfo> running = new  System.Collections.Concurrent.ConcurrentDictionary<Guid, WSInvokeInfo>();
 
         private  static  ConcurrentQueue<WSInvokeInfo> last = new  ConcurrentQueue<WSInvokeInfo>();
 
         private  static  ConcurrentDictionary< string , ConcurrentQueue<WSInvokeInfo>> remoteUserHost = new  ConcurrentDictionary< string , ConcurrentQueue<WSInvokeInfo>>();
 
 
         public  static  ConcurrentDictionary<Guid, WSInvokeInfo> Running { get  { return  running; } }
 
         public  static  ConcurrentQueue<WSInvokeInfo> LastInvoke { get  { return  last; } }
 
         public  static  RemoteHostInfo[] RemoteUserHost { get  { return  remoteUserHost.ToList().ConvertAll(d=> new  RemoteHostInfo(){ Host = d.Key, LastInvoke = d.Value.ToArray()}).ToArray(); } }
 
         public  static  int  MaxRunningMilliseconds = int .Parse(System.Configuration.ConfigurationManager.AppSettings[ "TimeWatchExtension.MaxRunningMilliseconds" ] ?? "800" );
 
         public  static  Timer timerSnap = null ;
         static  TimeWatchExtension()
         {
             timerSnap = new  Timer( new  TimerCallback(e => {
 
                 if  (Running.Count > 0)
                 {
                     var  running = Running.ToList();
 
                     running.ForEach(d => {
                         if  (d.Value.UseTime.TotalMilliseconds > MaxRunningMilliseconds)
                         {
                             log.Warn(d.Value.ToString());
                         }
                     });
                 }
             
             }));
 
             timerSnap.Change(1000, 1000);
         }
 
 
 
         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:
 
                         break ;
 
 
                     case  SoapMessageStage.AfterSerialize:
                         break ;
 
 
                     case  SoapMessageStage.BeforeDeserialize:
                         break ;
 
                     // About to call methods
                     case  SoapMessageStage.AfterDeserialize:
                         break ;
 
                     // After Method call
                     default :
                         throw  new  Exception( "No stage such as this" );
                 }
 
             }
             else  if  (message is  SoapServerMessage)
             {
                 SoapServerMessage msg = (SoapServerMessage)message;
                 switch  (message.Stage)
                 {
                     case  SoapMessageStage.BeforeDeserialize:
                         break ;
 
                     case  SoapMessageStage.AfterDeserialize:
                         {
                             //采集时间
                             this .invokeInfo.BeginInvokeTime = DateTime.Now;
                             //采集WebService方法名
                             this .invokeInfo.MethodName = message.MethodInfo.Name;
 
                             this .invokeInfo.UserHostAddress = System.Web.HttpContext.Current.Request.UserHostAddress;
 
 
                             this .invokeInfo.Args = new  Dictionary< string , object >();
 
                             message.MethodInfo.InParameters.ToList().ForEach(d =>
                                 {
                                     this .invokeInfo.Args.Add(d.Name, message.GetInParameterValue(d.Position));
                                 });
 
                             running.TryAdd( this .invokeInfo.Id, this .invokeInfo);
 
                             {
                                 last.Enqueue(invokeInfo);
 
                                 if  (last.Count > 20)
                                 {
                                     WSInvokeInfo removed;
                                     last.TryDequeue( out  removed);
                                 }
                             }
                             {
                                 var  queue = remoteUserHost.GetOrAdd(invokeInfo.UserHostAddress, uha => new  ConcurrentQueue<WSInvokeInfo>());
                                 queue.Enqueue(invokeInfo);
                                 if  (queue.Count > 5)
                                 {
                                     WSInvokeInfo removed;
                                     queue.TryDequeue( out  removed);
                                 }
                             }
                         }
                         break ;
 
                     case  SoapMessageStage.BeforeSerialize:
                         {
                             //采集时间
                             this .invokeInfo.EndInvokeTime = DateTime.Now;
                             WSInvokeInfo removed;
                             running.TryRemove( this .invokeInfo.Id, out  removed);
 
                             if  (log.IsDebugEnabled)
                             {
                                 if  ( this .invokeInfo.UseTime.TotalMilliseconds > MaxRunningMilliseconds)
                                     log.Debug( this .invokeInfo.ToString());
                             }
                         }
                         break ;
 
                     case  SoapMessageStage.AfterSerialize:
                         break ;
 
                     default :
                         throw  new  Exception( "No stage such as this" );
                 }
 
             }
         }
 
 
     }
 
     public  class  WSInvokeInfo
     {
         public  WSInvokeInfo()
         {
             Id = Guid.NewGuid();
         }
         public  Guid Id { get ; private  set ; }
         public  DateTime BeginInvokeTime { get ; set ; }
 
         public  string  MethodName { get ; set ; }
 
         public  string  UserHostAddress { get ; set ; }
 
 
         public  DateTime? EndInvokeTime { get ; set ; }
 
         public  Dictionary< string , object > Args { get ; set ; }
 
         public  TimeSpan UseTime { get  { return  (EndInvokeTime.HasValue ? EndInvokeTime.Value : DateTime.Now) - BeginInvokeTime; } }
 
         public  static  string  GetString(ICollection val)
         {
             var  ret = new  List< string >();
             var  iter = val.GetEnumerator();
             while  (iter.MoveNext())
             {
                 if  (iter.Current is  ICollection)
                     ret.Add(GetString((ICollection)iter.Current));
                 else
                     ret.Add(iter.Current.ToString());
             }
 
             return  string .Concat( "[" , string .Join( ", " , ret.ToArray()), "]" );
         }
 
 
         public  override  string  ToString()
         {
             return  string .Format( "Host:{0},  UseTime:{1}, Time:{2}, name:{3},Arg:{4}" ,
                 this .UserHostAddress ?? "none" ,
                 this .UseTime.TotalMilliseconds,
                 this .BeginInvokeTime,
                 this .MethodName ?? "unkown" ,
                 string .Join( ", " , this .Args.ToList().ConvertAll(d => string .Format( "{0}:={1}" , d.Key, d.Value == null  ? "null"  : (d.Value is  ICollection ? GetString((ICollection)d.Value) : d.Value.ToString()))).ToArray()));
         }
 
     }
 
     public  class  RemoteHostInfo
     {
         public  string  Host { get ; set ; }
 
         public  WSInvokeInfo[] LastInvoke { get ; set ; }
     }
 
}

  

查看页面:

<%@ WebHandler Language= "C#"  Class= "SoapUtil.ServerStat"  %>
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Web;
using  OA4.CommonLib.Soap;
 
namespace  SoapUtil
{
     /// <summary>
     /// Alive 的摘要说明
     /// </summary>
     public  class  ServerStat : IHttpHandler
     {
 
         public  void  ProcessRequest(HttpContext context)
         {
             context.Response.ContentType = "text/plain" ;
             var  resp = context.Response;
             try
             {
                 var  running = TimeWatchExtension.Running.ToList();
 
                 resp.Write( string .Format( "当前运行:{0}\n{1}" ,
                                         running.Count,
                                         string .Join( "\n" , running.ConvertAll(d =>
                                         {
                                             var  ret = "exception" ;
 
                                             try  { ret = d.Value.ToString(); }
                                             catch  (Exception ex)
                                             {
                                                 ret = string .Concat(ret, "," , d.Value.MethodName, "," , d.Value.UserHostAddress, "," , d.Value.BeginInvokeTime.ToString());
                                             }
                                             return  ret;
                                         }).ToArray())
                                         )
                            );
 
                 var  last = TimeWatchExtension.LastInvoke.ToList();
                 {
                     var  strInfo = "" ;
                     if  (last.Count > 1)
                     {
                         var  f = last.First();
                         TimeSpan ts = DateTime.Now - f.BeginInvokeTime;
                         var  speed = last.Count / ts.TotalSeconds;
                         var  avgUseTime = last.Average(d => d.UseTime.Milliseconds);
 
 
                         strInfo = string .Format( "{0:0.0} (Call/S), {1:0.0} (MS/Call)" , speed, avgUseTime);
                     }
                     else
                     {
 
                     }
                     resp.Write( string .Format( "\n最后记录:{0},\t{1}\n{2}" ,
                                            last.Count,
                                            strInfo,
                                            string .Join( "\n" , last.ConvertAll(d =>
                                            {
                                                var  ret = "exception" ;
 
                                                try  { ret = d.ToString(); }
                                                catch  (Exception ex)
                                                {
                                                    ret = string .Concat(ret, "," , d.MethodName, "," , d.UserHostAddress, "," , d.BeginInvokeTime.ToString());
                                                }
                                                return  ret;
                                            }).ToArray())
                                            )
                               );
                 }
 
                 resp.Write( "\n" );
                 var  userHost = TimeWatchExtension.RemoteUserHost;
                 Array.ForEach(userHost, info =>
                     {
                         var  invoke = info.LastInvoke.ToList();
                         if  (invoke.Count > 1)
                         {
                             var  f = invoke.First();
 
                             TimeSpan ts = DateTime.Now - f.BeginInvokeTime;
                             var  speed = invoke.Count / ts.TotalSeconds;
                             var  avgUseTime = invoke.Average(d => d.UseTime.Milliseconds);
 
 
                             var  strInfo = string .Format( "{0:0.0} (Call/S), {1:0.0} (MS/Call)" , speed, avgUseTime);
                             resp.Write( "\n\n"  + info.Host + "["  + strInfo + "]:" );
                         }
                         else
                         {
                             resp.Write( "\n\n"  + info.Host + ":" );
                         }
                         resp.Write( string .Format( "\n最后记录:{0}\n{1}" ,
                                       invoke.Count,
                                       string .Join( "\n" , invoke.ConvertAll(d =>
                                       {
                                           var  ret = "exception" ;
 
                                           try  { ret = d.ToString(); }
                                           catch  (Exception ex)
                                           {
                                               ret = string .Concat(ret, "," , d.MethodName, "," , d.UserHostAddress, "," , d.BeginInvokeTime.ToString());
                                           }
                                           return  ret;
                                       }).ToArray())
                                       )
                          );
                     });
 
             }
             catch  (Exception ex)
             {
                 context.Response.Write( string .Format( "ERROR:{0}" ,ex.Message));
             }
         }
 
         public  bool  IsReusable
         {
             get
             {
                 return  false ;
             }
         }
     }
}
相关文章

相关标签/搜索