系统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;
}
}
}
}