在上一篇文章中,我們在一個請求中執行了IronPython代碼,通過這個方法我們可以輕松地的檢查系 統運行的狀態,或對系統進行一些簡單修改。但是這種做法只能檢查系統在當前時刻的狀態,在很多情況 下,我們需要對系統的請求進行一段時間的采樣。對於簡單的數據(例如每秒執行的請求數量,請求時間 ),我們可以通過查看Performance Monitor中相關的計數器來獲得一些概要的數據。但是,如果我們需 要獲取一些系統的詳細狀態,甚至是需要根據需要進行動態改變的自定義需求,則勢必要深入到系統內部 進行數據采集。因此,我們可能需要讓代碼執行“一段時間”,並將直接結果進行匯總輸出。
讓代碼執行一段時間不難,簡單地使用Thread.Sleep便可,也不會造成什麼性能或吞吐量上的損失。 關鍵就在於,在代碼停留的這“一段時間”內,我們使用什麼樣的做法來采集數據。這時候,老趙腦海中 立即浮現出的便是HttpModule般監聽請求管道(Pipeline)中的各式事件。於是立馬寫出以下的代碼(在 前文的示例基礎上進行修改):
protected void btnExecute_Click(object sender, EventArgs e)
{
ScriptEngine engine = Python.CreateEngine();
var scope = engine.CreateScope ();
var script = engine.CreateScriptSourceFromString(
this.txtCode.Text, SourceCodeKind.Statements);
script.Execute(scope);
TextWriter writer = new StringWriter();
scope.SetVariable("logger", writer);
Action<HttpContext> traceRequest;
if (scope.TryGetVariable<Action<HttpContext>>("traceRequest", out traceRequest))
{
Action endTraceRequests;
scope.TryGetVariable<Action>("endTraceRequests", out endTraceRequests);
int waitTime;
if (!scope.TryGetVariable<int>("waitTime", out waitTime))
{
waitTime = 10000;
}
this.TraceRequests(traceRequest, waitTime, endTraceRequests);
}
this.txtOutput.Text = writer.ToString();
}
private void TraceRequests (Action<HttpContext> traceRequest, int waitTime, Action endTraceRequests)
{
EventHandler handler = (sender, e) =>
{
try
{
traceRequest((sender as HttpApplication).Context);
}
catch { }
};
this.Context.ApplicationInstance.BeginRequest += handler;
Thread.Sleep(waitTime);
this.Context.ApplicationInstance.BeginRequest -= handler;
if (endTraceRequests != null) endTraceRequests();
}