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 中看到该交易的数据。