1
0
Files
CoreProfilerExample/README.md
2024-03-25 18:18:41 +08:00

139 lines
4.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## CoreProfiler
```Shell
NUGET INSTALL coreprofiler -Version 1.1.4
```
用於紀錄特定區塊內的執行耗時。
基本手法如下:
```C#
var stepName = $"{class_name}.{method_name}";
using (ProfilingSession.Current.Step(stepName))
{
// 需要計時的程式碼片段
}
```
由於大部分都是使用相同的紀錄模型,因次本範例內提供一個擴充方法,透過反射取得類別與方法名稱。
```C#
// ./CoreProfilerExample.Common/Extensions/MethodBaseExtension.cs
public static IDisposable ProfilingStep(this MethodBase method, string? stepName = null)
{
if (stepName == null)
{
// 取得方法的類型物件
var methodType = method.ReflectedType;
// 取得類別的類型物件
var classType = methodType?.ReflectedType ?? methodType;
// 取出類別底下所有非同步類型的方法,比對出當前的方法類型
var classMethodType = classType?
.GetMethods()
.Select(x => new
{
Method = x,
Attribute = x.GetCustomAttribute<AsyncStateMachineAttribute>(),
})
.FirstOrDefault(x => x.Attribute?.StateMachineType == methodType);
var className = classType?.Name ?? "無法取得類別名稱";
var methodName = classMethodType?.Method.Name ?? method.Name ?? "無法取得方法名稱";
stepName = $"{classType?.Name}.{methodName}";
}
return ProfilingSession.Current.Step(stepName);
}
```
擴充 MethodBase 類別,開發者可以自行決定是否要輸入<code>stepName</code>參數,若沒有輸入則會透過反射的技術取得類別與方法的名稱,作為紀錄耗時的區塊階段名稱。
反射的說明: 透過<code>MethodBase</code>來取得方法的<code>Type</code>物件,再取得類別的<code>Type</code>物件,原本這樣就可以使用<code>Name</code>來取得類別與方法的名稱,但方法若為非同步,則會取出不好閱讀的名稱,因次需要再執行以下操作來取得易於閱讀的名稱:
```C#
var classMethodType = classType?
.GetMethods()
.Select(x => new
{
Method = x,
Attribute = x.GetCustomAttribute<AsyncStateMachineAttribute>(),
})
.Where(x => x.Attribute?.StateMachineType == methodType)
.FirstOrDefault();
```
利用類別的<code>Type</code>取得其底下的所有方法,再透過比對方法<code>Type</code>的方式取得方法的<code>MethodInfo</code>,就可以使用<code>Name</code>來取得易讀的方法名稱了。
擴充方法的基本使用方法如下:
```C#
using (MethodBase.GetCurrentMethod()?.ProfilingStep())
{
// 需要計時的程式碼片段
}
using (MethodBase.GetCurrentMethod()?.ProfilingStep("階段名稱"))
{
// 需要計時的程式碼片段
}
```
## CoreProfiler.Web
```Shell
NUGET INSTALL CoreProfiler.Web -Version 1.1.4
```
將每個階段要追蹤的程式碼包裝好後,再來安裝方便查找紀錄的介面,如下:
```C#
// ./CoreProfilerExample/Infrastructure/Extensions/DependencyInjectionExtension.cs
public static IApplicationBuilder UseCoreProfiler(this IApplicationBuilder app)
{
CoreProfilerOption.UseCoreProfilerSetting();
app.UseCoreProfiler(true);
return app;
}
```
使用<code>CoreProfilerOption.UseCoreProfilerSetting()</code>方法來產生GUI所需的相關設定參數後使用<code>app.UseCoreProfiler(true)</code>注入應用程式,其參數<code>true</code>表示每一個紀錄片段是否要往下查找是否有其他的紀錄片段。
啟動後連結 <a>/nanoprofiler/view</a> 確認是否有啟用成功。
執行紀錄如下:
![LastestProfilingResult](CoreProfilerExampleResource/LastestProfilingResult.JPG)
紀錄的詳細如下:
![LastestProfilingResultDetail](CoreProfilerExampleResource/LastestProfilingResultDetail.JPG)
## CoreProfiler extends DB
CoreProfiler也可用於紀錄SQL執行將原本資料庫使用的<code>Connection</code>替換成CoreProfiler實作的<code>Connection</code>就可以紀錄執行的T-SQL指令。
替換方法如下:
```C#
var connectionString = configuration.GetConnectionString("SQLITE");
var dbProfiler = ProfilingSession.Current != null
? new DbProfiler(ProfilingSession.Current.Profiler)
: null;
return new ProfiledDbConnection(new SqliteConnection(connectionString), dbProfiler);
```
在替換之前先確認CoreProfiler是否有運行的實體才替換資料庫連線執行結果如下:
![LastestProfilingResultDetailForDB](CoreProfilerExampleResource/LastestProfilingResultDetailForDB.JPG)