问题描述
我有一个应用程序洞察配置,我正在尝试在 .NET 4.8 WPF 应用程序中工作。一切似乎都在传输良好(包括实时指标数据),但不幸的是,我无法成功地让系统传输我的 sql 查询以及 EntityFramework6 正在执行的依赖关系信息。
我注意到在 following link 上它引用了
对于 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;
}
任何人都可以就我可能做错的事情提供任何意见吗?
解决方法
虽然我们都在等待洞察团队的潜在解决方案,但我想我会分享我的解决方案。
我主要关心的是在跟踪数据库操作时对提供的数据有更多的控制。我能够在 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 查询。