问题描述
当前已使用以下命令设置了弹性Apm:app.UseAllElasticApm(Configuration);
,它可以正常工作。我一直在试图找到一种方法来准确记录通过Entity Framework为每个事务运行的SQL查询数量。
理想情况下,在Kibana中查看Apm数据时,元数据标签可能只包含EntityFramework.ExecutedsqlQueriesCount
。
当前在.Net Core 2.2.3上
解决方法
您可以使用的一件事是Filter API。
有了它,您就可以在将所有事务和跨度发送到APM服务器之前对其进行访问。
对于给定的交易,您无法遍历所有范围,因此您需要进行一些调整-为此,我在示例中使用了Dictionary
。
var numberOfSqlQueries = new Dictionary<string,int>();
Elastic.Apm.Agent.AddFilter((ITransaction transaction) =>
{
if (numberOfSqlQueries.ContainsKey(transaction.Id))
{
// We make an assumption here: we assume that all SQL requests on a given transaction end before the transaction ends
// this in practice means that you don't do any "fire and forget" type of query. If you do,you need to make sure
// that the numberOfSqlQueries does not leak.
transaction.Labels["NumberOfSqlQueries"] = numberOfSqlQueries[transaction.Id].ToString();
numberOfSqlQueries.Remove(transaction.Id);
}
return transaction;
});
Elastic.Apm.Agent.AddFilter((ISpan span) =>
{
// you can't relly filter whether if it's done by EF Core,or another database library
// but you have all sorts of other info like db instance,also span.subtype and span.action could be helpful to filter properly
if (span.Context.Db != null && span.Context.Db.Instance == "MyDbInstance")
{
if (numberOfSqlQueries.ContainsKey(span.TransactionId))
numberOfSqlQueries[span.TransactionId]++;
else
numberOfSqlQueries[span.TransactionId] = 1;
}
return span;
});
这里的事物:
- 我假设您不会执行“即兴即忘”类型的查询,如果您这样做,则需要处理那些额外的问题
- 该计数并非真正针对EF Core查询,但您拥有诸如数据库名称,数据库类型(mssql等)之类的信息-希望以此为基础,您将能够过滤所需的查询。
- 使用
transaction.Labels["NumberOfSqlQueries"]
,我们将标签添加到给定的交易中,您将可以在Kibana上的交易中看到此数据。