I read this documentation: https://docs.microsoft.com/en-us/azure/application-insights/app-insights-api-custom-events-metrics
There are many different API method to track exceptions, track trace etc..
I have a ASP.NET MVC 5 application. For example, I have the following controller method (called by ajax):
[AjaxErrorHandling]
[HttpPost]
public async Task SyncDriverToVistracks(int DriverID)
{
if ([condition])
{
// some actions here
try
{
driver.VistrackId = await _vistracksService.AddNewDriverToVistrackAsync(domain);
await db.SaveChangesAsync();
}
catch (VistracksApiException api_ex)
{
// external service throws exception type VistracksApiException
throw new AjaxException("vistracksApiClient", api_ex.Response.Message);
}
catch (VistracksApiCommonException common_ex)
{
// external service throws exception type VistracksApiCommonException
throw new AjaxException("vistracksApiServer", "3MD HOS server is not available");
}
catch (Exception ex)
{
// something wrong at all
throw new AjaxException("General", ex.Message);
}
}
else
{
// condition is not valid
throw new AjaxException("General", "AccountId is not found");
}
}
this method throws AjaxException if something wrong (which catch by AjaxErrorHandling and then return something json response to client).
Now I want to add telemetry for logging, analyzing exceptions and observe on client events.
So, I added the following:
[AjaxErrorHandling]
[HttpPost]
public async Task SyncDriverToVistracks(int DriverID)
{
telemetryClient.TrackEvent("Sync driver", new Dictionary<string, string> { { "ChangedBy", User.Identity.Name }, { "DriverID", DriverID.ToString() } }, null);
if ([condition])
{
// some actions here
try
{
driver.VistrackId = await _vistracksService.AddNewDriverToVistrackAsync(domain);
await db.SaveChangesAsync();
}
catch (VistracksApiException api_ex)
{
// external service throws exception type VistracksApiException
telemetryClient.TrackTrace("VistracksApiException", new Dictionary<string, string> {
{ "ChangedBy", User.Identity.Name },
{ "DriverID", DriverID.ToString() },
{ "ResponseCode", api_ex.Response.Code.ToString() },
{ "ResponseMessage", api_ex.Response.Message },
{ "ResponseDescription", api_ex.Response.Description }
});
telemetryClient.TrackException(api_ex);
throw new AjaxException("vistracksApiClient", api_ex.Response.Message);
}
catch (VistracksApiCommonException common_ex)
{
// external service throws exception type VistracksApiCommonException
telemetryClient.TrackTrace("VistracksApiCommonException", new Dictionary<string, string> {
{ "ChangedBy", User.Identity.Name },
{ "DriverID", DriverID.ToString() },
{ "Message", common_ex.Message },
});
telemetryClient.TrackException(common_ex);
throw new AjaxException("vistracksApiServer", "3MD HOS server is not available");
}
catch (Exception ex)
{
// something wrong at all
telemetryClient.TrackTrace("Exception", new Dictionary<string, string> {
{ "ChangedBy", User.Identity.Name },
{ "DriverID", DriverID.ToString() },
{ "Message", ex.Message },
});
telemetryClient.TrackException(ex);
throw new AjaxException("General", ex.Message);
}
}
else
{
telemetryClient.TrackTrace("ConditionWrong", new Dictionary<string, string> {
{ "ChangedBy", User.Identity.Name },
{ "DriverID", DriverID.ToString() },
{ "Message", "AccountId is not found" },
});
// condition is not valid
throw new AjaxException("General", "AccountId is not found");
}
}
by the following line:
telemetryClient.TrackEvent("Sync driver", new Dictionary<string, string> { { "ChangedBy", User.Identity.Name }, { "DriverID", DriverID.ToString() } }, null);
I just "log" client event, that the method was called. Just for statistics.
In each "catch" block I try to write trace with different parameters and write exception:
telemetryClient.TrackTrace("trace name", new Dictionary<string, string> {
{ "ChangedBy", User.Identity.Name },
....
});
telemetryClient.TrackException(ex);
Is it necessary? Or just need to track only exception? Then I lose different info, like who try to add these changes etc... When each of these methods should be used?
This is the best practice for 2.5.1 AI SDK. Will highlight parts which might not be required in upcoming AI SDK releases.
The right way to do end-to-end tracing is to rely on new Activity class in .NET framework. Until AI supports Activity.Tags (https://github.com/Microsoft/ApplicationInsights-dotnet/issues/562) you need to propagate them manually using TelemetryInitializer:
public class ActvityTagsTelemetryInitializer : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
Activity current = Activity.Current;
if (current == null)
{
current = (Activity)HttpContext.Current?.Items["__AspnetActivity__"];
}
while (current != null)
{
foreach (var tag in current.Tags)
{
if (!telemetry.Context.Properties.ContainsKey(tag.Key))
{
telemetry.Context.Properties.Add(tag.Key, tag.Value);
}
}
current = current.Parent;
}
}
}
Then register it in ApplicationInsights.config:
<TelemetryInitializers>
...
<Add Type="<namespace>.ActvityTagsTelemetryInitializer, <assemblyname>"/>
</TelemetryInitializers>
Then you can populate proper tags:
[AjaxErrorHandling]
[HttpPost]
public async Task SyncDriverToVistracks(int DriverID)
{
Activity.Current.AddTag("DriverID", DriverID.ToString());
Activity.Current.AddTag("UserID", User.Identity.Name);
try
{
if ([condition])
{
// some actions here
try
{
// If below call is HTTP then no need to use StartOperation
using (telemetryClient.StartOperation<DependencyTelemetry>("AddNewDriverToVistrackAsync"))
{
driver.VistrackId = await _vistracksService.AddNewDriverToVistrackAsync(domain);
}
// If below call is HTTP then no need to use StartOperation
using (telemetryClient.StartOperation<DependencyTelemetry>("SaveChanges"))
{
await db.SaveChangesAsync();
}
}
catch (VistracksApiException api_ex)
{
// external service throws exception type VistracksApiException
throw new AjaxException("vistracksApiClient", api_ex.Response.Message);
}
catch (VistracksApiCommonException common_ex)
{
// external service throws exception type VistracksApiCommonException
throw new AjaxException("vistracksApiServer", "3MD HOS server is not available");
}
catch (Exception ex)
{
// something wrong at all
throw new AjaxException("General", ex.Message);
}
}
else
{
// condition is not valid
throw new AjaxException("General", "AccountId is not found");
}
}
catch (Exception ex)
{
// Upcoming 2.6 AI SDK will track exceptions for MVC apps automatically.
telemetryClient.TrackException(ex);
throw;
}
}
You should have the following telemetry:
All telemetry will be stamped with ChangedBy and DriverID