Elastic APM 显示在 .Net Core API 端点上执行的 SQL 查询总数
Elastic APM show total number of SQL Queries executed on .Net Core API Endpoint
目前 Elastic 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 中看到该交易的数据。
目前 Elastic 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 中看到该交易的数据。