This is the first in a series of posts covering measuring a .Net Core application. If you want to try follow the code then you can have a look at this repo: Blog-Diagnostics.
This is the plan for the series. I will update this with links as it evolves.
- Setting up local diagnostics tools
- Using dotnet-counters
- dotnet-counters with a custom provider
- Using dotnet-gcdump to investigate memory leaks
- Creating a dump file when a ASP.NET Core application crashes
There are quite a few diagnostic tools that you can install and use for your .net core applications to measure performance and other metrics and I will try go through the ones I know. One nice way to use them is to link them to a project with a local tool-manifest file. You can then check it into source control and anyone using your project can just restore them.
In this project I used the command line in the same folder as the main csproj file and ran the following commands.
dotnet new tool-manifest
dotnet tool install dotnet-counters
dotnet tool install dotnet-dump
dotnet tool install dotnet-gcdump
dotnet tool install dotnet-trace
dotnet tool install dotnet-sos
This creates a json file in a .config folder in the following format.
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-counters": {
"version": "3.1.120604",
"commands": [
"dotnet-counters"
]
},
"dotnet-dump": {
"version": "3.1.122203",
"commands": [
"dotnet-dump"
]
},
"dotnet-gcdump": {
"version": "3.1.120604",
"commands": [
"dotnet-gcdump"
]
},
"dotnet-trace": {
"version": "3.1.120604",
"commands": [
"dotnet-trace"
]
},
"dotnet-sos": {
"version": "3.1.122203",
"commands": [
"dotnet-sos"
]
}
}
}
Now anyone checking out the project can just run dotnet tool restore
and it will all be downloaded and made available.
I would like to run most of these from the docker container since that is most likely where the live code will run. One small problem that I had was that these tools require the SDK installed to be able to run them. Disclaimer: I saw some posts from people who managed to copy the dependencies needed into the runtime image but I never got it to work.
Since this is all just working on my machine I just updated the one that visual studio created to just use the SDK as the base image without playing too much with the multi stage builds.
For the sample project I initially have a Person controller that has a get endpoint that awaits a person result. I will most probably expand this when I go through some of the tools but this is the initial version.
[Route("api/[controller]")]
[ApiController]
public class PersonController : ControllerBase
{
readonly IPersonService _personService;
public PersonController(IPersonService personService)
{
_personService = personService;
}
[HttpGet]
[Route("{name}")]
public async Task<IActionResult> Get(string name)
{
return Ok(await _personService.GetAsync(name));
}
}
public class PersonService : IPersonService
{
public async Task<Person> GetAsync(string name)
{
await Task.Delay(TimeSpan.FromSeconds(1));
return new Person { Name = name, Age = 18 };
}
}
public interface IPersonService
{
Task<Person> GetAsync(string name);
}
When I start the application I will sh into the container and run the command.
You should then get a response
Tool 'dotnet-counters' (version '3.1.120604') was restored. Available commands: dotnet-counters
Tool 'dotnet-dump' (version '3.1.122203') was restored. Available commands: dotnet-dump
Tool 'dotnet-gcdump' (version '3.1.120604') was restored. Available commands: dotnet-gcdump
Tool 'dotnet-trace' (version '3.1.120604') was restored. Available commands: dotnet-trace
Tool 'dotnet-sos' (version '3.1.122203') was restored. Available commands: dotnet-sos
And now you can have some fun.