Reputation: 18556
I want certain exceptions to be logged to application insights as warnings instead of exceptions. Unfortunately, I can't change the code that throws the exceptions, so I created a TelemetryProcessor instead (based on this answer).
However, the TraceTelemetry
created by this code never reaches Application Insights. I checked both the live metrics and waited a couple of minutes for the entries to show up in search.
My guess would be that I am missing some things like the proper context, but I am unsure what to copy. The Context
property is readonly, so I can't simply reuse it.
public class ExceptionTelemetryProcessor : ITelemetryProcessor
{
private ITelemetryProcessor Next { get; set; }
public ExceptionTelemetryProcessor(ITelemetryProcessor next)
{
Next = next;
}
public void Process(ITelemetry item)
{
if (item is ExceptionTelemetry exceptionTelemetry
&& exceptionTelemetry.Exception is Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException bhre
&& bhre.StatusCode == 408)
{
// Track exception as warning instead
var traceTelemetry = new TraceTelemetry(exceptionTelemetry.Exception.Message, SeverityLevel.Warning);
Next.Process(traceTelemetry);
}
else
{
Next.Process(item);
}
}
}
Upvotes: 4
Views: 1080
Reputation: 1317
If you copy all data from the original exception telemetry into trace telemetry and pass it further - it will be logged (crucial are Context.InstrumentationKey and Timestamp):
private ITelemetry ToTraceTelemetry(ExceptionTelemetry exceptionTelemetry)
{
var traceTelemetry = new TraceTelemetry(exceptionTelemetry.Message, SeverityLevel.Warning);
foreach (var telemetryProperty in exceptionTelemetry.Properties)
{
traceTelemetry.Properties.Add(telemetryProperty);
}
traceTelemetry.Timestamp = exceptionTelemetry.Timestamp;
traceTelemetry.Extension = exceptionTelemetry.Extension;
traceTelemetry.ProactiveSamplingDecision = exceptionTelemetry.ProactiveSamplingDecision;
traceTelemetry.Sequence = traceTelemetry.Sequence;
traceTelemetry.Context.InstrumentationKey = exceptionTelemetry.Context.InstrumentationKey;
traceTelemetry.Context.Flags = exceptionTelemetry.Context.Flags;
traceTelemetry.Context.Location.Ip = exceptionTelemetry.Context.Location.Ip;
traceTelemetry.Context.Cloud.RoleInstance = exceptionTelemetry.Context.Cloud.RoleInstance;
traceTelemetry.Context.Cloud.RoleName = exceptionTelemetry.Context.Cloud.RoleName;
traceTelemetry.Context.Component.Version = exceptionTelemetry.Context.Component.Version;
traceTelemetry.Context.Device.Id = exceptionTelemetry.Context.Device.Id;
traceTelemetry.Context.Device.Model = exceptionTelemetry.Context.Device.Model;
traceTelemetry.Context.Device.OemName = exceptionTelemetry.Context.Device.OemName;
traceTelemetry.Context.Device.OperatingSystem = exceptionTelemetry.Context.Device.OperatingSystem;
traceTelemetry.Context.Device.Type = exceptionTelemetry.Context.Device.Type;
traceTelemetry.Context.Operation.Id = exceptionTelemetry.Context.Operation.Id;
traceTelemetry.Context.Operation.CorrelationVector = exceptionTelemetry.Context.Operation.CorrelationVector;
traceTelemetry.Context.Operation.Name = exceptionTelemetry.Context.Operation.Name;
traceTelemetry.Context.Operation.ParentId = exceptionTelemetry.Context.Operation.ParentId;
traceTelemetry.Context.Operation.SyntheticSource = exceptionTelemetry.Context.Operation.SyntheticSource;
traceTelemetry.Context.Session.Id = exceptionTelemetry.Context.Session.Id;
traceTelemetry.Context.Session.IsFirst = exceptionTelemetry.Context.Session.IsFirst;
traceTelemetry.Context.User.Id = exceptionTelemetry.Context.User.Id;
traceTelemetry.Context.User.AccountId = exceptionTelemetry.Context.User.AccountId;
traceTelemetry.Context.User.AuthenticatedUserId = exceptionTelemetry.Context.User.AuthenticatedUserId;
traceTelemetry.Context.User.UserAgent = exceptionTelemetry.Context.User.UserAgent;
return traceTelemetry;
}
Then just call it:
public void Process(ITelemetry item)
{
if (item is ExceptionTelemetry exceptionTelemetry
&& other_condition)
{
item = ToTraceTelemetry(exceptionTelemetry);
}
Next.Process(item);
}
Upvotes: 3
Reputation: 30035
The reason here is that it lacks context instrumentation key as Peter points out.
You can debug your code(set checkpoint in your custom Telemetry Processor class) in visual studio, and in the output window, you can see the instrumentation key is not configured. Screenshot as below:
Please change your code like below:
public void Process(ITelemetry item)
{
if (item is ExceptionTelemetry exceptionTelemetry
&& other_condition)
{
// Track exception as warning instead
var traceTelemetry = new TraceTelemetry(exceptionTelemetry.Exception.Message, SeverityLevel.Warning);
//add this line of code to send the trace message.
new TelemetryClient().TrackTrace(traceTelemetry);
//Note that, you should remove the Next.Process() method here, or it will reproduce another same message with the above line of code
//Next.Process(traceTelemetry);
}
else
{
Next.Process(item);
}
}
Upvotes: 1