From 3382627c8c33b3df4a611ee796ba4bd2866b6529 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Mon, 25 Mar 2024 17:39:44 +0800 Subject: [PATCH] =?UTF-8?q?GUI=20=E5=95=9F=E5=8B=95=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CoreProfilerExample.Common.csproj | 4 + .../Extensions/MethodBaseExtension.cs | 39 ++++++ .../Options/CoreProfilerOption.cs | 61 +++++++++ .../Options/CoreProfilerOptionFilter.cs | 14 ++ .../Implements/WeatherForecastRepository.cs | 17 ++- .../Extensions/MapperExtension.cs | 5 - .../Implements/WeatherService.cs | 23 ++-- .../Models/Dtos/GetWeatherForecastDto.cs | 8 +- .../Models/Dtos/GetWeatherForecastItemDto.cs | 8 +- .../GetWeatherForecastParameterDto.cs | 8 +- CoreProfilerExample.sln | 5 + .../Controllers/WeatherController.cs | 17 ++- .../CoreProfilerExample.csproj | 1 + .../DependencyInjectionExtension.cs | 13 +- CoreProfilerExample/Program.cs | 4 + .../LastestProfilingResult.JPG | Bin 0 -> 22452 bytes .../LastestProfilingResultDetail.JPG | Bin 0 -> 34522 bytes README.md | 120 +++++++++++++++++- 18 files changed, 299 insertions(+), 48 deletions(-) create mode 100644 CoreProfilerExample.Common/Extensions/MethodBaseExtension.cs create mode 100644 CoreProfilerExample.Common/Options/CoreProfilerOption.cs create mode 100644 CoreProfilerExample.Common/Options/CoreProfilerOptionFilter.cs create mode 100644 CoreProfilerExampleResource/LastestProfilingResult.JPG create mode 100644 CoreProfilerExampleResource/LastestProfilingResultDetail.JPG diff --git a/CoreProfilerExample.Common/CoreProfilerExample.Common.csproj b/CoreProfilerExample.Common/CoreProfilerExample.Common.csproj index fa71b7a..04296cf 100644 --- a/CoreProfilerExample.Common/CoreProfilerExample.Common.csproj +++ b/CoreProfilerExample.Common/CoreProfilerExample.Common.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/CoreProfilerExample.Common/Extensions/MethodBaseExtension.cs b/CoreProfilerExample.Common/Extensions/MethodBaseExtension.cs new file mode 100644 index 0000000..6cc4101 --- /dev/null +++ b/CoreProfilerExample.Common/Extensions/MethodBaseExtension.cs @@ -0,0 +1,39 @@ +using CoreProfiler; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace CoreProfilerExample.Common.Extensions +{ + public static class MethodBaseExtension + { + 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(), + }) + .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); + } + } +} diff --git a/CoreProfilerExample.Common/Options/CoreProfilerOption.cs b/CoreProfilerExample.Common/Options/CoreProfilerOption.cs new file mode 100644 index 0000000..8ad4cfd --- /dev/null +++ b/CoreProfilerExample.Common/Options/CoreProfilerOption.cs @@ -0,0 +1,61 @@ +using Newtonsoft.Json; + +namespace CoreProfilerExample.Common.Options +{ + public class CoreProfilerOption + { + /// + /// 資料保存上限(Session)。 + /// + [JsonProperty("circularBufferSize")] + public int CircularBufferSize { get; set; } = 200; + /// + /// 要過濾掉的項目。 + /// + [JsonProperty("filters")] + public IEnumerable Filters { get; set; } = [ + new CoreProfilerOptionFilter + { + Key = "/coreprofiler", + Value = "/coreprofiler", + Type = "CoreProfiler.ProfilingFilters.NameContainsProfilingFilter, CoreProfiler", + }, + new CoreProfilerOptionFilter + { + Key = "static files", + Value = "ico,jpg,js,css,svg,json,ttf,woff,woff2,eot", + Type = "CoreProfiler.ProfilingFilters.FileExtensionProfilingFilter, CoreProfiler", + }, + ]; + + public CoreProfilerOption Save(string filename) + { + var json = JsonConvert.SerializeObject(this, Formatting.Indented); + + File.WriteAllText(filename, json); + + return this; + } + + public static CoreProfilerOption UseCoreProfilerSetting() + { + var filename = Path.Combine(AppContext.BaseDirectory, "coreprofiler.json"); + + if (File.Exists(filename)) + { + try + { + var json = File.ReadAllText(filename); + + return JsonConvert.DeserializeObject(json); + } + catch + { + + } + } + + return new CoreProfilerOption().Save(filename); + } + } +} diff --git a/CoreProfilerExample.Common/Options/CoreProfilerOptionFilter.cs b/CoreProfilerExample.Common/Options/CoreProfilerOptionFilter.cs new file mode 100644 index 0000000..48b2bc4 --- /dev/null +++ b/CoreProfilerExample.Common/Options/CoreProfilerOptionFilter.cs @@ -0,0 +1,14 @@ +using Newtonsoft.Json; + +namespace CoreProfilerExample.Common.Options +{ + public class CoreProfilerOptionFilter + { + [JsonProperty("key")] + public string Key { get; set; } = null!; + [JsonProperty("value")] + public string Value { get; set; } = null!; + [JsonProperty("type")] + public string Type { get; set; } = null!; + } +} diff --git a/CoreProfilerExample.Repository/Implements/WeatherForecastRepository.cs b/CoreProfilerExample.Repository/Implements/WeatherForecastRepository.cs index 65d929d..494fb17 100644 --- a/CoreProfilerExample.Repository/Implements/WeatherForecastRepository.cs +++ b/CoreProfilerExample.Repository/Implements/WeatherForecastRepository.cs @@ -1,5 +1,7 @@ -using CoreProfilerExample.Repository.Interfaces; +using CoreProfilerExample.Common.Extensions; +using CoreProfilerExample.Repository.Interfaces; using CoreProfilerExample.Repository.Models.DataModels; +using System.Reflection; using static CoreProfilerExample.Common.Constants.WeatherConstant; namespace CoreProfilerExample.Repository.Implements @@ -8,12 +10,15 @@ namespace CoreProfilerExample.Repository.Implements { public Task> GetAsync(int days) { - return Task.Run(() => days > 0 ? Enumerable.Range(1, days).Select(index => new WeatherForecastDataModel + using (MethodBase.GetCurrentMethod()?.ProfilingStep()) { - Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = WeatherSummaries[Random.Shared.Next(WeatherSummaries.Length)] - }) : []); + return Task.Run(() => days > 0 ? Enumerable.Range(1, days).Select(index => new WeatherForecastDataModel + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = WeatherSummaries[Random.Shared.Next(WeatherSummaries.Length)] + }) : []); + } } } } diff --git a/CoreProfilerExample.Service/Extensions/MapperExtension.cs b/CoreProfilerExample.Service/Extensions/MapperExtension.cs index b597b76..9db7a1a 100644 --- a/CoreProfilerExample.Service/Extensions/MapperExtension.cs +++ b/CoreProfilerExample.Service/Extensions/MapperExtension.cs @@ -1,10 +1,5 @@ using CoreProfilerExample.Repository.Models.DataModels; using CoreProfilerExample.Service.Models.Dtos; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace CoreProfilerExample.Service.Extensions { diff --git a/CoreProfilerExample.Service/Implements/WeatherService.cs b/CoreProfilerExample.Service/Implements/WeatherService.cs index 46e5555..dc7d52c 100644 --- a/CoreProfilerExample.Service/Implements/WeatherService.cs +++ b/CoreProfilerExample.Service/Implements/WeatherService.cs @@ -1,21 +1,28 @@ -using CoreProfilerExample.Repository.Interfaces; +using CoreProfilerExample.Common.Extensions; +using CoreProfilerExample.Repository.Interfaces; using CoreProfilerExample.Service.Extensions; using CoreProfilerExample.Service.Interfaces; using CoreProfilerExample.Service.Models.Dtos; using CoreProfilerExample.Service.Models.ParameterDtos; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Reflection; namespace CoreProfilerExample.Service.Implements { - public class WeatherService(IWeatherForecastRepository weatherForecast) : IWeatherService + public class WeatherService : IWeatherService { + public WeatherService(IWeatherForecastRepository weatherForecast) + { + this.weatherForecast = weatherForecast; + } + + private readonly IWeatherForecastRepository weatherForecast = null!; + public Task GetWeatherForecastAsync(GetWeatherForecastParameterDto parameterDto) { - return weatherForecast.GetAsync(parameterDto.ForecastDays).ToDtoAsync(); + using (MethodBase.GetCurrentMethod()?.ProfilingStep()) + { + return weatherForecast.GetAsync(parameterDto.ForecastDays).ToDtoAsync(); + } } } } diff --git a/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastDto.cs b/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastDto.cs index 1ed21fb..452b529 100644 --- a/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastDto.cs +++ b/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastDto.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CoreProfilerExample.Service.Models.Dtos +namespace CoreProfilerExample.Service.Models.Dtos { public class GetWeatherForecastDto { diff --git a/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastItemDto.cs b/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastItemDto.cs index 79a36b7..0565875 100644 --- a/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastItemDto.cs +++ b/CoreProfilerExample.Service/Models/Dtos/GetWeatherForecastItemDto.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CoreProfilerExample.Service.Models.Dtos +namespace CoreProfilerExample.Service.Models.Dtos { public class GetWeatherForecastItemDto { diff --git a/CoreProfilerExample.Service/Models/ParameterDtos/GetWeatherForecastParameterDto.cs b/CoreProfilerExample.Service/Models/ParameterDtos/GetWeatherForecastParameterDto.cs index 15e89b0..6a90bf2 100644 --- a/CoreProfilerExample.Service/Models/ParameterDtos/GetWeatherForecastParameterDto.cs +++ b/CoreProfilerExample.Service/Models/ParameterDtos/GetWeatherForecastParameterDto.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CoreProfilerExample.Service.Models.ParameterDtos +namespace CoreProfilerExample.Service.Models.ParameterDtos { public class GetWeatherForecastParameterDto { diff --git a/CoreProfilerExample.sln b/CoreProfilerExample.sln index 75a48a1..96579f7 100644 --- a/CoreProfilerExample.sln +++ b/CoreProfilerExample.sln @@ -11,6 +11,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreProfilerExample.Service EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreProfilerExample.Common", "CoreProfilerExample.Common\CoreProfilerExample.Common.csproj", "{DDD6FCC3-454E-42CB-94D0-23A7EA57D039}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "方案項目", "方案項目", "{5C1FF8FA-0F30-4581-8173-320356AFD2CC}" + ProjectSection(SolutionItems) = preProject + README.md = README.md + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/CoreProfilerExample/Controllers/WeatherController.cs b/CoreProfilerExample/Controllers/WeatherController.cs index db44914..8ad5c66 100644 --- a/CoreProfilerExample/Controllers/WeatherController.cs +++ b/CoreProfilerExample/Controllers/WeatherController.cs @@ -1,9 +1,11 @@ +using CoreProfilerExample.Common.Extensions; using CoreProfilerExample.Infrastructure.Extensions; using CoreProfilerExample.Models.Parameters; using CoreProfilerExample.Models.ViewModels; using CoreProfilerExample.Service.Interfaces; using Microsoft.AspNetCore.Mvc; using System.Net; +using System.Reflection; namespace CoreProfilerExample.Controllers { @@ -17,13 +19,16 @@ namespace CoreProfilerExample.Controllers [ProducesResponseType(typeof(ExceptionViewModel), (int)HttpStatusCode.BadRequest)] public async Task GetWeatherForecastAsync(GetWeatherForecastParameter parameter) { - try + using (MethodBase.GetCurrentMethod()?.ProfilingStep()) { - return Ok(await weather.GetWeatherForecastAsync(parameter.ToDto()).ToViewModel()); - } - catch (Exception ex) - { - return BadRequest(ex.ToViewModel()); + try + { + return Ok(await weather.GetWeatherForecastAsync(parameter.ToDto()).ToViewModel()); + } + catch (Exception ex) + { + return BadRequest(ex.ToViewModel()); + } } } } diff --git a/CoreProfilerExample/CoreProfilerExample.csproj b/CoreProfilerExample/CoreProfilerExample.csproj index 0b8764a..7118ec8 100644 --- a/CoreProfilerExample/CoreProfilerExample.csproj +++ b/CoreProfilerExample/CoreProfilerExample.csproj @@ -7,6 +7,7 @@ + diff --git a/CoreProfilerExample/Infrastructure/Extensions/DependencyInjectionExtension.cs b/CoreProfilerExample/Infrastructure/Extensions/DependencyInjectionExtension.cs index cf85aed..b8eda56 100644 --- a/CoreProfilerExample/Infrastructure/Extensions/DependencyInjectionExtension.cs +++ b/CoreProfilerExample/Infrastructure/Extensions/DependencyInjectionExtension.cs @@ -1,4 +1,6 @@ -using CoreProfilerExample.Repository.Implements; +using CoreProfiler.Web; +using CoreProfilerExample.Common.Options; +using CoreProfilerExample.Repository.Implements; using CoreProfilerExample.Repository.Interfaces; using CoreProfilerExample.Service.Implements; using CoreProfilerExample.Service.Interfaces; @@ -18,5 +20,14 @@ namespace CoreProfilerExample.Infrastructure.Extensions services.AddScoped(); return services; } + + public static IApplicationBuilder UseCoreProfiler(this IApplicationBuilder app) + { + CoreProfilerOption.UseCoreProfilerSetting(); + + app.UseCoreProfiler(true); + + return app; + } } } diff --git a/CoreProfilerExample/Program.cs b/CoreProfilerExample/Program.cs index c03b524..f7e249a 100644 --- a/CoreProfilerExample/Program.cs +++ b/CoreProfilerExample/Program.cs @@ -22,4 +22,8 @@ app.UseAuthorization(); app.MapControllers(); +#region CoreProfilerExample +app.UseCoreProfiler(); +#endregion + app.Run(); diff --git a/CoreProfilerExampleResource/LastestProfilingResult.JPG b/CoreProfilerExampleResource/LastestProfilingResult.JPG new file mode 100644 index 0000000000000000000000000000000000000000..6d5ccb8331e47949cfa7ee24aac2bbbe75b24095 GIT binary patch literal 22452 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 literal 0 HcmV?d00001 diff --git a/CoreProfilerExampleResource/LastestProfilingResultDetail.JPG b/CoreProfilerExampleResource/LastestProfilingResultDetail.JPG new file mode 100644 index 0000000000000000000000000000000000000000..a920d5500cf194f5df3527accc4bd041e3ce24e1 GIT binary patch literal 34522 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 F{xAIYVL|`^ literal 0 HcmV?d00001 diff --git a/README.md b/README.md index b9d1bd3..7de1725 100644 --- a/README.md +++ b/README.md @@ -1 +1,119 @@ -# CoreProfilerExample \ No newline at end of file +## CoreProfiler + +```Shell +NUGET INSTALL coreprofiler -Version 1.1.4 +``` + +ΩSw϶ӮɡC + +򥻤kpU: + +```C# +var stepName = $"{class_name}.{method_name}"; + +using (ProfilingSession.Current.Step(stepName)) +{ + // ݭnpɪ{Xq +} +``` + +ѩjOϥάۦPҫA]dҤѤ@XRkAzLϮgoOPkW١C + +```C# +// ./CoreProfilerExample.Common/Extensions/MethodBaseExtension.cs + +public static IDisposable ProfilingStep(this MethodBase method, string? stepName = null) +{ + if (stepName == null) + { + // ok + var methodType = method.ReflectedType; + + // oO + var classType = methodType?.ReflectedType ?? methodType; + + // XOUҦDPBkAXek + var classMethodType = classType? + .GetMethods() + .Select(x => new + { + Method = x, + Attribute = x.GetCustomAttribute(), + }) + .FirstOrDefault(x => x.Attribute?.StateMachineType == methodType); + + var className = classType?.Name ?? "LkoOW"; + + var methodName = classMethodType?.Method.Name ?? method.Name ?? "LkokW"; + + stepName = $"{classType?.Name}.{methodName}"; + } + + return ProfilingSession.Current.Step(stepName); +} +``` + +XR MethodBase OA}o̥iHۦMwO_nJstepNameѼơAYSJh|zLϮg޳NoOPkW١A@Ӯɪ϶qW١C + +Ϯg: zLMethodBaseӨokTypeAAoOTypeA쥻o˴NiHϥNameӨoOPkW١AkYDPBAh|Xn\ŪW١A]ݭnAHUާ@Өo\ŪW: + +```C# +var classMethodType = classType? + .GetMethods() + .Select(x => new + { + Method = x, + Attribute = x.GetCustomAttribute(), + }) + .Where(x => x.Attribute?.StateMachineType == methodType) + .FirstOrDefault(); +``` + +QOTypeo䩳UҦkAAzLkType覡okMethodInfoANiHϥNameӨoŪkW٤FC + +XRk򥻨ϥΤkpU: + +```C# +using (MethodBase.GetCurrentMethod()?.ProfilingStep()) +{ + // ݭnpɪ{Xq +} + +using (MethodBase.GetCurrentMethod()?.ProfilingStep("qW")) +{ + // ݭnpɪ{Xq +} +``` + +## CoreProfiler.Web + +```Shell +NUGET INSTALL CoreProfiler.Web -Version 1.1.4 +``` + +NCӶqnlܪ{X]˦nAAӦwˤKdApU: + +```C# +// ./CoreProfilerExample/Infrastructure/Extensions/DependencyInjectionExtension.cs + +public static IApplicationBuilder UseCoreProfiler(this IApplicationBuilder app) +{ + CoreProfilerOption.UseCoreProfilerSetting(); + + app.UseCoreProfiler(true); + + return app; +} +``` + +ϥCoreProfilerOption.UseCoreProfilerSetting()kӲGUIһݪ]wѼƫAϥapp.UseCoreProfiler(true)`Jε{AѼtrueܨC@ӬqO_nUdO_LqC + +Ұʫs /nanoprofiler/view T{O_ҥΦ\C + +pU: + +![LastestProfilingResult](CoreProfilerExampleResource/LastestProfilingResult.JPG) + +ԲӦpU: + +![LastestProfilingResultDetail](CoreProfilerExampleResource/LastestProfilingResultDetail.JPG) \ No newline at end of file