0

我有一个应用程序洞察配置,我正在尝试在 .NET 4.8 WPF 应用程序中工作。一切似乎都可以正常传输(包括实时指标数据),但不幸的是,我无法成功让系统传输我的 SQL 查询以及 EntityFramework6 正在执行的依赖信息。

我注意到在以下链接中它引用了

对于 ASP.NET 应用程序,完整的 SQL 查询文本是在字节码检测的帮助下收集的,这需要使用检测引擎或使用 Microsoft.Data.SqlClient NuGet 包而不是 System.Data.SqlClient 库。

显然这对我来说是不可能的(我不认为?),因为我使用的是 EntityFramework(这取决于 System.Data.SqlClient),但我已经安装了 Microsoft.ApplicationInsights.Agent_**,我认为这是解决这个问题的方法上面的链接建议。

此外,当我查看 Azure 中提供的数据时,我注意到它被标记为 rddf:2.17.0-32,这表明代理无法正常工作。

在此处输入图像描述

我的初始化代码如下所示:

public static TelemetryConfiguration CreateConfig(string instrumentationKey, string authenticationApiKey)
{
    var config = new TelemetryConfiguration()
    {
        ConnectionString = $"InstrumentationKey={instrumentationKey};IngestionEndpoint=https://australiaeast-0.in.applicationinsights.azure.com/",
        TelemetryChannel = new ServerTelemetryChannel()
        {
            DeveloperMode = true
        },
               
    };

    var dependencyTrackingModule = new DependencyTrackingTelemetryModule()
    {
        EnableSqlCommandTextInstrumentation = true
    };

    // prevent Correlation Id to be sent to certain endpoints. You may add other domains as needed.
    dependencyTrackingModule.ExcludeComponentCorrelationHttpHeadersOnDomains.Add("core.windows.net");

    // enable known dependency tracking, note that in future versions, we will extend this list. 
    dependencyTrackingModule.IncludeDiagnosticSourceActivities.Add("Microsoft.Azure.ServiceBus");
    dependencyTrackingModule.IncludeDiagnosticSourceActivities.Add("Microsoft.Azure.EventHubs");

    // initialize the module
    dependencyTrackingModule.Initialize(config);

    QuickPulseTelemetryProcessor quickPulseProcessor = null;
    config.DefaultTelemetrySink.TelemetryProcessorChainBuilder
        .Use((next) =>
        {
            quickPulseProcessor = new QuickPulseTelemetryProcessor(next);
            return quickPulseProcessor;
        })
        .Build();

    var quickPulseModule = new QuickPulseTelemetryModule()
    {
        AuthenticationApiKey = authenticationApiKey
    };

    quickPulseModule.Initialize(config);
    quickPulseModule.RegisterTelemetryProcessor(quickPulseProcessor);

    config.TelemetryInitializers.Add(new HttpDependenciesParsingTelemetryInitializer());
    config.TelemetryInitializers.Add(new BuildInfoConfigComponentVersionTelemetryInitializer());

    return config;
}

任何人都可以就我可能做错的事情提供任何意见吗?

4

1 回答 1

0

当我们都在等待洞察团队的潜在解决方案时,我想我会分享我的解决方案。

首先,我关心的是在跟踪数据库操作时更好地控制所提供的数据。我能够在 EntityFramework 中找到一个简洁的小功能,称为DbInterception.

这个单例允许您注册拦截器,这些拦截器可以跟踪和分析提供给 EntityFramework 的查询。

实现最终就像这样简单:

internal class InsightsOperation 
{
    public InsightsOperation(DbCommand command, Stopwatch stopwatch)
    {
        this.Command = command;
        this.Stopwatch = stopwatch;
    }

    public DbCommand Command { get; }
    public Stopwatch Stopwatch { get; }
    public DateTime StartTime { get; } = DateTime.UtcNow;
}

public class AppInsightsInterceptor : IDbCommandInterceptor
{

    private ConcurrentDictionary<Guid, InsightsOperation> _pendingOperations = new ConcurrentDictionary<Guid, InsightsOperation>();
    private ITelemetryManager _telemetryManager;

    public AppInsightsInterceptor(ITelemetryManager telemetryManager)
    {
        this._telemetryManager = telemetryManager ?? throw new ArgumentNullException(nameof(telemetryManager));
    }

    private void StartTimingOperation<T>(DbCommand command, DbCommandInterceptionContext<T> interceptionContext)
    {
        if (!(command is SQLiteCommand))
        {
            var id = Guid.NewGuid();
            var stopwatch = Stopwatch.StartNew();

            interceptionContext.SetUserState(nameof(AppInsightsInterceptor), id);
            this._pendingOperations.TryAdd(id, new InsightsOperation(command, stopwatch));
        }
    }

    private void StopTimingOperation<T>(DbCommand command, DbCommandInterceptionContext<T> interceptionContext)
    {
        if (!(command is SQLiteCommand))
        {
            var id = (Guid)interceptionContext.FindUserState(nameof(AppInsightsInterceptor));
            if (this._pendingOperations.TryRemove(id, out InsightsOperation operation))
            {
                operation.Stopwatch.Stop();
                this._telemetryManager.TrackDependency(command.CommandType.ToString(),
                    "SQL",
                    command.CommandText,
                    new DateTimeOffset(operation.StartTime),
                    operation.Stopwatch.Elapsed,
                    interceptionContext.Exception == null);
            }
        }
    }

    public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
        this.StopTimingOperation(command, interceptionContext);
    }

    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
        this.StartTimingOperation(command, interceptionContext);            
    }

    public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        this.StopTimingOperation(command, interceptionContext);
    }

    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
    {
        
        this.StartTimingOperation(command, interceptionContext);
            
    }

    public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
        this.StopTimingOperation(command, interceptionContext);
    }

    public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
    {
        this.StartTimingOperation(command, interceptionContext);
    }
}

请注意,此注册是一个单例,如果您想排除数据,您需要了解所有 DbContext 实例将命中拦截器。

就我而言,我想排除代码中看到的 SQLite 查询。

于 2021-01-02T08:25:16.017 回答