One of the most important things when it comes to your application's health is logging information. Whether that is external dependencies, performance metrics or errors, logging is one of the fundamental things that your application should have.
I have too much information and I don't want more. - No one, ever
One of the most requested features in my workplace when I was showcasing Cosmonaut was logging. Initially I didn't have logging in place and that's because I thought that the only way to add logging is to add external packages which is something I really didn't want to do, mainly because I don't wanna needlessly increase the minimum .NET Standard requirements.
Turns out, Microsoft has my back.
Reminder: Everything you are about to read, is already included in Cosmonaut. If you are already using it you don't need to worry about adding this but it's still good to read this blog to learn how it works behind the scenes.
System.Diagnostics is part of the .NET Standard and it contains everything you need in order to create an Event Source. That event source can then be used with your CosmosDB calls in order to offer the basic logging solution.
Here is what my event source for Cosmonaut looks like:
As you can see, I am extending the
EventSource class to create
Once I do that I can call the Singleton
CosmosEventSource from wherever I want and use the
CosmosEventSource.EventSource.TrackError methods to track successful or failed CosmosDB calls.
An example of how to invoke a CosmosDB dependency call with logging looks something like this:
As we can see we have all the data we need including time metrics for the action.
I created some extension methods for my needs, which you can find here.
This is how CosmonautClient calls CosmosDB.
You can find the complete Diagnostics solution that I use for Cosmonaut here.
It contains some handy extension methods and examples on how to use it.
You can also add more custom data by adding more entries in the
EventMetadata.Properties dictionary, which is translated to
This however doesn't mean that our data is logged in a place that's useful for us yet. Let's see what we can do to log this data somewhere.
My APM of choice is Application Insights because Azure, that's why.
In all seriousness, Application Insights gets better and better every day and with it's querying and visualisation power makes retrieving data really easy. It's also really cheap and it has kick ass integration with Visual Studio and .NET.
What we need to do is to create an
EventListener that implements
ITelemetryModule in order to capture those Event Source events and add them in Application Insights.
The module's code is pretty simple. First we need to override the
OnEventSourceCreated method in order to Enable the events for our EventSource. The next method we need to override is the
OnEventWritten which is the method called every time we write an event in the event source.
Simply converting the event into a dependency and calling our telemetry client's
TrackDependency method will do the trick.
var dependencyTelemetry = CreateDependency(eventData); _telemetryClient.TrackDependency(dependencyTelemetry);
Note: Due to how the Application Insights SDK internal buffer logic works, the event won't be flushed to App Insights instantly but rather when one of the three things happen: 1) You manually call the
Flush method of the client. 2) 30 seconds (or whatever the interval is) goes by. 3) The event buffer is full.
Here is the full code of Cosmonaut.ApplicationInsights telemetry module.
In order to activate it you either need to register it in your IoC or simply call the
Keep in mind however that if you already have an ApplicationInsights TelemetryClient registered you should NOT instantiate a new
TelemetryConfiguration object but rather use the
If however you don't have an active one simply create one like this:
Here is an example of how the end-to-end transaction for a simple GET request on a web api with 3 cosmosdb calls looks like:
As you can see, all the important information is logged such as time taken for each request, which class and method was called, request charge, activity id, how many documents where returned and also the query that was executed.
You can also do flexible querying in the analytics region of Application Insights.
or visualise things like your average request charge every n seconds
Hope this helps you learn more about your services.