專案架構:Web 前端 + WebService 業務層 + 資料庫,三層分佈式部署。需求:統計每頁執行時間、WebService 呼叫方法與耗時。採用 HttpModule + SoapExtension 雙重攔截,零侵入業務代碼。
<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>
public class SimpleWSInvokeMonitorExtension : SoapExtension {
private const string WSInvokeMonitorKey = "__WSInvokeMonitorKey__";
private WSInvokeInfo invokeInfo = new WSInvokeInfo();
public override Stream ChainStream(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:
invokeInfo.BeginInvokeTime = DateTime.Now;
invokeInfo.MethodName = message.MethodInfo.Name; break;
case SoapMessageStage.AfterDeserialize:
invokeInfo.EndInvokeTime = DateTime.Now;
var pageInfo = (PageInfo)HttpContext.Current.Items[WSInvokeMonitorKey];
if (pageInfo != null) pageInfo.AppendInvokeInfo(invokeInfo); break;
}
} else if (message is SoapServerMessage) { /* 伺服端略 */ }
}
}
於 BeginRequest、PreRequestHandlerExecute、PreSendRequestContent、EndRequest 等事件收集頁面層級資訊,最後由 Log4Net 寫入日誌。達成開關配置即啟用/停用,無需重新編譯部署。