在遥测处理器中更改遥测类型

Change telemetry type in Telemetry Processor

我希望将某些异常作为警告而不是异常记录到应用程序洞察中。不幸的是,我无法更改引发异常的代码,因此我创建了一个 TelemetryProcessor ()。

但是,此代码创建的 TraceTelemetry 永远不会到达 Application Insights。我检查了两个实时指标并等待了几分钟让条目显示在搜索中。

我的猜测是我遗漏了一些东西,比如正确的上下文,但我不确定要复制什么。 Context 属性 是只读的,所以我不能简单地重用它。

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);
            }
        }
    }

这里的原因是它缺少上下文检测密钥,正如彼得指出的那样。

您可以在 visual studio 中调试您的代码(在您的自定义遥测处理器 class 中设置检查点),在输出 window 中,您可以看到检测密钥未配置.截图如下:

更改您的代码如下:

    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);
        }

    }

如果您将原始异常遥测中的所有数据复制到跟踪遥测中并进一步传递 - 它将被记录(关键是 Context.InstrumentationKey时间戳):

    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;
    }

然后直接调用它:

public void Process(ITelemetry item)
{
    if (item is ExceptionTelemetry exceptionTelemetry
        && other_condition)
    {
        item = ToTraceTelemetry(exceptionTelemetry);
    }

    Next.Process(item);
}