[英]ASP.Net MVC AsyncController log request processing time
我需要獲得asp.net MVC的請求處理時間。 我使用IHttpModule訂閱onBeginRequest和onEndRequest事件。 對於同步控制器,它工作得很好但是對於異步它會返回錯誤的結果(例如,當實時約為2分鍾時為20ms)。 如何以一般方式獲取AsyncController的請求處理時間(不為每個異步操作在ActionAsync / ActionCompleted中編寫附加代碼)?
public class TrackRequestModule : RequestProcessingModuleBase, IHttpModule
{
public const string BeginRequestTimeKey = "beginRequestTime";
public void Init(HttpApplication context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
context.BeginRequest += onBeginRequest;
context.EndRequest += onEndRequest;
}
private void onEndRequest(object sender, EventArgs e)
{
InvokeHandler(sender, OnEndRequest);
}
private void onBeginRequest(object sender, EventArgs e)
{
InvokeHandler(sender, OnBeginRequest);
}
public void OnBeginRequest(HttpContextBase context)
{
context.Items[BeginRequestTimeKey] = DateTime.Now.ToLocalTime();
}
public void OnEndRequest(HttpContextBase context)
{
var beginRequestTime = (DateTime)context.Items[BeginRequestTimeKey];
TimeSpan elapsedTime = DateTime.Now.ToLocalTime() - beginRequestTime;
var info = new RequestData
{
BeginTime = beginRequestTime,
ElapsedTimeMilliseconds = elapsedTime.Milliseconds,
Url = context.Request.Url.AbsoluteUri,
Data = GetRequestData(context.Request)
};
ThreadPool.QueueUserWorkItem(logRequestInfo, info);
}
public void Dispose() { }
private void logRequestInfo(object state)
{
var info = (RequestData)state;
var queryStore = ObjectBuilder.Instance.Resolve<IRequestTrackingDataQueryStore>();
queryStore.SaveRequestTrackingData(info.BeginTime, info.ElapsedTimeMilliseconds, info.Url, info.Data);
}
private sealed class RequestData
{
public DateTime BeginTime { get; set; }
public int ElapsedTimeMilliseconds { get; set; }
public string Url { get; set; }
public string Data { get; set; }
}
}
這很奇怪。 通常這種情況應該有效。 遺憾的是,您沒有顯示您的代碼,因此很難說您可能做錯了什么。
此外,我無法重現它。 這是我寫的測試模塊:
public class MeasureModule : IHttpModule
{
private static readonly ReaderWriterLockSlim _gateway = new ReaderWriterLockSlim();
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, e) =>
{
var app = (sender as HttpApplication);
var watch = Stopwatch.StartNew();
app.Context.Items["watch"] = watch;
};
context.EndRequest += (sender, e) =>
{
var app = (sender as HttpApplication);
var watch = app.Context.Items["watch"] as Stopwatch;
watch.Stop();
var url = app.Context.Request.Url.AbsoluteUri;
var message = string.Format("url: {0}, time: {1}ms", url, watch.ElapsedMilliseconds);
var log = HostingEnvironment.MapPath("~/log.txt");
_gateway.EnterWriteLock();
try
{
File.AppendAllLines(log, new[] { message });
}
finally
{
_gateway.ExitWriteLock();
}
};
}
}
我在web.config中注冊了(我在Cassini下測試過,如果你打算使用IIS 7,你必須在相應的<system.webServer>
部分注冊模塊):
<httpModules>
<add name="measure" type="MvcApplication.Modules.MeasureModule, MvcApplication" />
</httpModules>
然后寫了一個樣本控制器來測試:
[SessionState(SessionStateBehavior.Disabled)]
public class HomeController : AsyncController
{
public ActionResult IndexSync()
{
Thread.Sleep(5000);
return Content("completed", "text/plain");
}
public void IndexAsync()
{
AsyncManager.OutstandingOperations.Increment();
Task.Factory.StartNew(() =>
{
Thread.Sleep(5000);
AsyncManager.OutstandingOperations.Decrement();
});
}
public ActionResult IndexCompleted()
{
return Content("completed", "text/plain");
}
}
然后我向以下網址發出了兩個並行HTTP請求:
/home/index
/home/indexsync
2個請求在大約5秒后按預期完成,並且日志文件看起來完全正常:
url: http://localhost:14953/home/index, time: 5047ms
url: http://localhost:14953/home/indexsync, time: 5005ms
如您所見,HTTP模塊正確地測量了異步和同步操作的執行時間。
什么給出了什么?
順便說一句,您可以檢查MiniProfiler並確保您的方案沒有輪盤重新設置。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.