diff --git a/EasyProfiler.sln b/EasyProfiler.sln index d211f61..b5a0d1e 100644 --- a/EasyProfiler.sln +++ b/EasyProfiler.sln @@ -7,8 +7,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9AE5BFB8-BA7 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyProfiler.SQLServer", "src\EasyProfiler.SQLServer\EasyProfiler.SQLServer.csproj", "{A6CF2E31-7D4C-465A-9E3D-72DD012C26C3}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyProfiler.Entities", "src\EasyProfiler.Entities\EasyProfiler.Entities.csproj", "{7EA52047-90A2-48E3-A1E6-48A56B4B8E0A}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A6E015BB-C6E2-4EBF-BDE1-421F601B63FB}" ProjectSection(SolutionItems) = preProject .gitignore = .gitignore @@ -23,7 +21,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyProfiler.Core", "src\Ea EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyProfiler.MariaDb", "src\EasyProfiler.MariaDb\EasyProfiler.MariaDb.csproj", "{7D777586-91E5-4826-91AC-4ED0C9C30B13}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EasyProfiler.PostgreSQL", "src\EasyProfiler.PostgreSQL\EasyProfiler.PostgreSQL.csproj", "{FCC42610-B106-443B-9CDD-6DB922D47139}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyProfiler.PostgreSQL", "src\EasyProfiler.PostgreSQL\EasyProfiler.PostgreSQL.csproj", "{FCC42610-B106-443B-9CDD-6DB922D47139}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -35,10 +33,6 @@ Global {A6CF2E31-7D4C-465A-9E3D-72DD012C26C3}.Debug|Any CPU.Build.0 = Debug|Any CPU {A6CF2E31-7D4C-465A-9E3D-72DD012C26C3}.Release|Any CPU.ActiveCfg = Release|Any CPU {A6CF2E31-7D4C-465A-9E3D-72DD012C26C3}.Release|Any CPU.Build.0 = Release|Any CPU - {7EA52047-90A2-48E3-A1E6-48A56B4B8E0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7EA52047-90A2-48E3-A1E6-48A56B4B8E0A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7EA52047-90A2-48E3-A1E6-48A56B4B8E0A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7EA52047-90A2-48E3-A1E6-48A56B4B8E0A}.Release|Any CPU.Build.0 = Release|Any CPU {E08FD8E2-2D4F-4DA2-A668-E7A3E84B8DE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E08FD8E2-2D4F-4DA2-A668-E7A3E84B8DE9}.Debug|Any CPU.Build.0 = Debug|Any CPU {E08FD8E2-2D4F-4DA2-A668-E7A3E84B8DE9}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -61,7 +55,6 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {A6CF2E31-7D4C-465A-9E3D-72DD012C26C3} = {9AE5BFB8-BA7B-4939-934E-B28220564041} - {7EA52047-90A2-48E3-A1E6-48A56B4B8E0A} = {9AE5BFB8-BA7B-4939-934E-B28220564041} {E08FD8E2-2D4F-4DA2-A668-E7A3E84B8DE9} = {E7EE1DF1-9E6C-4B2B-9847-3C03030EFF6E} {5900675D-AC82-4F00-A90E-486AA22F8FDF} = {9AE5BFB8-BA7B-4939-934E-B28220564041} {7D777586-91E5-4826-91AC-4ED0C9C30B13} = {9AE5BFB8-BA7B-4939-934E-B28220564041} diff --git a/samples/EasyProfiler.Web/Controllers/DefaultController.cs b/samples/EasyProfiler.Web/Controllers/DefaultController.cs index d5959c0..547a49e 100644 --- a/samples/EasyProfiler.Web/Controllers/DefaultController.cs +++ b/samples/EasyProfiler.Web/Controllers/DefaultController.cs @@ -73,5 +73,20 @@ public async Task AdvancedFilterForEasyProfilerAsync([FromQuery] { return Ok(await baseService.AdvancedFilterAsync(model)); } + + /// + /// Find slowest endpoint. + /// + /// + /// EasyProfilerBaseService + /// + /// + /// List of SlowestEndpointResponseModel. + /// + [HttpGet("SlowestEndpoint")] + public async Task SlowestEndpointAsync([FromServices] IEasyProfilerBaseService baseService) + { + return Ok(await baseService.GetSlowestEndpointsAsync()); + } } } diff --git a/src/EasyProfiler.Core/Abstractions/IEasyProfilerBaseService.cs b/src/EasyProfiler.Core/Abstractions/IEasyProfilerBaseService.cs index 9c602d5..f4ee6f5 100644 --- a/src/EasyProfiler.Core/Abstractions/IEasyProfilerBaseService.cs +++ b/src/EasyProfiler.Core/Abstractions/IEasyProfilerBaseService.cs @@ -1,8 +1,10 @@ -using EasyProfiler.Core.Helpers.AdvancedQuery; -using EasyProfiler.Entities; +using EasyProfiler.Core.Entities; +using EasyProfiler.Core.Helpers.AdvancedQuery; +using EasyProfiler.Core.Helpers.Responses; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; +using System.Linq; using System.Text; using System.Threading.Tasks; @@ -13,5 +15,7 @@ public interface IEasyProfilerBaseService where TDbContext : DbConte Task InsertAsync(Profiler profiler); Task> AdvancedFilterAsync(AdvancedFilterModel advancedFilterModel); + + Task> GetSlowestEndpointsAsync(); } } diff --git a/src/EasyProfiler.Core/Concrete/EasyProfilerBaseManager.cs b/src/EasyProfiler.Core/Concrete/EasyProfilerBaseManager.cs index af833d7..331cf56 100644 --- a/src/EasyProfiler.Core/Concrete/EasyProfilerBaseManager.cs +++ b/src/EasyProfiler.Core/Concrete/EasyProfilerBaseManager.cs @@ -1,8 +1,10 @@ using AutoFilterer.Extensions; using EasyProfiler.Core.Abstractions; +using EasyProfiler.Core.Entities; using EasyProfiler.Core.Helpers.AdvancedQuery; -using EasyProfiler.Entities; +using EasyProfiler.Core.Helpers.Responses; using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Diagnostics; using System; using System.Collections.Generic; using System.Linq; @@ -25,6 +27,18 @@ public async Task> AdvancedFilterAsync(AdvancedFilterModel advanc return await dbContext.Set().ApplyFilter(advancedFilterModel).ToListAsync(); } + public async Task> GetSlowestEndpointsAsync() + { + var data = await dbContext.Set().Where(x => !string.IsNullOrEmpty(x.RequestUrl) && x.RequestUrl != "/") + .GroupBy(g => g.RequestUrl).Select(s => new SlowestEndpointResponseModel + { + RequestUrl = s.Key, + Count = s.Count(), + AvarageDurationTime = new TimeSpan(s.Sum(a => a.Duration) / s.Count()) + }).ToListAsync(); + return data.OrderByDescending(x=>x.AvarageDurationTime).ToList(); + } + public async Task InsertAsync(Profiler profiler) { var entity = dbContext.Entry(profiler); diff --git a/src/EasyProfiler.Core/EasyProfiler.Core.csproj b/src/EasyProfiler.Core/EasyProfiler.Core.csproj index eb44e31..46c3ce5 100644 --- a/src/EasyProfiler.Core/EasyProfiler.Core.csproj +++ b/src/EasyProfiler.Core/EasyProfiler.Core.csproj @@ -7,12 +7,18 @@ easyProfilerSQLServer.png https://github.com/furkandeveloper/EasyProfiler sql-server, profiler, query-profiler,query-analyzer - Added base service. - 1.1.0 + + *♻️ Move Profiler entity from EasyProfiler.Entites to EasyProfiler.Core + *✨ Add RequestUrl feature. + *✨ Add SlowestEndpoint feature. + + 1.2.0 + + @@ -21,9 +27,5 @@ - - - - diff --git a/src/EasyProfiler.Entities/BaseEntity.cs b/src/EasyProfiler.Core/Entities/BaseEntity.cs similarity index 88% rename from src/EasyProfiler.Entities/BaseEntity.cs rename to src/EasyProfiler.Core/Entities/BaseEntity.cs index 5290aa3..f1eeed4 100644 --- a/src/EasyProfiler.Entities/BaseEntity.cs +++ b/src/EasyProfiler.Core/Entities/BaseEntity.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace EasyProfiler.Entities +namespace EasyProfiler.Core.Entities { /// /// Base Entity. diff --git a/src/EasyProfiler.Entities/Profiler.cs b/src/EasyProfiler.Core/Entities/Profiler.cs similarity index 63% rename from src/EasyProfiler.Entities/Profiler.cs rename to src/EasyProfiler.Core/Entities/Profiler.cs index 7bbf32c..dd7842a 100644 --- a/src/EasyProfiler.Entities/Profiler.cs +++ b/src/EasyProfiler.Core/Entities/Profiler.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace EasyProfiler.Entities +namespace EasyProfiler.Core.Entities { /// /// Profiler entity. @@ -11,6 +11,8 @@ public class Profiler : BaseEntity { public string Query { get; set; } - public TimeSpan Duration { get; set; } + public long Duration { get; set; } + + public string RequestUrl { get; set; } = "/"; } } diff --git a/src/EasyProfiler.Core/Helpers/AdvancedQuery/AdvancedFilterModel.cs b/src/EasyProfiler.Core/Helpers/AdvancedQuery/AdvancedFilterModel.cs index 4002817..b3d6267 100644 --- a/src/EasyProfiler.Core/Helpers/AdvancedQuery/AdvancedFilterModel.cs +++ b/src/EasyProfiler.Core/Helpers/AdvancedQuery/AdvancedFilterModel.cs @@ -25,8 +25,14 @@ public AdvancedFilterModel() public string Query { get; set; } /// - /// Query duration. + /// Request Url /// - public Range Duration { get; set; } + [ToLowerContainsComparison] + public string RequestUrl { get; set; } + + /// + /// Duration. + /// + public Range Duration { get; set; } } } diff --git a/src/EasyProfiler.Entities/GuidGenerator.cs b/src/EasyProfiler.Core/Helpers/Generators/GuidGenerator.cs similarity index 91% rename from src/EasyProfiler.Entities/GuidGenerator.cs rename to src/EasyProfiler.Core/Helpers/Generators/GuidGenerator.cs index adecf0c..c64426a 100644 --- a/src/EasyProfiler.Entities/GuidGenerator.cs +++ b/src/EasyProfiler.Core/Helpers/Generators/GuidGenerator.cs @@ -4,7 +4,7 @@ using System.Collections.Generic; using System.Text; -namespace EasyProfiler.Entities +namespace EasyProfiler.Core.Helpers.Generators { /// /// Guid value generator for primary key. diff --git a/src/EasyProfiler.Core/Helpers/Responses/SlowestEndpointResponseModel.cs b/src/EasyProfiler.Core/Helpers/Responses/SlowestEndpointResponseModel.cs new file mode 100644 index 0000000..c9da732 --- /dev/null +++ b/src/EasyProfiler.Core/Helpers/Responses/SlowestEndpointResponseModel.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace EasyProfiler.Core.Helpers.Responses +{ + public class SlowestEndpointResponseModel + { + public string RequestUrl { get; set; } + + public int Count { get; set; } + + public TimeSpan AvarageDurationTime { get; set; } + } +} diff --git a/src/EasyProfiler.Entities/EasyProfiler.Entities.csproj b/src/EasyProfiler.Entities/EasyProfiler.Entities.csproj deleted file mode 100644 index 4fd2cc1..0000000 --- a/src/EasyProfiler.Entities/EasyProfiler.Entities.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - netcoreapp3.1 - furkandeveloper - easyProfilerSQLServer.png - This repo, provides query profiler for EF Core. - https://github.com/furkandeveloper/EasyProfiler - sql-server, profiler, query-profiler,query-analyzer - Implement entities for EasyProfiler. - - - - - - - - - True - - - - - diff --git a/src/EasyProfiler.Entities/easyProfilerSQLServer.png b/src/EasyProfiler.Entities/easyProfilerSQLServer.png deleted file mode 100644 index a70fe3c..0000000 Binary files a/src/EasyProfiler.Entities/easyProfilerSQLServer.png and /dev/null differ diff --git a/src/EasyProfiler.MariaDb/Context/ProfilerDbContext.cs b/src/EasyProfiler.MariaDb/Context/ProfilerDbContext.cs index 35544c5..aae13a1 100644 --- a/src/EasyProfiler.MariaDb/Context/ProfilerDbContext.cs +++ b/src/EasyProfiler.MariaDb/Context/ProfilerDbContext.cs @@ -1,4 +1,5 @@ -using EasyProfiler.Entities; +using EasyProfiler.Core.Entities; +using EasyProfiler.Core.Helpers.Generators; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; @@ -40,8 +41,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity .Property(p => p.Duration) - .HasColumnType("bigint") - .HasConversion(new TimeSpanToTicksConverter()); + .HasColumnType("bigint"); }); base.OnModelCreating(modelBuilder); } diff --git a/src/EasyProfiler.MariaDb/EasyProfiler.MariaDb.csproj b/src/EasyProfiler.MariaDb/EasyProfiler.MariaDb.csproj index 6dc2939..3f81a6e 100644 --- a/src/EasyProfiler.MariaDb/EasyProfiler.MariaDb.csproj +++ b/src/EasyProfiler.MariaDb/EasyProfiler.MariaDb.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 @@ -6,11 +6,15 @@ false This repo, provides query profiler for EF Core. mariadb, profiler, query-profiler,query-analyzer - Move service layer EasyProfiler.MariaDb to EasyProfiler.Core + + *♻️ Move Profiler entity from EasyProfiler.Entites to EasyProfiler.Core + *✨ Add RequestUrl feature. + *✨ Add SlowestEndpoint feature. + easyProfilerMariaDb.png https://github.com/furkandeveloper/EasyProfiler furkandeveloper - 1.1.0 + 1.2.0 @@ -24,7 +28,6 @@ - diff --git a/src/EasyProfiler.MariaDb/Interceptors/EasyProfilerInterceptors.cs b/src/EasyProfiler.MariaDb/Interceptors/EasyProfilerInterceptors.cs index 8aa6e84..d0f58d5 100644 --- a/src/EasyProfiler.MariaDb/Interceptors/EasyProfilerInterceptors.cs +++ b/src/EasyProfiler.MariaDb/Interceptors/EasyProfilerInterceptors.cs @@ -1,6 +1,7 @@ using System.Data.Common; using System.Threading.Tasks; using EasyProfiler.Core.Abstractions; +using EasyProfiler.Core.Entities; using EasyProfiler.MariaDb.Context; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -17,10 +18,10 @@ public EasyProfilerInterceptors(IEasyProfilerBaseService base public override InterceptionResult DataReaderDisposing(DbCommand command, DataReaderDisposingEventData eventData, InterceptionResult result) { - Task.Run(() => baseService.InsertAsync(new Entities.Profiler() + Task.Run(() => baseService.InsertAsync(new Profiler() { Query = command.CommandText, - Duration = eventData.Duration + Duration = eventData.Duration.Ticks })); return base.DataReaderDisposing(command, eventData, result); } diff --git a/src/EasyProfiler.MariaDb/Migrations/20201109184436_AddRequestUrl.Designer.cs b/src/EasyProfiler.MariaDb/Migrations/20201109184436_AddRequestUrl.Designer.cs new file mode 100644 index 0000000..67ba38f --- /dev/null +++ b/src/EasyProfiler.MariaDb/Migrations/20201109184436_AddRequestUrl.Designer.cs @@ -0,0 +1,47 @@ +// +using System; +using EasyProfiler.MariaDb.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace EasyProfiler.MariaDb.Migrations +{ + [DbContext(typeof(ProfilerDbContext))] + [Migration("20201109184436_AddRequestUrl")] + partial class AddRequestUrl + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.8") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("EasyProfiler.Entities.Profiler", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("Duration") + .HasColumnType("bigint"); + + b.Property("Query") + .IsRequired() + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.Property("RequestUrl") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + + b.HasKey("Id"); + + b.HasIndex("Duration"); + + b.ToTable("Profilers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/EasyProfiler.MariaDb/Migrations/20201109184436_AddRequestUrl.cs b/src/EasyProfiler.MariaDb/Migrations/20201109184436_AddRequestUrl.cs new file mode 100644 index 0000000..e16f0fe --- /dev/null +++ b/src/EasyProfiler.MariaDb/Migrations/20201109184436_AddRequestUrl.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace EasyProfiler.MariaDb.Migrations +{ + public partial class AddRequestUrl : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RequestUrl", + table: "Profilers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RequestUrl", + table: "Profilers"); + } + } +} diff --git a/src/EasyProfiler.MariaDb/Migrations/ProfilerDbContextModelSnapshot.cs b/src/EasyProfiler.MariaDb/Migrations/ProfilerDbContextModelSnapshot.cs index a0be5d7..8cd3f61 100644 --- a/src/EasyProfiler.MariaDb/Migrations/ProfilerDbContextModelSnapshot.cs +++ b/src/EasyProfiler.MariaDb/Migrations/ProfilerDbContextModelSnapshot.cs @@ -30,6 +30,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("longtext CHARACTER SET utf8mb4"); + b.Property("RequestUrl") + .HasColumnType("longtext CHARACTER SET utf8mb4"); + b.HasKey("Id"); b.HasIndex("Duration"); diff --git a/src/EasyProfiler.PostgreSQL/Context/ProfilerDbContext.cs b/src/EasyProfiler.PostgreSQL/Context/ProfilerDbContext.cs index 720f8ab..ff1eb5a 100644 --- a/src/EasyProfiler.PostgreSQL/Context/ProfilerDbContext.cs +++ b/src/EasyProfiler.PostgreSQL/Context/ProfilerDbContext.cs @@ -1,4 +1,5 @@ -using EasyProfiler.Entities; +using EasyProfiler.Core.Entities; +using EasyProfiler.Core.Helpers.Generators; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; @@ -46,8 +47,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity .Property(p => p.Duration) - .HasColumnType("bigint") - .HasConversion(new TimeSpanToTicksConverter()); + .HasColumnType("bigint"); }); base.OnModelCreating(modelBuilder); } diff --git a/src/EasyProfiler.PostgreSQL/EasyProfiler.PostgreSQL.csproj b/src/EasyProfiler.PostgreSQL/EasyProfiler.PostgreSQL.csproj index 7fcf5f8..eed1e31 100644 --- a/src/EasyProfiler.PostgreSQL/EasyProfiler.PostgreSQL.csproj +++ b/src/EasyProfiler.PostgreSQL/EasyProfiler.PostgreSQL.csproj @@ -1,14 +1,20 @@  - - netcoreapp3.1 - This repo, provides query profiler for EF Core. - https://github.com/furkandeveloper/EasyProfiler - sql-server, profiler, query-profiler,query-analyzer - ✨Supported PostgreSQL - easyProfilerPostgreSQL.png - true - + + netcoreapp3.1 + This repo, provides query profiler for EF Core. + https://github.com/furkandeveloper/EasyProfiler + sql-server, profiler, query-profiler,query-analyzer + + *♻️ Move Profiler entity from EasyProfiler.Entites to EasyProfiler.Core + *✨ Add RequestUrl feature. + *✨ Add SlowestEndpoint feature. + + easyProfilerPostgreSQL.png + true + furkandeveloper + 1.1.0 + @@ -20,8 +26,7 @@ - - + diff --git a/src/EasyProfiler.PostgreSQL/Extensions/Interception.cs b/src/EasyProfiler.PostgreSQL/Extensions/Interception.cs index 284a6a4..f3d52a3 100644 --- a/src/EasyProfiler.PostgreSQL/Extensions/Interception.cs +++ b/src/EasyProfiler.PostgreSQL/Extensions/Interception.cs @@ -1,6 +1,7 @@ using EasyProfiler.Core.Abstractions; using EasyProfiler.PostgreSQL.Context; using EasyProfiler.PostgreSQL.Interceptors; +using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using System; @@ -25,7 +26,8 @@ public static class Interception /// public static DbContextOptionsBuilder AddEasyProfiler(this DbContextOptionsBuilder optionsBuilder, IServiceCollection services) { - optionsBuilder.AddInterceptors(new EasyProfilerInterceptors(services.BuildServiceProvider().GetService>())); + var buildServices = services.BuildServiceProvider(); + optionsBuilder.AddInterceptors(new EasyProfilerInterceptors(buildServices.GetService>(),buildServices.GetService())); return optionsBuilder; } } diff --git a/src/EasyProfiler.PostgreSQL/Interceptors/EasyProfilerInterceptors.cs b/src/EasyProfiler.PostgreSQL/Interceptors/EasyProfilerInterceptors.cs index 5eecc74..318b119 100644 --- a/src/EasyProfiler.PostgreSQL/Interceptors/EasyProfilerInterceptors.cs +++ b/src/EasyProfiler.PostgreSQL/Interceptors/EasyProfilerInterceptors.cs @@ -1,5 +1,7 @@ using EasyProfiler.Core.Abstractions; +using EasyProfiler.Core.Entities; using EasyProfiler.PostgreSQL.Context; +using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore.Diagnostics; using System; using System.Collections.Generic; @@ -15,10 +17,12 @@ namespace EasyProfiler.PostgreSQL.Interceptors public class EasyProfilerInterceptors : DbCommandInterceptor { private readonly IEasyProfilerBaseService baseService; + private readonly IHttpContextAccessor httpContextAccessor; - public EasyProfilerInterceptors(IEasyProfilerBaseService baseService) + public EasyProfilerInterceptors(IEasyProfilerBaseService baseService,IHttpContextAccessor httpContextAccessor) { this.baseService = baseService; + this.httpContextAccessor = httpContextAccessor; } /// /// Data reader Disposing. @@ -35,10 +39,11 @@ public EasyProfilerInterceptors(IEasyProfilerBaseService base /// public override InterceptionResult DataReaderDisposing(DbCommand command, DataReaderDisposingEventData eventData, InterceptionResult result) { - Task.Run(() => baseService.InsertAsync(new Entities.Profiler + Task.Run(() => baseService.InsertAsync(new Profiler { - Duration = eventData.Duration, - Query = command.CommandText + Duration = eventData.Duration.Ticks, + Query = command.CommandText, + RequestUrl = httpContextAccessor?.HttpContext?.Request?.Path.Value })); return base.DataReaderDisposing(command, eventData, result); } diff --git a/src/EasyProfiler.PostgreSQL/Migrations/20201109183336_AddRequestUrl.Designer.cs b/src/EasyProfiler.PostgreSQL/Migrations/20201109183336_AddRequestUrl.Designer.cs new file mode 100644 index 0000000..b2cb6cb --- /dev/null +++ b/src/EasyProfiler.PostgreSQL/Migrations/20201109183336_AddRequestUrl.Designer.cs @@ -0,0 +1,49 @@ +// +using System; +using EasyProfiler.PostgreSQL.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace EasyProfiler.PostgreSQL.Migrations +{ + [DbContext(typeof(ProfilerDbContext))] + [Migration("20201109183336_AddRequestUrl")] + partial class AddRequestUrl + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) + .HasAnnotation("ProductVersion", "3.1.9") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + modelBuilder.Entity("EasyProfiler.Entities.Profiler", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Duration") + .HasColumnType("bigint"); + + b.Property("Query") + .IsRequired() + .HasColumnType("text"); + + b.Property("RequestUrl") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Duration"); + + b.ToTable("Profilers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/EasyProfiler.PostgreSQL/Migrations/20201109183336_AddRequestUrl.cs b/src/EasyProfiler.PostgreSQL/Migrations/20201109183336_AddRequestUrl.cs new file mode 100644 index 0000000..3a54b22 --- /dev/null +++ b/src/EasyProfiler.PostgreSQL/Migrations/20201109183336_AddRequestUrl.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace EasyProfiler.PostgreSQL.Migrations +{ + public partial class AddRequestUrl : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RequestUrl", + table: "Profilers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RequestUrl", + table: "Profilers"); + } + } +} diff --git a/src/EasyProfiler.PostgreSQL/Migrations/ProfilerDbContextModelSnapshot.cs b/src/EasyProfiler.PostgreSQL/Migrations/ProfilerDbContextModelSnapshot.cs index ed99814..b21cb6a 100644 --- a/src/EasyProfiler.PostgreSQL/Migrations/ProfilerDbContextModelSnapshot.cs +++ b/src/EasyProfiler.PostgreSQL/Migrations/ProfilerDbContextModelSnapshot.cs @@ -32,6 +32,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("text"); + b.Property("RequestUrl") + .HasColumnType("text"); + b.HasKey("Id"); b.HasIndex("Duration"); diff --git a/src/EasyProfiler.SQLServer/Context/ProfilerDbContext.cs b/src/EasyProfiler.SQLServer/Context/ProfilerDbContext.cs index 085f8eb..7b3d67e 100644 --- a/src/EasyProfiler.SQLServer/Context/ProfilerDbContext.cs +++ b/src/EasyProfiler.SQLServer/Context/ProfilerDbContext.cs @@ -1,4 +1,5 @@ -using EasyProfiler.Entities; +using EasyProfiler.Core.Entities; +using EasyProfiler.Core.Helpers.Generators; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using System; @@ -40,11 +41,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity .Property(p => p.Query) .IsRequired(); - + entity .Property(p => p.Duration) - .HasColumnType("bigint") - .HasConversion(new TimeSpanToTicksConverter()); + .HasColumnType("bigint"); }); base.OnModelCreating(modelBuilder); } diff --git a/src/EasyProfiler.SQLServer/EasyProfiler.SQLServer.csproj b/src/EasyProfiler.SQLServer/EasyProfiler.SQLServer.csproj index afd7f07..32ba570 100644 --- a/src/EasyProfiler.SQLServer/EasyProfiler.SQLServer.csproj +++ b/src/EasyProfiler.SQLServer/EasyProfiler.SQLServer.csproj @@ -6,11 +6,15 @@ false This repo, provides query profiler for EF Core. sql-server, profiler, query-profiler,query-analyzer - Change `Duration` field data type from `time` to `bigint` for SQL Server provider. + + *♻️ Move Profiler entity from EasyProfiler.Entites to EasyProfiler.Core + *✨ Add RequestUrl feature. + *✨ Add SlowestEndpoint feature. + easyProfilerSQLServer.png https://github.com/furkandeveloper/EasyProfiler furkandeveloper - 1.2.0 + 1.3.0 @@ -24,7 +28,6 @@ - diff --git a/src/EasyProfiler.SQLServer/Interceptors/EasyProfilerInterceptors.cs b/src/EasyProfiler.SQLServer/Interceptors/EasyProfilerInterceptors.cs index a5b0626..3ebfd63 100644 --- a/src/EasyProfiler.SQLServer/Interceptors/EasyProfilerInterceptors.cs +++ b/src/EasyProfiler.SQLServer/Interceptors/EasyProfilerInterceptors.cs @@ -1,4 +1,5 @@ using EasyProfiler.Core.Abstractions; +using EasyProfiler.Core.Entities; using EasyProfiler.SQLServer.Context; using Microsoft.EntityFrameworkCore.Diagnostics; using System; @@ -21,10 +22,10 @@ public EasyProfilerInterceptors(IEasyProfilerBaseService base public override InterceptionResult DataReaderDisposing(DbCommand command, DataReaderDisposingEventData eventData, InterceptionResult result) { - Task.Run(() => baseService.InsertAsync(new Entities.Profiler() + Task.Run(() => baseService.InsertAsync(new Profiler() { Query = command.CommandText, - Duration = eventData.Duration + Duration = eventData.Duration.Ticks })); return base.DataReaderDisposing(command, eventData, result); } diff --git a/src/EasyProfiler.SQLServer/Migrations/20201109184302_AddRequestUrl.Designer.cs b/src/EasyProfiler.SQLServer/Migrations/20201109184302_AddRequestUrl.Designer.cs new file mode 100644 index 0000000..20986be --- /dev/null +++ b/src/EasyProfiler.SQLServer/Migrations/20201109184302_AddRequestUrl.Designer.cs @@ -0,0 +1,49 @@ +// +using System; +using EasyProfiler.SQLServer.Context; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace EasyProfiler.SQLServer.Migrations +{ + [DbContext(typeof(ProfilerDbContext))] + [Migration("20201109184302_AddRequestUrl")] + partial class AddRequestUrl + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "3.1.8") + .HasAnnotation("Relational:MaxIdentifierLength", 128) + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); + + modelBuilder.Entity("EasyProfiler.Entities.Profiler", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("Duration") + .HasColumnType("bigint"); + + b.Property("Query") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("RequestUrl") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("Duration"); + + b.ToTable("Profilers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/EasyProfiler.SQLServer/Migrations/20201109184302_AddRequestUrl.cs b/src/EasyProfiler.SQLServer/Migrations/20201109184302_AddRequestUrl.cs new file mode 100644 index 0000000..ab34f06 --- /dev/null +++ b/src/EasyProfiler.SQLServer/Migrations/20201109184302_AddRequestUrl.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace EasyProfiler.SQLServer.Migrations +{ + public partial class AddRequestUrl : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RequestUrl", + table: "Profilers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RequestUrl", + table: "Profilers"); + } + } +} diff --git a/src/EasyProfiler.SQLServer/Migrations/ProfilerDbContextModelSnapshot.cs b/src/EasyProfiler.SQLServer/Migrations/ProfilerDbContextModelSnapshot.cs index 9cb0297..9579a7e 100644 --- a/src/EasyProfiler.SQLServer/Migrations/ProfilerDbContextModelSnapshot.cs +++ b/src/EasyProfiler.SQLServer/Migrations/ProfilerDbContextModelSnapshot.cs @@ -15,7 +15,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "3.1.9") + .HasAnnotation("ProductVersion", "3.1.8") .HasAnnotation("Relational:MaxIdentifierLength", 128) .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); @@ -32,6 +32,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); + b.Property("RequestUrl") + .HasColumnType("nvarchar(max)"); + b.HasKey("Id"); b.HasIndex("Duration");