預設coreprofiler使用記憶體存放200筆資料,如果你想要關閉監控功能,只需把circularBufferSize設定0即可,
由於記憶體資源不太可能都讓coreprofiler獨佔,所以我們必須將這些效能監控資料存放至SQL Server,
方便後續讓我們進行效能分析。
查看source code,我們知道InitializeConfigurationFromConfig() method,會從coreprofiler.json讀取設定。
https://github.com/teddymacn/CoreProfiler/blob/master/CoreProfiler/ProfilingSession.cs#L256
CoreProfilerMiddleware.cs這支讓我們知道,coreProfiler是透過middleware來呈現監控資料View(透過StringBuilder組html tag)。
https://github.com/teddymacn/CoreProfiler/blob/master/CoreProfiler.Web/CoreProfilerMiddleware.cs
大致看了source code後,看來所有profiler的資料都能新增到資料庫中的CoreProfiler資料表,
但我不想改現有controller中所有action的code,如下圖,
我原先都埋好每個階段的profiler,當然,你也可以每個階段接Timing物件,
處理Mapping後新增至SQL Server
像這種Infrastructure的處理,我比較喜歡統一底層來handle,開發人員不用額外判斷該相關功能是否有啟用,
一來不會破壞現有的code,二來也不會和現有business邏輯參雜一起變瀨尿牛丸。
所以我打算透過ResultFilter來實現,相關code如下
@add a new module
[Serializable]
[Table("CoreProfiler")]
public class CoreProfilerModulecs
{
[Key]
[Write(false)]
public long Serial { get; set; }
public string SessionId { get; set; }
public string ParentId { get; set; }
public string Machine { get; set; }
public string Type { get; set; }
public string CurrentId { get; set; }
public string Name { get; set; }
public Int64 Start { get; set; }
public Int64 Duration { get; set; }
public Int64 Sort { get; set; }
public DateTime Started { get; set; }
}
@add a new CoreProfilerResultFilter.cs (透過DI注入對應的Logger和Repository),
我這裡繼承非同步ResultFilter,這樣才不會影響server回應client時間
public class CoreProfilerResultFilter : Attribute, IAsyncResultFilter
{
private readonly ILogger<CoreProfilerResultFilter> _logger;
private readonly ICoreProfilerRepository _coreProfilerRepository;
public CoreProfilerResultFilter(ILogger<CoreProfilerResultFilter> logger, ICoreProfilerRepository coreProfilerRepository)
{
_logger = logger;
_coreProfilerRepository = coreProfilerRepository;
}
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
await next(); //after the action executes;
var timingSession = ProfilingSession.Current.Profiler.GetTimingSession();
if (timingSession != null)
{
string sessionId = timingSession.Id.ToString();
List<CoreProfilerModulecs> coreProfilerModulecs = new List<CoreProfilerModulecs>();
foreach (var timing in timingSession.Timings)
{
long duration = 0;
if (timing.Name.ToLowerInvariant() == "root" && timing.DurationMilliseconds <= 0)
duration = timingSession.DurationMilliseconds;
coreProfilerModulecs.Add(new CoreProfilerModulecs
{
SessionId = sessionId,
ParentId = timing.ParentId.HasValue ? timing.ParentId.Value.ToString() : "",
Machine = timingSession.MachineName,
Type = timing.Type,
CurrentId = timing.Id.ToString(),
Name = timing.Name,
Start = timing.StartMilliseconds,
Duration = duration > 0 ? duration : timing.DurationMilliseconds,
Sort = timing.Sort,
Started = timing.Started
});
}
await _coreProfilerRepository.BulkInsertAsync(coreProfilerModulecs);
}
}
}
Note:我這裡沒有處理Timing.Data物件資料,另外root的duration我使用session的duration。
@startup.cs統一設定
結果比對
SQL Server
View
參考