在上一篇文章中,我们在一个请求中执行了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();
}