如何将基准测试记录到 MVC 控制器中的 CSV 文件中?
How can I log benchmark tests to CSV file in MVC controllers?
我有一个 ASP.NET 核心应用程序,其中包含继承自 BaseController
的各种控制器。我需要实施一些基本的基准测试,使用秒表,它只会在动作方法的开头开始并在结尾结束。我可以通过 appsettings.json
打开和关闭它。 Startup.cs
有一个ILogger
工厂:
public void Configure ( IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory ) {
loggerFactory.AddConsole( Configuration.GetSection( "Logging" ) );
loggerFactory.AddDebug();
loggerFactory.AddFile(@"C:\Logs\Portal\portal-{Date}.txt");
我已将 ILogger
添加到我的 BaseController
(下),我希望这将通过 DI 提供。鉴于上述情况,我可以使用它来记录我的基准测试结果,并将其归档到与启动文件不同的位置吗?我想要一个包含某些列的 .csv
文件,我可以用结果填充这些列。这可能吗?
public class BaseController : Controller {
protected AppSettings AppSettings;
protected IMapper Mapper;
protected IPortalApiService PortalApiService;
protected ILogger Logger;
protected UserManager<ApplicationUser> UserManager;
private static Stopwatch _stopWatch = new Stopwatch();
private static long _seconds;
public BaseController ( IMapper mapper,
IOptions<AppSettings> appSettings,
UserManager<ApplicationUser> userManager,
IPortalApiService PortalApiService,
ILogger logger) {
Mapper = mapper;
AppSettings = appSettings.Value;
UserManager = userManager;
PortalApiService = PortalApiService;
Logger = logger;
}
public BaseController ( IMapper mapper,
IOptions<AppSettings> appSettings,
UserManager<ApplicationUser> userManager,
ILogger logger) {
Mapper = mapper;
AppSettings = appSettings.Value;
UserManager = userManager;
Logger = logger;
}
protected Task<ApplicationUser> GetCurrentUserAsync () {
return UserManager.GetUserAsync( HttpContext.User );
}
public void StartBenchmark()
{
if (AppSettings.EnableBenchmarkLogging)
{
_stopWatch = Stopwatch.StartNew();
}
}
public void EndBenchmark()
{
if (_stopWatch.IsRunning)
{
_stopWatch.Stop();
_seconds = _stopWatch.ElapsedMilliseconds;
//logging to do
}
}
}
是not a good idea to use a BaseController
in MVC. There are better ways to implement crosscutting concerns. In this particular case, you could use a global filter。
public class BenchmarkFilter : IActionFilter
{
private readonly ILogger Logger;
// DON'T DECLARE STATIC!!
private Stopwatch _stopWatch = new Stopwatch();
public BenchmarkFilter(ILogger logger)
{
_logger = logger ??
throw new ArgumentNullException(nameof(logger));
}
public void OnActionExecuting(ActionExecutingContext context)
{
_stopWatch = Stopwatch.StartNew();
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (_stopWatch.IsRunning)
{
_stopWatch.Stop();
var seconds = _stopWatch.ElapsedMilliseconds;
//logging to do
}
}
}
这允许您通过构造函数通过 DI 注入服务 ,而不必将这些参数添加到子类化公共 BaseController
的每个控制器,将基准测试的关注点分开完全来自控制器。
用法
在Startup.cs
中,在ConfigureServices
方法中添加过滤器。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Filters.Add(typeof(BenchmarkFilter)); // runs on every action method call
});
services.AddScoped<BenchmarkFilter>();
// ....
}
我有一个 ASP.NET 核心应用程序,其中包含继承自 BaseController
的各种控制器。我需要实施一些基本的基准测试,使用秒表,它只会在动作方法的开头开始并在结尾结束。我可以通过 appsettings.json
打开和关闭它。 Startup.cs
有一个ILogger
工厂:
public void Configure ( IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory ) {
loggerFactory.AddConsole( Configuration.GetSection( "Logging" ) );
loggerFactory.AddDebug();
loggerFactory.AddFile(@"C:\Logs\Portal\portal-{Date}.txt");
我已将 ILogger
添加到我的 BaseController
(下),我希望这将通过 DI 提供。鉴于上述情况,我可以使用它来记录我的基准测试结果,并将其归档到与启动文件不同的位置吗?我想要一个包含某些列的 .csv
文件,我可以用结果填充这些列。这可能吗?
public class BaseController : Controller {
protected AppSettings AppSettings;
protected IMapper Mapper;
protected IPortalApiService PortalApiService;
protected ILogger Logger;
protected UserManager<ApplicationUser> UserManager;
private static Stopwatch _stopWatch = new Stopwatch();
private static long _seconds;
public BaseController ( IMapper mapper,
IOptions<AppSettings> appSettings,
UserManager<ApplicationUser> userManager,
IPortalApiService PortalApiService,
ILogger logger) {
Mapper = mapper;
AppSettings = appSettings.Value;
UserManager = userManager;
PortalApiService = PortalApiService;
Logger = logger;
}
public BaseController ( IMapper mapper,
IOptions<AppSettings> appSettings,
UserManager<ApplicationUser> userManager,
ILogger logger) {
Mapper = mapper;
AppSettings = appSettings.Value;
UserManager = userManager;
Logger = logger;
}
protected Task<ApplicationUser> GetCurrentUserAsync () {
return UserManager.GetUserAsync( HttpContext.User );
}
public void StartBenchmark()
{
if (AppSettings.EnableBenchmarkLogging)
{
_stopWatch = Stopwatch.StartNew();
}
}
public void EndBenchmark()
{
if (_stopWatch.IsRunning)
{
_stopWatch.Stop();
_seconds = _stopWatch.ElapsedMilliseconds;
//logging to do
}
}
}
是not a good idea to use a BaseController
in MVC. There are better ways to implement crosscutting concerns. In this particular case, you could use a global filter。
public class BenchmarkFilter : IActionFilter
{
private readonly ILogger Logger;
// DON'T DECLARE STATIC!!
private Stopwatch _stopWatch = new Stopwatch();
public BenchmarkFilter(ILogger logger)
{
_logger = logger ??
throw new ArgumentNullException(nameof(logger));
}
public void OnActionExecuting(ActionExecutingContext context)
{
_stopWatch = Stopwatch.StartNew();
}
public void OnActionExecuted(ActionExecutedContext context)
{
if (_stopWatch.IsRunning)
{
_stopWatch.Stop();
var seconds = _stopWatch.ElapsedMilliseconds;
//logging to do
}
}
}
这允许您通过构造函数通过 DI 注入服务 ,而不必将这些参数添加到子类化公共 BaseController
的每个控制器,将基准测试的关注点分开完全来自控制器。
用法
在Startup.cs
中,在ConfigureServices
方法中添加过滤器。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.Filters.Add(typeof(BenchmarkFilter)); // runs on every action method call
});
services.AddScoped<BenchmarkFilter>();
// ....
}