Skip to content

Commit

Permalink
Add feature: allows to get PerformanceMeter of concrete class using D…
Browse files Browse the repository at this point in the history
…I with `RegisterPerformanceMeterScope` option setted to true (by default is true)
  • Loading branch information
unchase committed Jun 5, 2020
1 parent 5a4688c commit 1bb2f67
Show file tree
Hide file tree
Showing 13 changed files with 226 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

These are the changes to each version that has been released on the official [NuGet Gallery (Common)](https://www.nuget.org/packages/Unchase.FluentPerformanceMeter) and [NuGet Gallery (MVC)](https://www.nuget.org/packages/Unchase.FluentPerformanceMeter.AspNetCore.Mvc).

## v2.1.2 `(2020-06-05)`

- [x] Add feature: allows to get PerformanceMeter of concrete class using DI with `RegisterPerformanceMeterScope` option setted to true (by default is true)

## v2.1.1 `(2020-05-02)`

- [x] Add feature: allows to iterate executing Actions with `iterations` parameter in `Start` extension methods
Expand Down
60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ The data obtained as a result of the method’s performance measurement can be u
* [Examples of usage](#SimpleSamples)
* [Method's performance measurement](#SimpleSamples)
* [Using DI to Get Performance measurement results (v2.1.0)](#UsingDISamples)
* [Using DI to Get Performance measurement instance (v2.1.2)](#UsingDIInstanceSamples)
* [Method's performance measurement with `DiagnosticSource` (v1.1.0)](#DiagnosticSourceSample)
* [Method's performance measurement with `WatchingPerformanceAttribute` attribute (v2.0.0)](#WatchingPerformanceSample)
* [Measuring the performance of an external library method](#SampleExternal)
Expand Down Expand Up @@ -220,6 +221,65 @@ public class PerformanceMeterController : ControllerBase
}
```

#### <a name="UsingDIInstanceSamples"></a> Using DI to Get Performance measurement instance

Starting with [*v2.1.2*](https://github.com/unchase/Unchase.FluentPerformanceMeter/releases/tag/v2.1.2), it became possible to get the performance measurement of the class instance using the built-in **DI** in *ASP.NET Core* application.
To do this, add the following code to `Startap.cs`:

```csharp
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddPerformanceMeter<PerformanceMeterController>(options =>
{
// ...
// adds a scope service of the PerformanceMeter of concrete class for DI
// use it with ".WithSettingData.CallerFrom(IHttpContextAccessor)"
options.RegisterPerformanceMeterScope = true;
}

// ...
}
```

Then, using DI, you can get the performance measurement instance, for example, as follows:

```csharp
[ApiController]
[Route("api/v1/[controller]")]
public class PerformanceMeterController : ControllerBase
{
[HttpGet("WatchingMethodUsingDI")]
public IActionResult WatchingMethodUsingDI()
{
// method performance info will reach with HttpContextAccessor (required for DI)
using (PerformanceMeter<PerformanceMeterController>
.WatchingMethod(nameof(WatchingMethodUsingDI))
.WithSettingData
.CallerFrom(_httpContextAccessor)
.Start())
{
GetPerformanceMeterUsingDI();

return Ok();
}
}

private void GetPerformanceMeterUsingDI()
{
// get instance of PerformanceMeter<PerformanceMeterController> using DI
var pm = HttpContext.RequestServices.GetRequiredService(typeof(PerformanceMeter<PerformanceMeterController>)) as PerformanceMeter<PerformanceMeterController>;

// we can use "pm" for adding steps or for other operations
// ...
}

// ...
}
```

### <a name="DiagnosticSourceSample"></a> Method's performance measurement with `DiagnosticSource`

Starting with [*v1.1.0*](https://github.com/unchase/Unchase.FluentPerformanceMeter/releases/tag/v1.1.0), it became possible to measure the performance of methods in an *AspNetCore MVC* application using the `DiagnosticSource` and the special `WatchingWithDiagnosticSourceAttribute` attribute. To do this, add the *NuGet* package [`Unchase.FluentPerformanceMeter.AspNetCore.Mvc`](https://www.nuget.org/Unchase.FluentPerformanceMeter.AspNetCore.Mvc) to the project and add the following code to `Startap.cs`:
Expand Down
60 changes: 60 additions & 0 deletions README_RU.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
* [Примеры использования](#SimpleSamples)
* [Измерение производительности метода](#SimpleSamples)
* [Использование DI для получения результатов замера производительности (v2.1.0)](#UsingDISamples)
* [Использование DI для получения экземпляра текущего замера производительности (v2.1.2)](#UsingDIInstanceSamples)
* [Измерение производительности метода с помощью `DiagnosticSource` (v1.1.0)](#DiagnosticSourceSample)
* [Измерение производительности метода с помощью атрибута `WatchingPerformanceAttribute` (v2.0.0)](#WatchingPerformanceSample)
* [Измерение производительности метода используемой библиотеки](#SampleExternal)
Expand Down Expand Up @@ -224,6 +225,65 @@ public class PerformanceMeterController : ControllerBase
}
```

#### <a name="UsingDIInstanceSamples"></a> Использование DI для получения экземпляра текущего замера производительности

Начиная с версии [*v2.1.2*](https://github.com/unchase/Unchase.FluentPerformanceMeter/releases/tag/v2.1.2) появилась возможность получать текущий экземпляр замера производительности методов класса, используя встроенный **DI** в *ASP.NET Core* приложении.
Для этого необходимо добавить в `Startap.cs` следующий код:

```csharp
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddPerformanceMeter<PerformanceMeterController>(options =>
{
// ...
// adds a scope service of the PerformanceMeter of concrete class for DI
// use it with ".WithSettingData.CallerFrom(IHttpContextAccessor)"
options.RegisterPerformanceMeterScope = true;
}

// ...
}
```

После чего, используя DI, можно получить текущий экземпляр замера производительности, например, следующим образом:

```csharp
[ApiController]
[Route("api/v1/[controller]")]
public class PerformanceMeterController : ControllerBase
{
[HttpGet("WatchingMethodUsingDI")]
public IActionResult WatchingMethodUsingDI()
{
// method performance info will reach with HttpContextAccessor (required for DI)
using (PerformanceMeter<PerformanceMeterController>
.WatchingMethod(nameof(WatchingMethodUsingDI))
.WithSettingData
.CallerFrom(_httpContextAccessor)
.Start())
{
GetPerformanceMeterUsingDI();

return Ok();
}
}

private void GetPerformanceMeterUsingDI()
{
// get instance of PerformanceMeter<PerformanceMeterController> using DI
var pm = HttpContext.RequestServices.GetRequiredService(typeof(PerformanceMeter<PerformanceMeterController>)) as PerformanceMeter<PerformanceMeterController>;

// we can use "pm" for adding steps or for other operations
// ...
}

// ...
}
```

### <a name="DiagnosticSourceSample"></a> Измерение производительности метода с помощью `DiagnosticSource`

Начиная с версии [*v1.1.0*](https://github.com/unchase/Unchase.FluentPerformanceMeter/releases/tag/v1.1.0) появилась возможность мерять производительность методов в *AspNetCore MVC* приложении с помощью `DiagnosticSource` и специального атрибута `WatchingWithDiagnosticSourceAttribute`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Unchase.FluentPerformanceMeter.AspNetCore.Mvc.DiagnosticSource;

Expand Down Expand Up @@ -62,11 +63,24 @@ public static IApplicationBuilder UsePerformanceDiagnosticObserver(this IApplica
/// <param name="configureOptions">An <see cref="Action{PerformanceMeterMvcOptions}"/> to configure options for Unchase.FluentPerformanceMeter.</param>
public static IServiceCollection AddPerformanceMeter<TClass>(this IServiceCollection services, Action<PerformanceMeterMvcOptions<TClass>> configureOptions = null) where TClass : ControllerBase
{
// ensure that IHttpContextAccessor was added
services.AddHttpContextAccessor();

if (configureOptions != null)
{
services.Configure(configureOptions);
}
services.Configure<PerformanceMeterMvcOptions<TClass>>(o => PerformanceMeter<TClass>.Configure(o));

services.Configure<PerformanceMeterMvcOptions<TClass>>(o =>
{
PerformanceMeter<TClass>.Configure(o);
});

services.AddScoped(typeof(PerformanceMeter<TClass>), serviceProvider =>
{
var httpContext = serviceProvider.GetRequiredService<IHttpContextAccessor>()?.HttpContext;
return httpContext?.Items[$"PerformanceMeter{httpContext.TraceIdentifier}"];
});

return services;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Version>2.1.1</Version>
<Version>2.1.2</Version>
<Authors>Unchase</Authors>
<Company>Unchase</Company>
<Description>Unchase Fluent Performance Meter is an open-source and cross-platform .Net Standart 2.0 library is designed for the method’s performance measurement.</Description>
Expand All @@ -16,8 +16,8 @@
<RepositoryType>Github</RepositoryType>
<PackageTags>performance benchmark benchmarking csharp dot-net</PackageTags>
<NeutralLanguage>en</NeutralLanguage>
<AssemblyVersion>2.1.1.0</AssemblyVersion>
<FileVersion>2.1.1.0</FileVersion>
<AssemblyVersion>2.1.2.0</AssemblyVersion>
<FileVersion>2.1.2.0</FileVersion>
<DocumentationFile>Unchase.FluentPerformanceMeter.AspNetCore.Mvc.xml</DocumentationFile>
</PropertyGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Threading;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Swashbuckle.AspNetCore.Annotations;
using Swashbuckle.AspNetCore.Filters;
using Unchase.FluentPerformanceMeter.AspNetCore.Mvc.Attributes;
Expand Down Expand Up @@ -476,6 +477,46 @@ public ActionResult<long> WatchingMethodStartWithCorrelationIdAndFakeServiceStep

#endregion

#region DI

/// <summary>
/// Test GET method with using HttpContextAccessor and adding step with DI.
/// </summary>
/// <param name="value">Some value.</param>
/// <returns>
/// Returns input value.
/// </returns>
[HttpGet("WatchingMethodUsingDI")]
public ActionResult<string> WatchingMethodUsingDI(uint value)
{
// method performance info will reach with HttpContextAccessor (required for DI)
using (PerformanceMeter<PerformanceMeterController>
.WatchingMethod(nameof(WatchingMethodUsingDI))
.WithSettingData
.CallerFrom(_httpContextAccessor)
.Start())
{
// adds step to PerformanceMeter using DI
AddStepWithDI();

return Ok($"{value}");
}
}

private void AddStepWithDI()
{
// get instance of PerformanceMeter<PerformanceMeterController> using DI
var pm = HttpContext.RequestServices.GetRequiredService(typeof(PerformanceMeter<PerformanceMeterController>)) as PerformanceMeter<PerformanceMeterController>;

// add "Step (DI)"
using (pm?.Step("Step (DI)"))
{
Thread.Sleep(1000);
}
}

#endregion

#region With HttpContextAccessor, custom data and executed commands

/// <summary>
Expand Down
4 changes: 4 additions & 0 deletions Unchase.FluentPerformanceMeter.TestWebAPI31/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ public void ConfigureServices(IServiceCollection services)

// set default exception handler for the controller class
//options.SetDefaultExceptionHandler((ex) => Debug.WriteLine(ex.Message));

// adds a scope service of the PerformanceMeter of concrete class for DI
// use it with ".WithSettingData.CallerFrom(IHttpContextAccessor)"
//options.RegisterPerformanceMeterScope = false;
});

//services.AddPerformanceDiagnosticObserver<PerformanceMeterController>(options =>
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ internal PerformanceMeter<TClass> Start()
else
throw;
}

if (PerformanceMeter<TClass>.DefaultOptions?.RegisterPerformanceMeterScope == true)
{
var httpContext = this.PerformanceMeter.HttpContextAccessor?.HttpContext;
if (httpContext != null)
httpContext.Items[$"PerformanceMeter{httpContext.TraceIdentifier}"] = this.PerformanceMeter;
}

return this.PerformanceMeter;
}

Expand Down
7 changes: 7 additions & 0 deletions Unchase.FluentPerformanceMeter/PerformanceMeter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,13 @@ private void Dispose(bool disposing)

foreach (var performanceAction in this.RegisteredActions)
performanceAction(PerformanceInfo);

if (DefaultOptions.RegisterPerformanceMeterScope)
{
var httpContext = this.HttpContextAccessor?.HttpContext;
if (httpContext != null && httpContext.Items.ContainsKey($"PerformanceMeter{httpContext.TraceIdentifier}"))
httpContext.Items.Remove($"PerformanceMeter{httpContext.TraceIdentifier}");
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions Unchase.FluentPerformanceMeter/PerformanceMeterBaseOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ public class PerformanceMeterBaseOptions
/// </summary>
public bool AddCustomDataFromCustomAttributes { get; set; } = true;

/// <summary>
/// Adds a scope service of the PerformanceMeter of Class.
/// Default value is true.
/// </summary>
public bool RegisterPerformanceMeterScope { get; set; } = true;

#endregion

#region Methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
<PackageIcon>icon.png</PackageIcon>
<PackageIconUrl />
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<AssemblyVersion>2.1.1.0</AssemblyVersion>
<FileVersion>2.1.1.0</FileVersion>
<Version>2.1.1</Version>
<AssemblyVersion>2.1.2.0</AssemblyVersion>
<FileVersion>2.1.2.0</FileVersion>
<Version>2.1.2</Version>
<DocumentationFile>Unchase.FluentPerformanceMeter.xml</DocumentationFile>
</PropertyGroup>

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1bb2f67

Please sign in to comment.