Une autre façon de mesurer les performances des méthodes d'application .NET


Souvent, il est nécessaire de collecter des statistiques sur les performances des méthodes d'application en temps réel (lorsque l'application est déjà en cours d'exécution) afin d'identifier ses goulots d'étranglement et de voir quelle partie de l'application ralentit.


En outre, il serait intéressant de sauvegarder le contexte d'appel dans lequel les performances sont suivies (comme les arguments de l'appel de méthode et les données arbitraires ajoutées par le développeur), en plus des données de performance elles-mêmes (heure de développement de la méthode, date de début et de fin de son appel).


Eh bien, la "cerise sur le gâteau" peut être considérée comme la commodité et la simplicité de l'outil utilisé, ce qui est également important.


Pour résoudre ces problèmes, une bibliothèque .NET multiplateforme open source Unchase.FluentPerformanceMeter a été développée .


Présentation


Ainsi, cet article est une description de l'utilisation de Unchase Fluent Performance Meter , une bibliothèque multiplateforme open source .Net Standard 2.0 conçue pour calculer les performances des méthodes.


La bibliothèque peut être utilisée dans les applications .NET Core et .NET Framework qui prennent en charge .Net Standard 2.0 et permet:


  • Effectuer des mesures prĂ©cises des performances des mĂ©thodes publiques pour les classes publiques de votre code et du code des bibliothèques utilisĂ©es (en fixant l'heure exacte du dĂ©but et de la fin de la mesure);
  • Ajoutez des donnĂ©es supplĂ©mentaires ( donnĂ©es personnalisĂ©es) aux rĂ©sultats de mesure. Par exemple, les valeurs des paramètres d'entrĂ©e de la mĂ©thode et le rĂ©sultat; ou donnĂ©es de contexte d'exĂ©cution de mĂ©thode; ou corellationId , par lequel il sera possible de relier plusieurs mesures de la performance des mĂ©thodes;
  • Divisez la mesure des performances de la mĂ©thode en Ă©tapes distinctes (Ă©tapes) avec la fixation de vos propres donnĂ©es pour chaque Ă©tape. De plus, vous pouvez dĂ©finir le temps d'exĂ©cution minimum , Ă  partir duquel l'Ă©tape sera prise en compte dans la mesure (si l'Ă©tape est terminĂ©e plus rapidement, elle ne sera pas mesurĂ©e);
  • Exclure des parties individuelles du code de la mesure des performances (par exemple, les appels Ă  des mĂ©thodes individuelles dont le temps d'exĂ©cution n'a pas besoin d'ĂŞtre pris en compte lors de la mesure);
  • Ajoutez vos propres commandes (commandes), dont l'exĂ©cution est garantie immĂ©diatement après la fin de la mesure des performances de la mĂ©thode (par exemple, pour ajouter un traitement supplĂ©mentaire des rĂ©sultats obtenus, comme l'enregistrement ou l'Ă©criture de donnĂ©es dans le stockage);
  • Ajoutez votre propre gestionnaire d'exceptions pour le code exĂ©cutĂ© dans le contexte de la mesure des performances de la mĂ©thode (tous deux communs Ă  toutes les mesures et Ă  chaque mesure sĂ©parĂ©ment);
  • DĂ©finissez le temps de stockage des rĂ©sultats des mesures de la productivitĂ© des mĂ©thodes, après quoi les rĂ©sultats seront supprimĂ©s;
  • Ajouter des donnĂ©es sur qui appelle la mĂ©thode (appelant) via IHttpContextAccesor ou la tâche de l'appelant dans le code aux rĂ©sultats de mesure (par exemple, vous pouvez spĂ©cifier le nom du service externe qui a appelĂ© la mĂ©thode);
  • Ajouter aux rĂ©sultats des mesures des donnĂ©es sur le lieu oĂą la mesure des performances a Ă©tĂ© lancĂ©e (nom de fichier et numĂ©ro de ligne avec l'emplacement de l'appel dans le code);
  • Interrompre la mesure des performances de la mĂ©thode avant la fin de son exĂ©cution .

Les données obtenues à la suite de la mesure des performances des méthodes peuvent être utilisées pour analyser les performances de l'application (ses parties individuelles, à la fois internes - code natif et externes - le code des bibliothèques utilisées) et affichées sous une forme graphique qui vous convient.


Table des matières



Pour commencer


Pour utiliser la bibliothèque, installez le package NuGet dans votre projet:


Utilisation manuelle du gestionnaire de packages NuGet :


Install-Package Unchase.FluentPerformanceMeter 

Utilisation de la CLI .NET:


 dotnet add package Unchase.FluentPerformanceMeter --version {version} 

OĂą {version} est la version du package que vous souhaitez installer.
Par exemple, dotnet add package Unchase.FluentPerformanceMeter --version 1.0.0

Exemples d'utilisation


Mesure de la performance de la méthode


Voici un exemple simple d'utilisation de la bibliothèque (sans configuration ni paramètres supplémentaires) pour mesurer les performances de la SimpleWatchingMethodStart (Action) SimpleWatchingMethodStart contrôleur SimpleWatchingMethodStart (Controller) PerformanceMeterController Asp.Net Core 2.2 WebAPI . Pour ce faire, vous pouvez utiliser la méthode d'extension .WatchingMethod().Start() ou une fonctionnalité similaire .StartWatching() .
Depuis la version 1.0.5, vous pouvez également utiliser .WatchingMethod().Start(SimpleWatchingMethodStart) ou .StartWatching(SimpleWatchingMethodStart) avec le nom de la méthode.


Tous les exemples d'utilisation de la bibliothèque peuvent être trouvés dans les projets Unchase.FluentPerformanceMeter.Test* de ce référentiel .

 /// <summary> /// Test GET method with simple performance watching. /// </summary> [HttpGet("SimpleWatchingMethodStart")] public ActionResult SimpleWatchingMethodStart() { // for C# 8 you can use: //using var pm = PerformanceMeter<PerformanceMeterController>.StartWatching(); using (PerformanceMeter<PerformanceMeterController>.WatchingMethod().Start()) { // put your code with some logic here return Ok(); } } 

Pour obtenir les résultats des mesures de performances des méthodes publiques de la classe de contrôleur PerformanceMeterController , vous pouvez appeler la méthode suivante:


 /// <summary> /// Get methods performance info for this controller. /// </summary> /// <returns>Returns methods performance info.</returns> [HttpGet("GetPerformanceInfo")] [IgnoreMethodPerformance] public ActionResult<IPerformanceInfo> GetPerformanceInfo() { return Ok(PerformanceMeter<PerformanceMeterController>.PerformanceInfo); } 

Après avoir appelé la méthode SimpleWatchingMethodStart lors de l'appel de GetPerformanceInfo nous obtenons:


 { "methodCalls": [ { "methodName": "SimpleWatchingMethodStart", "elapsed": "00:00:00.0016350", "caller": "unknown", "startTime": "2019-12-06T10:27:27.3385385Z", "endTime": "2019-12-06T10:27:27.3401735Z", "customData": {}, "steps": [] } ], "totalActivity": [ { "methodName": "SimpleWatchingMethodStart", "callsCount": 1 } ], "currentActivity": [ { "methodName": "SimpleWatchingMethodStart", "callsCount": 0 } ], "uptimeSince": "2019-12-06T10:27:27.3370183Z", "className": "Unchase.FluentPerformanceMeter.TestWebAPI.Controllers.PerformanceMeterController", "methodNames": [ "SimpleWatchingMethodStart" ], "customData": {}, "timerFrequency": 10000000 } 

Mesure des performances des méthodes à l'aide de DiagnosticSource


À partir de la version v1.1.0 , il est devenu possible de mesurer les performances des méthodes dans une application AspNetCore MVC à l'aide de DiagnosticSource et de l'attribut spécial WatchingWithDiagnosticSourceAttribute .
Pour ce faire, ajoutez le package Unchase.FluentPerformanceMeter.AspNetCore.Mvc au projet NuGet et ajoutez le code suivant Ă  Startap.cs :


 public void ConfigureServices(IServiceCollection services) { // ... // allows to measure methods performance for class "MeasurableClass" and "MeasurableSecondClass" services.AddPerformanceDiagnosticObserver<MeasurableClass>(); services.AddPerformanceDiagnosticObserver<MeasurableSecondClass>(); // ... the same for another classes services.AddMvc(); // ... } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // ... app.UsePerformanceDiagnosticObserver(); app.UseMvc(); } 

Marquez ensuite avec l'attribut WatchingWithDiagnosticSourceAttribute ou des méthodes individuelles:


 [HttpGet("SimpleWatchingMethodStart")] [WatchingWithDiagnosticSource] public ActionResult SimpleWatchingMethodStart() { return Ok(); } 

ou toute la classe:


 [ApiController] [Route("api/v1/[controller]")] [Produces("application/json")] [SwaggerTag("Unchase.PerformanceMeter Test WebAPI Controller")] [WatchingWithDiagnosticSource] public class PerformanceMeterController : ControllerBase { // measurable methods } 

À partir de la version v1.2.0 , il est devenu possible d'ajouter des arguments d'appel aux données de mesure des performances de la méthode utilisateur dans une application AspNetCore MVC à l'aide de l'attribut spécial AddMethodArgumentsToCustomDataAttribute en conjonction avec l'attribut WatchingWithDiagnosticSourceAttribute :


 [HttpPost("SimpleWatchingMethodStartWithArgs")] [WatchingWithDiagnosticSource] [AddMethodArgumentsToCustomData("actionArguments")] public ActionResult SimpleWatchingMethodStartWithArgs(DTOArgument arg) { return Ok(); } 

Après avoir appelé la méthode SimpleWatchingMethodStartWithArgs lors de l'appel de GetPerformanceInfo nous obtenons:


 { "methodCalls": [ { "methodName": "SimpleWatchingMethodStartWithArgs", "elapsed": "00:00:00.0016350", "caller": "unknown", "startTime": "2019-12-06T10:27:27.3385385Z", "endTime": "2019-12-06T10:27:27.3401735Z", "customData": { "actionArguments": { "arg": { "data": "<string_in_DTOArgument>" } } }, "steps": [] } ], "totalActivity": [ { "methodName": "SimpleWatchingMethodStartWithArgs", "callsCount": 1 } ], "currentActivity": [ { "methodName": "SimpleWatchingMethodStartWithArgs", "callsCount": 0 } ], "uptimeSince": "2019-12-06T10:27:27.3370183Z", "className": "Unchase.FluentPerformanceMeter.TestWebAPI.Controllers.PerformanceMeterController", "methodNames": [ "SimpleWatchingMethodStartWithArgs" ], "customData": {}, "timerFrequency": 10000000 } 

Mesurer les performances de la méthode utilisée par la bibliothèque


Pour mesurer les performances de la méthode publique de la classe publique de la bibliothèque tierce utilisée, vous devez définir explicitement la classe elle-même et son nom de méthode:


 [HttpGet("GetThreadSleepPerformance")] public ActionResult<string> GetThreadSleepPerformance() { using (PerformanceMeter<Thread>.WatchingMethod(nameof(Thread.Sleep)).Start()) { Thread.Sleep(1000); } return Ok(PerformanceMeter<Thread>.PerformanceInfo.MethodCalls.FirstOrDefault(ta => ta.MethodName == nameof(Thread.Sleep))?.Elapsed); } 

La méthode exécutée renverra:


 "00:00:01.0033040" 

Vous pouvez obtenir des données sur l'appel de cette méthode via un appel:


 /// <summary> /// Get methods performance info for Thread class. /// </summary> /// <returns>Returns Thread methods performance info.</returns> [HttpGet("GetThreadPerformanceInfo")] [IgnoreMethodPerformance] public ActionResult<IPerformanceInfo> GetThreadPerformanceInfo() { return Ok(PerformanceMeter<Thread>.PerformanceInfo); } 

L'attribut IgnoreMethodPerformance conçu de sorte que la méthode qu'il IgnoreMethodPerformance n'est pas prise en compte lors de la mesure des performances.

En réponse à l'appel à cette méthode sera:


 { "methodCalls": [ { "methodName": "Sleep", "elapsed": "00:00:01.0033040", "caller": "unknown", "startTime": "2019-12-06T13:08:09.336624Z", "endTime": "2019-12-06T13:08:10.339928Z", "customData": {}, "steps": [] } ], "totalActivity": [ { "methodName": "Abort", "callsCount": 0 }, // ... { "methodName": "Sleep", "callsCount": 1 } // ... ], "currentActivity": [ { "methodName": "Abort", "callsCount": 0 }, // ... { "methodName": "Sleep", "callsCount": 1 } // ... ], "uptimeSince": "2019-12-06T13:08:09.3357028Z", "className": "System.Threading.Thread", "methodNames": [ "Abort", // ... "Sleep", // ... ], "customData": {}, "timerFrequency": 10000000 } 

Ajout de données supplémentaires (données personnalisées) et de pagination (étapes)


Vous pouvez ajouter des données supplémentaires (données personnalisées) pour toutes les mesures de performances des méthodes d'une classe particulière. Par exemple, dans le constructeur statique de la classe de contrôleur PerformanceMeterController :


 [ApiController] [Route("api/v1/[controller]")] public class PerformanceMeterController : ControllerBase { /// <summary> /// Static constructor. /// </summary> static PerformanceMeterController() { // add common custom data (string) to class performance information PerformanceMeter<PerformanceMeterController>.AddCustomData("Tag", "CustomTag"); // add common custom data (anonymous class) to class performance information PerformanceMeter<PerformanceMeterController>.AddCustomData("Custom anonymous class", new { Name = "Custom Name", Value = 1 }); } // ... actions } 

En outre, vous pouvez ajouter des données supplémentaires (données personnalisées) pour une mesure spécifique à l'aide de la méthode d'extension .WithSettingData.CustomData("<key>", <value>) (y compris via un attribut spécial de la méthode MethodCustomDataAttribute ) et pour chaque étape (étape ) de cette mesure, ajoutée à l'aide de la .Step("<step_name>") extension .Step("<step_name>") , à l'aide de la .AddCustomData("<key>", <value>) extension .AddCustomData("<key>", <value>) :


 /// <summary> /// Test GET method with simple performance watching (with steps). /// </summary> [HttpGet("SimpleStartWatchingWithSteps")] [MethodCustomData("Custom data from attribute", "Attr")] public ActionResult SimpleStartWatchingWithSteps() { using (var pm = PerformanceMeter<PerformanceMeterController> .WatchingMethod() .WithSettingData .CustomData("coins", 1) .CustomData("Coins sets", new { Gold = "Many", Silver = 5 }) .Start()) { // put your code with some logic here // add "Step 1" using (pm.Step("Step 1")) { Thread.Sleep(1000); } // add "Step 2" with custom data using (var pmStep = pm.Step("Step 2").AddCustomData("step2 custom data", "data!")) { // add "Step 3 in Step 2" using (pm.Step("Step 3 in Step 2")) { Thread.Sleep(1000); } // add custom data to "Step 2" pmStep.AddCustomData("step2 another custom data", "data2!"); // get and remove custom data from "Step 2" var customData = pmStep.GetAndRemoveCustomData<string>("step2 custom data"); // get custom data from "Step 2" (without removing) var anotherCustomData = pmStep.GetCustomData<string>("step2 another custom data"); // ... } } } 

Par conséquent, lorsque vous appelez GetPerformanceInfo nous obtenons:


 { "methodCalls": [ { "methodName": "SimpleStartWatchingWithSteps", "elapsed": "00:00:02.0083031", "caller": "unknown", "startTime": "2019-12-06T11:58:18.9006891Z", "endTime": "2019-12-06T11:58:20.9089922Z", "customData": { "Coins sets": { "gold": "Many", "silver": 5 }, "coins": 1, "Custom data from attribute": "Attr" }, "steps": [ { "stepName": "Step 1", "elapsed": "00:00:01.0009758", "startTime": "2019-12-06T11:58:18.9018272Z", "endTime": "2019-12-06T11:58:19.902803Z", "customData": {} }, { "stepName": "Step 3 in Step 2", "elapsed": "00:00:01.0004549", "startTime": "2019-12-06T11:58:19.9046523Z", "endTime": "2019-12-06T11:58:20.9051072Z", "customData": {} }, { "stepName": "Step 2", "elapsed": "00:00:01.0029596", "startTime": "2019-12-06T11:58:19.904534Z", "endTime": "2019-12-06T11:58:20.9074936Z", "customData": { "step2 another custom data": "data2!" } } ] } ], "totalActivity": [ { "methodName": "SimpleStartWatchingWithSteps", "callsCount": 1 } ], "currentActivity": [ { "methodName": "SimpleStartWatchingWithSteps", "callsCount": 0 } ], "uptimeSince": "2019-12-06T11:58:18.8801249Z", "className": "Unchase.FluentPerformanceMeter.TestWebAPI.Controllers.PerformanceMeterController", "methodNames": [ "SimpleStartWatchingWithSteps" ], "customData": { "Tag": "CustomTag", "Custom anonymous class": { "name": "Custom Name", "value": 1 } }, "timerFrequency": 10000000 } 

Exception de la mesure (Ignorer)


Vous pouvez ignorer des parties individuelles de la méthode pour mesurer les performances (à l'aide de .Ignore() ou .Executing().WithoutWatching().Start(<Action>) ), et ne pas enregistrer les étapes individuelles (méthode d'extension .StepIf("<step_name>", <minSaveMs>) ) s'ils ne remplissent pas la condition (le temps d'exécution de l'étape sera pris en compte dans le temps d'exécution de la méthode):


 using (var pm = PerformanceMeter<PerformanceMeterController>.WatchingMethod().Start()) { // put your code with some logic here // sleep 1 sec Thread.Sleep(1000); // ignore this block in performance watching using (pm.Ignore()) { Thread.Sleep(5000); } // skip this step with minSaveMs (not save, but consider duration in method performance watching) using (pm.StepIf("Skipped step", minSaveMs: 1000)) { Thread.Sleep(500); } // execute action without performance watching pm.Executing().WithoutWatching().Start(() => { Thread.Sleep(2000); }); return Ok(); } 

En conséquence, nous obtenons:


 { "methodCalls": [ { "methodName": "SimpleStartWatchingWithIgnored", "elapsed": "00:00:01.5080227", "caller": "unknown", "startTime": "2019-12-06T12:34:36.9187359Z", "endTime": "2019-12-06T12:34:38.4267586Z", "customData": {}, "steps": [] } ], "totalActivity": [ { "methodName": "SimpleStartWatchingWithIgnored", "callsCount": 1 } ], "currentActivity": [ { "methodName": "SimpleStartWatchingWithIgnored", "callsCount": 0 } ], "uptimeSince": "2019-12-06T12:34:36.9035129Z", "className": "Unchase.FluentPerformanceMeter.TestWebAPI.Controllers.PerformanceMeterController", "methodNames": [ "SimpleStartWatchingWithIgnored" ], "customData": { }, "timerFrequency": 10000000 } 

Ajout de commandes et d'actions


Pour ajouter une commande dont l'exécution sera garantie à la fin de la mesure des performances d'une méthode, vous devez créer une classe de commande qui implémentera l'interface IPerformanceCommand .
Dans le même temps, vous pouvez transférer des données arbitraires via le constructeur de la commande créée qui sera utilisée lors de son exécution. Par exemple:


 /// <summary> /// Custom executed command. /// </summary> public class ExecutedCommand : IPerformanceCommand { /// <summary> /// Executed commad name. /// </summary> public string CommandName => this.GetType().Name; private string _customString { get; } internal bool IsCommandExecuted { get; private set; } /// <summary> /// Constructor. /// </summary> /// <remarks> /// You can pass any data through the command constructor. /// </remarks> /// <param name="customString"></param> public ExecutedCommand(string customString) { this._customString = customString; } /// <summary> /// Execute command. /// </summary> /// <param name="performanceInfo"><see cref="IPerformanceInfo"/>.</param> public void Execute(IPerformanceInfo performanceInfo) { // for example, write to the debug console some information Debug.WriteLine(this.CommandName); Debug.WriteLine(this._customString); Debug.WriteLine($"Method names count: {performanceInfo.MethodNames.Count}"); this.IsCommandExecuted = true; } } 

Vous pouvez ajouter une commande (IPerformanceCommand) et une action (Action) pour qu'elles soient exécutées à la fin de la mesure, de la manière suivante:


 // custom "ExecutedCommand" will be executed after performance watching is completed using (PerformanceMeter<PerformanceMeterController> .WatchingMethod() .WithExecutingOnComplete .Command(new ExecutedCommand("bla-bla-bla")) .Action((pi) => { Debug.WriteLine($"Class name: {pi.ClassName}"); }) .Start()) { return Ok(); } 

Par conséquent, à la fin de la mesure des performances de la méthode dans la console de débogage , il affichera:


 ExecutedCommand bla-bla-bla Method names count: 13 Class name: Unchase.FluentPerformanceMeter.TestWebAPI.Controllers.PerformanceMeterController 

Ajout de gestionnaires d'exceptions


Si vous devez gérer les exceptions qui peuvent se produire lors de l'exécution d'une partie de la méthode dont les performances sont surveillées, vous devez ajouter un gestionnaire d'exceptions comme suit:


 using (var pm = PerformanceMeter<PerformanceMeterController>.StartWatching()) { // execute action throws Exception with exception handler pm.Executing() .WithExceptionHandler((ex) => Debug.WriteLine(ex.Message)) .Start(() => throw new Exception("Exception")); // execute action throws custom Exception with exception handler pm.Executing<CustomException>() .WithExceptionHandler((ex) => { Debug.WriteLine(ex.Message); }) .Start(() => { throw new CustomException("Custom exception was occured!"); }); return Ok(); } 

OĂą se trouve la classe CustomException , par exemple:


 /// <summary> /// Custom exception. /// </summary> public class CustomException : Exception { public CustomException(string message) : base(message) { } public CustomException(string message, Exception innerException) : base(message, innerException) { } public CustomException() { } } 

Par conséquent, la console de débogage affichera:


 Exception Custom exception was occured! 

En outre, vous pouvez spécifier un gestionnaire d'exceptions qui sera utilisé par défaut pour mesurer les performances de toute méthode de cette classe, par exemple, via le constructeur statique de la classe de contrôleur PerformanceMeterController :


 [ApiController] [Route("api/v1/[controller]")] public class PerformanceMeterController : ControllerBase { /// <summary> /// Static constructor. /// </summary> static PerformanceMeterController() { // set default exception handler for PerformanceMeterController class PerformanceMeter<PerformanceMeterController>.SetDefaultExceptionHandler((ex) => Debug.WriteLine(ex.Message)); } // ... actions } 

Réglage de la durée de stockage des données (Set Cache Time)


Vous pouvez définir la durée de stockage des données des mesures de performances des méthodes, après quoi ces données seront supprimées. Pour chaque classe pour laquelle la mesure est effectuée, ce temps est défini séparément. Par exemple, l'heure peut être définie via le constructeur statique de la classe de contrôleur PerformanceMeterController :


 [ApiController] [Route("api/v1/[controller]")] public class PerformanceMeterController : ControllerBase { /// <summary> /// Static constructor. /// </summary> static PerformanceMeterController() { // set cache time for PerformanceMeterController class PerformanceMeter<PerformanceMeterController>.SetMethodCallsCacheTime(5); } // ... actions } 

Ajout de données sur la méthode d'appel et le lieu de l'appel (et interruption de la mesure des performances)


  • Vous pouvez spĂ©cifier qui appelle la mĂ©thode Ă  l'aide de la mĂ©thode d'extension .CallerFrom("<caller_name>") (une chaĂ®ne ou IHttpContextAccessor lui est transmise ) ou un attribut spĂ©cial de la mĂ©thode [MethodCaller("<caller_name>")] . De plus, si Ă  la fois l'attribut et la mĂ©thode d'extension sont utilisĂ©s, la valeur sera prise de cette dernière.


  • La mĂ©thode d'extension .WithSettingData.CallerSourceData() utilisĂ©e pour ajouter un point d'appel pour mesurer les performances.


  • Pour arrĂŞter de mesurer les performances Ă  l'intĂ©rieur du bloc using , utilisez .StopWatching() mĂ©thode d'extension .StopWatching() ou la mĂ©thode Dispose() :



 [HttpPost("StartWatchingWithCallerName")] [MethodCaller("testCaller")] public ActionResult<string> StartWatchingWithCallerName([FromBody] string value) { // method performance info will reach with caller name (if internal HttpContextAccessor is null) using (var pm = PerformanceMeter<PerformanceMeterController> .WatchingMethod() .WithSettingData .CallerSourceData() .CallerFrom("Test caller") .Start()) { pm.StopWatching(); // stop watching here (or you can use "pm.Dispose();") Thread.Sleep(2000); return Ok(value); } } 

À la suite de l'appel de la méthode GetPerformanceInfo , GetPerformanceInfo obtiendrez:


 { "methodCalls": [ { "methodName": "StartWatchingWithCallerName", "elapsed": "00:00:00.0019172", "caller": "Test caller", "startTime": "2019-12-06T13:35:45.3164507Z", "endTime": "2019-12-06T13:35:45.3183679Z", "customData": { "customData123": 123, "callerSourceLineNumber": 525, "callerSource": "D:\\GitHub\\Unchase.FluentPerformanceMeter\\Unchase.FluentPerformanceMeter.TestWebAPI\\Controllers\\PerformanceMeterController.cs" }, "steps": [] } ], "totalActivity": [ { "methodName": "StartWatchingWithCallerName", "callsCount": 1 } ], "currentActivity": [ { "methodName": "StartWatchingWithCallerName", "callsCount": 0 } ], "uptimeSince": "2019-12-06T13:35:45.2601668Z", "className": "Unchase.FluentPerformanceMeter.TestWebAPI.Controllers.PerformanceMeterController", "methodNames": [ "StartWatchingWithCallerName" ], "customData": { }, "timerFrequency": 10000000 } 

Conclusion


Ainsi, la solution présentée nous permet d'automatiser partiellement la collecte d'informations sur les performances des méthodes d'application .NET d'une manière plutôt pratique. Les données collectées peuvent être visualisées d'une manière qui convient mieux à chaque développeur spécifique.


Bien sûr, la bibliothèque ne résout pas tous les problèmes liés à la collecte de données sur les performances des méthodes, mais cherche à simplifier les plus courants.


La bibliothèque est une solution open-source, toutes les suggestions et suggestions pour son développement ne sont que les bienvenues, tout comme les rapports de bogues (tout le monde peut suivre le lien ; l'auteur sera reconnaissant pour toute aide!).

Source: https://habr.com/ru/post/fr485198/


All Articles