This is the third 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
Now that we have tried using the built in providers for the dotnet-counters tool, lets try create our own custom one.
You can achieve this by using a custom EventSource. You just need to create a class that implements EventSource and populate different types of counters depending on what you are trying to achieve.
The event source that I created will report as Diagnostics.Person
and does a silly measure of the amount of gets of people with steve in their name. Way too many steves around ;)
[EventSource(Name = PersonEventSource.SourceName)]
public class PersonEventSource : EventSource
{
readonly EventCounter steveCreatedCounter;
int steveCreatedCount = 0;
readonly EventCounter notSteveCreatedCounter;
int notSteveCreatedCount = 0;
public PersonEventSource()
{
steveCreatedCounter = new EventCounter("Steve created", this);
notSteveCreatedCounter = new EventCounter("Not Steve created", this);
}
const string SourceName = "Diagnostics.Person";
[Event(1, Level= EventLevel.Informational)]
public void Created(string name)
{
if (name.Contains("Steve", StringComparison.InvariantCultureIgnoreCase))
{
steveCreatedCounter.WriteMetric(Interlocked.Increment(ref steveCreatedCount));
}
else
{
notSteveCreatedCounter.WriteMetric(Interlocked.Increment(ref notSteveCreatedCount));
}
}
}
I then register it as a singleton in startup ConfigureServices.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<PersonEventSource>();
services.AddScoped<IPersonService, PersonService>();
}
Then injected it into my service.
public class PersonService : IPersonService
{
private readonly PersonEventSource personEventSource;
public PersonService(PersonEventSource personEventSource)
{
this.personEventSource = personEventSource;
}
public async Task<Person> GetAsync(string name)
{
await Task.Delay(TimeSpan.FromSeconds(1));
personEventSource.Created(name);
return new Person { Name = name, Age = 18 };
}
}
After restarting the application I can run the counters command as:
dotnet counters monitor -p 24 --providers Diagnostics.Person
This will give the following result after a little prodding.
Obviously not a real example but hopefully you can see the power. An example I could use at work is for an application processing realtime trades. I could add metrics on the average process time per asset class.