Jattac.Libs.Profiling 1.0.4

dotnet add package Jattac.Libs.Profiling --version 1.0.4
                    
NuGet\Install-Package Jattac.Libs.Profiling -Version 1.0.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Jattac.Libs.Profiling" Version="1.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Jattac.Libs.Profiling" Version="1.0.4" />
                    
Directory.Packages.props
<PackageReference Include="Jattac.Libs.Profiling" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Jattac.Libs.Profiling --version 1.0.4
                    
#r "nuget: Jattac.Libs.Profiling, 1.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Jattac.Libs.Profiling@1.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Jattac.Libs.Profiling&version=1.0.4
                    
Install as a Cake Addin
#tool nuget:?package=Jattac.Libs.Profiling&version=1.0.4
                    
Install as a Cake Tool

Jattac.Libs.Profiling

A lightweight, dependency-injection-friendly library for profiling method execution times in .NET applications using a dynamic proxy and attributes.

This tool allows you to non-invasively measure the performance of specific methods or entire classes with minimal configuration.

Features

  • Automatic Service Discovery: Scans your assemblies to find and register services for profiling with a single command.
  • Flexible Attribute-Based Control: Add an attribute to interfaces, classes, or methods to control profiling.
  • DI Integration: Easily registers profiled services with your IServiceCollection.
  • Async Support: Seamlessly profiles both synchronous and asynchronous (Task-based) methods.
  • Configuration-Based: Enable or disable profiling globally via your appsettings.json file.
  • Detailed Summaries: Provides clear console logs, including execution time summaries and a list of the slowest calls for each service instance.

Getting Started

Follow these steps to integrate the execution time profiler into your .NET application.

1. Install the NuGet Package

Install the package from NuGet using the .NET CLI or the NuGet Package Manager.

.NET CLI:

dotnet add package Jattac.Libs.Profiling

Package Manager Console:

Install-Package Jattac.Libs.Profiling

2. Apply the Attribute

To mark services for profiling, add the [MeasureExecutionTime] attribute. You can place it on an interface, a class, or an individual method.

Example:

using Jattac.Libs.Profiling;

// You can place the attribute on the interface...
[MeasureExecutionTime(logSummary: true)]
public interface IMyService
{
    void DoWork();
    
    [MeasureExecutionTime(logSummary: false)] // Or on a specific method
    Task DoSpecificWorkAsync();
}

// ...or you can place it on the class.
[MeasureExecutionTime(trackSlowest: true)]
public class MyOtherService : IMyOtherService 
{
    //...
}
  • logSummary: true: Generates a summary table of all calls for the service instance when it's disposed.
  • trackSlowest: true: Keeps track of the slowest method calls for the service instance.

3. Configure Your Application

Add a section to your appsettings.json file to control the profiler's behavior.

{
  "ExecutionTime": {
    "EnableTiming": true,
    "UseCultureFormatting": true
  }
}
  • EnableTiming: true: Profiling is enabled. Set to false to disable all profiling, which removes any performance overhead.
  • UseCultureFormatting: true: Numbers in the summary tables are formatted with thousand separators for readability (e.g., 1,000). Set to false to output raw, unformatted numbers (e.g., 1000), which can be easier for some log parsers to ingest.

4. Configure Your Services

In your application's startup file (e.g., Program.cs), use the AddProfiledServices extension method to automatically find and register all the services you marked with the attribute.

Example in Program.cs (.NET 6+):

using Jattac.Libs.Profiling;

var builder = WebApplication.CreateBuilder(args);

// Automatically find and register all services marked for profiling
// in the current assembly.
builder.Services.AddProfiledServices(builder.Configuration);

// ... other services

var app = builder.Build();

The AddProfiledServices method will discover any service where the interface or the implementation class has the [MeasureExecutionTime] attribute.

Manual Registration

If you prefer to register services manually, you can still use the ProfileScoped method.

builder.Services.ProfileScoped<IMyManualService, MyManualService>(builder.Configuration);

Example Output

When your application runs and the profiled methods are called, you will see output in the console.

Individual Method Log
14:25:10.152: Method MyService.DoWork took 52 ms
14:25:10.355: Method MyService.DoSpecificWorkAsync took 201 ms
Slowest Calls Summary
Top Execution Times (Slowest):
-----------------------------
| MyService.DoSpecificWorkAsync |    201 ms |
| MyService.DoWork      |     52 ms |
-----------------------------
Execution Summary
Execution Summary:
-------------------------------------------
| Method Name         | Count |  Avg ms  | Min ms | Max ms |
-------------------------------------------
| MyService.DoSpecificWorkAsync |     1 |     201 ms |    201 ms |    201 ms |
| MyService.DoWork      |     1 |      52 ms |     52 ms |     52 ms |
-------------------------------------------

Limitations

Please be aware of the following limitations when using this library:

  • No Private Method Profiling: The proxy-based approach can only intercept calls to public methods on a service's interface. It cannot profile private, protected, or internal methods. For this, a more advanced, runtime-level profiler (like those in Visual Studio) is required.

  • Scoped Lifetime Only: All services registered by this library (both automatically and manually) are forced into a Scoped lifetime. Singleton and Transient lifetimes are not supported.

  • One-to-One Mapping for Auto-Discovery: The AddProfiledServices() auto-discovery feature is designed for scenarios where there is a one-to-one mapping between an interface and its implementation. If you have an interface with multiple implementations, you must use manual registration for each one.

  • Performance Overhead: While lightweight, the proxying mechanism does introduce a small amount of performance overhead for each profiled method call. We strongly recommend using the EnableTiming: false configuration in performance-sensitive production environments.

Advanced Notes & Important Behaviors

Please be aware of the following behaviors to ensure the library works as expected in your application.

Dependency Injection: Attribute Wins

If the auto-discovery feature finds a service marked for profiling, it will overwrite any existing manual registration for that service. This is an intentional design choice, as the [MeasureExecutionTime] attribute is treated as the definitive source of truth.

Attribute Placement and Precedence

The library is flexible about where you place the [MeasureExecutionTime] attribute. Here is the order of precedence:

  • For enabling profiling on all methods of a service: An attribute on the class takes precedence over an attribute on the interface.
  • For profiling a specific method: An attribute on either the class method or the interface method will cause it to be profiled (if profiling isn't already enabled for the whole class).
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.4 87 8/10/2025
1.0.3 82 8/9/2025
1.0.2 100 8/9/2025
1.0.1 91 8/9/2025
1.0.0 96 8/9/2025