公共 API

编辑

Elastic APM .NET 代理的公共 API 允许您自定义和手动创建 span 和事务,以及跟踪错误。

初始化

编辑

API 不需要显式的代理初始化,代理初始化是可选的。 Elastic.Apm.Agent.IsConfigured 属性允许您检查代理是否已初始化。

隐式代理初始化

编辑

如果您没有显式初始化代理,它将以默认组件设置启动。这意味着代理将从环境变量中读取配置设置。如果您没有设置环境变量,代理将使用默认值。例如,ServerUrl 默认值为 https://127.0.0.1:8200

代理的这种隐式初始化发生在对 Elastic.Apm.Agent 类的第一次调用时。

一个例外是 Elastic.Apm.Agent.IsConfigured 方法。此方法永远不会初始化代理,它仅检查代理是否已初始化。

初始化的另一个示例是,当您通过设置代理说明中的一种特定于技术的方法启用代理时。特别是当在 ASP.NET Core 中调用 UseElasticApmUseAllElasticApm 方法时,或者在 IIS 应用程序中初始化 IIS 模块时。

默认的代理设置应涵盖大多数用例,并且配置代理的主要方法是通过环境变量。

显式代理初始化

编辑

如果您想替换其中一个代理组件,可以通过调用 Elastic.Apm.Agent.Setup(AgentComponents) 方法来实现。在 AgentComponents 中,您可以将以下可选组件传递给代理

  • IApmLogger:一个日志记录器实现,用于打印日志消息。默认值:控制台记录器。
  • IPayloadSender:一个组件,它接收所有捕获的事件,如 span、事务和指标。默认实现将所有事件序列化并发送到 Elastic APM Server
  • IConfigurationReader:一个组件,用于读取代理配置设置。默认实现通过环境变量读取配置。

在 ASP.NET Core 的情况下,当您注册代理时,UseElasticApmUseAllElasticApm 方法都会通过在内部调用 Elastic.Apm.Agent.Setup 方法来隐式初始化代理。在该设置中,如果您将 IConfiguration 实例传递给该方法,IConfigurationReader 实现将从 ASP.NET Core 配置系统中读取配置。 IApmLogger 实例还将通过集成到 ASP.NET Core 日志记录系统中来记录。

自动检测与公共代理 API 相结合

编辑

使用 Elastic.Apm.Agent.Subscribe(params IDiagnosticsSubscriber[] subscribers) 方法,您可以为支持的库启用自动检测。

在 ASP.NET Core 的情况下,当您使用 UseAllElasticApm 方法启用代理时,代理将自动执行此操作。

对于典型的控制台应用程序,您需要在应用程序中的某个位置(最好是在启动代码中)手动调用 Elastic.Apm.Agent.Subscribe(params IDiagnosticsSubscriber[] subscribers) 方法。

IDiagnosticsSubscriber 实现由代理提供,它们订阅诊断源事件或其他数据源,以便自动捕获事件。

一些示例

  • HttpDiagnosticsSubscriber:通过 HttpClientHttpWebRequest 捕获 HTTP 调用

    Agent.Subscribe(new HttpDiagnosticsSubscriber());
  • EfCoreDiagnosticsSubscriber:通过 Entity Framework Core 捕获数据库调用
  • SqlClientDiagnosticSubscriber:通过 SqlClient 捕获数据库调用

当代理配置为Enabled 设置为 false时,Elastic.ApmAgent.Subscribe(params IDiagnosticsSubscriber[] subscribers) 将不会使订阅者订阅诊断源事件。

Tracer API

编辑

tracer 使您可以访问当前活动的事务,并允许您手动启动事务。

您可以使用 Agent 上的静态属性访问 API: Elastic.Apm.Agent.Tracer

ITransaction StartTransaction(string name, string type, DistributedTracingData = null)

编辑

使用此方法创建自定义事务。

请注意,在自动检测的情况下,代理会自动为您执行此操作。例如,如果您的 ASP.NET Core 应用程序中有传入的 HTTP 调用,则代理会自动启动事务。在这些情况下,不需要此方法。

重要的是,当事务结束时调用void End()。最佳实践是在 try-catch-finally 块中使用事务,或使用CaptureTransaction 方法。

示例

var transaction = Elastic.Apm.Agent
        .Tracer.StartTransaction("MyTransaction", ApiConstants.TypeRequest);
try
{
    //application code that is captured as a transaction
}
catch (Exception e)
{
    transaction.CaptureException(e);
    throw;
}
finally
{
    transaction.End();
}

ITransaction CurrentTransaction

编辑

返回当前活动的事务。请参阅事务 API以自定义当前事务。

如果没有当前事务,此方法将返回 null

var transaction = Elastic.Apm.Agent.Tracer.CurrentTransaction;

ISpan CurrentSpan

编辑

返回当前活动的 span。请参阅Span API以自定义当前 span。

如果没有当前 span,此方法将返回 null

var span = Elastic.Apm.Agent.Tracer.CurrentSpan;

CaptureTransaction

编辑

这是一个方便的方法,用于启动和结束事务并捕获未处理的异常。它有 3 个必需的参数

  • name:事务的名称
  • type 事务的类型
  • 以下类型之一,引用您要捕获为事务的代码

    • Action
    • Action<ITransaction>
    • Func<T>
    • Func<ITransaction,T>
    • Func<Task>
    • Func<ITransaction,Task>
    • Func<Task<T>>
    • Func<ITransaction,Task<T>>

和一个可选参数

  • distributedTracingData:一个 DistributedTracingData 实例,其中包含分布式跟踪信息,以防您希望新事务成为跟踪的一部分。

以下代码与前一个示例使用方便的 API 等效。它会自动启动和结束事务并报告未处理的异常。 t 参数使您可以访问 ITransaction 实例,该实例表示您刚刚创建的事务。

Elastic.Apm.Agent.Tracer
        .CaptureTransaction("TestTransaction", ApiConstants.TypeRequest, (t) =>
{
   //application code that is captured as a transaction
});

此 API 还支持使用 Func<Task> 重载的 async 方法。

事务的持续时间将是 async lambda 表达式的第一行和最后一行之间的时间跨度。

示例

await Elastic.Apm.Agent.Tracer
        .CaptureTransaction("TestTransaction", "TestType", async () =>
{
    //application code that is captured as a transaction
    await Task.Delay(500); //sample async code
});

接受 Task(或 Task<T>)的 CaptureTransaction 方法重载的返回值与作为参数传递的 Task(或 Task<T>)实例相同,因此如果您的应用程序应仅在任务完成后继续,则必须使用 await 关键字调用 CaptureTransaction

手动传播分布式跟踪上下文

编辑

代理会自动为支持的技术传播分布式跟踪上下文(请参阅网络客户端技术)。如果您的应用程序通过代理不支持的协议进行通信,您可以手动将分布式跟踪上下文从调用方传播到被调用方,使用公共代理 API。

首先,您在调用方序列化分布式跟踪上下文

string outgoingDistributedTracingData =
    (Agent.Tracer.CurrentSpan?.OutgoingDistributedTracingData
        ?? Agent.Tracer.CurrentTransaction?.OutgoingDistributedTracingData)?.SerializeToString();

然后,您将生成字符串传输到被调用方,并通过将反序列化的分布式跟踪上下文传递给 ITransaction StartTransaction(string name, string type, DistributedTracingData = null)CaptureTransaction API 中的任何一个,继续跟踪 - 所有这些 API 都有一个可选的 DistributedTracingData 参数。例如

var transaction2 = Agent.Tracer.StartTransaction("Transaction2", "TestTransaction",
     DistributedTracingData.TryDeserializeFromString(serializedDistributedTracingData));

OutgoingDistributedTracingData 属性可以为 null。一种情况是当代理被禁用时。

void CaptureError(string message, string culprit, StackFrame[] frames = null, string parentId = null);

编辑

使用此方法捕获带有消息和罪魁祸首的 APM 错误。

捕获的错误会自动与活动的事务关联。如果没有活动事务,错误仍会出现在 APM 应用中,但不会与事务关联。

示例

Agent.Tracer.CaptureError("Something went wrong", "Database issue");

void CaptureException(Exception exception, string culprit = null, bool isHandled = false, string parentId = null);

编辑

使用此方法捕获 .NET 异常作为 APM 错误。

捕获的错误会自动与活动的事务关联。如果没有活动事务,错误仍会出现在 APM 应用中,但不会与事务关联。

示例

try
{
	//run my code
}
catch (Exception e)
{
	Agent.Tracer.CaptureException(e);
	//handle error
}

void CaptureErrorLog(ErrorLog errorLog, string parentId = null, Exception exception = null);

编辑

使用此方法将日志事件捕获为 APM 错误。

捕获的错误会自动与活动的事务关联。如果没有活动事务,错误仍会出现在 APM 应用中,但不会与事务关联。

示例

var errorLog = new ErrorLog("Error message")
{
	Level = "error",
	ParamMessage = "42"
};

Agent.Tracer.CaptureErrorLog(errorLog);

事务 API

编辑

事务描述了由 Elastic APM 代理监控服务时捕获的事件。事务有助于将多个 Span 组合成逻辑组,并且它们是服务的第一个 Span。有关事务和 Span 的更多信息,请参阅 APM 数据模型 文档。

有关如何获取当前事务的引用,请参阅 ITransaction CurrentTransaction

在调用 void End() 之后调用事务的任何方法都是非法的。您只能在控制事务生命周期时与事务进行交互。

ISpan StartSpan(string name, string type, string subType = null, string action = null)

编辑

启动并返回一个新的自定义 span 作为给定事务的子项。

重要的是在 span 结束后调用 void End() 或使用 CaptureSpan 方法。最佳实践是在 try-catch-finally 块中使用 span。

示例

ISpan span = transaction.StartSpan("Select FROM customer",
     ApiConstants.TypeDb, ApiConstants.SubtypeMssql, ApiConstants.ActionQuery);
try
{
    //execute db query
}
catch(Exception e)
{
    span.CaptureException(e);
    throw;
}
finally
{
    span.End();
}

void SetLabel(string key, T value) [1.7.0] 在 1.7.0 中添加。数字和布尔标签需要 APM Server 6.7+

编辑

标签用于向事务、span 和错误添加 已索引的 信息。已索引意味着数据在 Elasticsearch 中可搜索和可聚合。可以使用不同的键值对定义多个标签。

  • 已索引:是
  • Elasticsearch 类型:对象
  • Elasticsearch 字段:labels(在 context.tags)

标签值可以是字符串、布尔值或数字。由于给定键的标签存储在 Elasticsearch 中的相同位置,因此给定键的所有标签值必须具有相同的数据类型。每个键的多个数据类型将引发异常,例如,{"foo": "bar"}{"foo": 42}

数字和布尔标签仅在 APM Server 6.7+ 中引入。将此 API 与旧版本的 APM Server 结合使用会导致验证错误。

避免定义过多的用户指定标签。在索引中定义太多唯一字段是一种可能导致 映射爆炸 的情况。

transaction.SetLabel("stringSample", "bar");
transaction.SetLabel("boolSample", true);
transaction.SetLabel("intSample", 42);
  • String key:标签键
  • String|Number|bool value:标签值

T TryGetLabel<T>(string key, out T value) [1.7.1] 在 1.7.1 中添加。数字和布尔标签需要 APM Server 6.7+

编辑

value 输出参数中返回事务的标签。如果 key 不存在,则此方法返回 false。可以使用 SetLabel 方法添加标签。

if(transaction.TryGetLabel<int>("foo", our var myLabel))
    Console.WriteLine(myLabel);

Dictionary<string,string> Labels

编辑

此属性已过时,将在未来的版本中删除。请改用 void SetLabel() 方法,该方法允许设置字符串、布尔值和数字的标签。为了不破坏二进制兼容性,此属性目前仍然保留,并且在序列化时,使用 .SetLabel() 设置的值与 Labels 合并,以形成发送到 APM 服务器的标签集,其中 Labels 中的值优先。

用户定义的具有字符串值的标签的平面映射。

如果键包含任何特殊字符(.*"),它们将被替换为下划线。例如,a.b 将存储为 a_b

在使用自定义标签之前,请确保您了解可用的不同类型的 元数据

避免定义过多的用户指定标签。在索引中定义太多唯一字段是一种可能导致 映射爆炸 的情况。

Agent.Tracer
 .CaptureTransaction(TransactionName, TransactionType,
    transaction =>
    {
        transaction.Labels["foo"] = "bar";
        //application code that is captured as a transaction
    });
  • key:标签键
  • value:标签值

void End()

编辑

结束事务并计划将其报告给 APM Server。

对已结束的 span 实例调用任何方法都是非法的。这也包括此方法和 ISpan StartSpan(string name, string type, string subType = null, string action = null)

示例

transaction.End();

如果使用 CaptureTransaction 方法,则不得调用 void End()

void CaptureException(Exception e)

编辑

捕获异常并将其报告给 APM 服务器。

void CaptureError(string message, string culprit, StackFrame[] frames)

编辑

捕获自定义错误并将其报告给 APM 服务器。

当您想要报告错误但没有 Exception 实例时,通常会使用此方法。

void CaptureErrorLog(ErrorLog errorLog, string parentId = null, Exception exception = null);

编辑

捕获自定义错误并将其报告给 APM 服务器,并附加一个日志。

当您已经在代码中记录错误并且想要将此错误附加到 APM 事务时,通常会使用此方法。该日志将作为错误的一部分显示在 APM UI 上,并且它将与事务相关联。

CaptureSpan

编辑

这是一种便捷的方法,可在给定事务上启动和结束 span,并捕获未处理的异常。它具有与 CaptureTransaction 方法相同的重载。

它有 3 个必需的参数

  • name:span 的名称
  • type:span 的类型
  • 以下类型之一,引用您要捕获为事务的代码

    • Action
    • Action<ITransaction>
    • Func<T>
    • Func<ITransaction,T>
    • Func<Task>
    • Func<ITransaction,Task>
    • Func<Task<T>>
    • Func<ITransaction,Task<T>>

和 2 个可选参数

  • supType:span 的子类型
  • action:span 的操作

以下代码与 ISpan StartSpan(string name, string type, string subType = null, string action = null) 部分中以前的示例相同,但使用了便捷的 API。它会自动启动和结束 span 并报告未处理的异常。s 参数允许您访问表示刚创建的 span 的 ISpan 实例。

ITransaction transaction = Elastic.Apm.Agent.Tracer.CurrentTransaction;

transaction.CaptureSpan("SampleSpan", ApiConstants.TypeDb, (s) =>
{
    //execute db query
}, ApiConstants.SubtypeMssql, ApiConstants.ActionQuery);

CaptureTransaction API 类似,此方法还支持带有 Func<Task> 重载的 async 方法。

span 的持续时间将是 async lambda 表达式的第一行和最后一行之间的时间跨度。

此示例演示如何将返回结果 (Task<T>) 的 async 代码块作为 span 进行跟踪

ITransaction transaction = Elastic.Apm.Agent.Tracer.CurrentTransaction;
var asyncResult = await transaction.CaptureSpan("Select FROM customer", ApiConstants.TypeDb, async(s) =>
{
    //application code that is captured as a span
    await Task.Delay(500); //sample async code
    return 42;
});

接受 Task(或 Task<T>)的 CaptureSpan 方法重载的返回值与作为参数传递的 Task(或 Task<T>)实例相同,因此,如果您的应用程序应仅在任务完成后继续,则必须使用 await 关键字调用 CaptureSpan

上面的代码示例使用 Elastic.Apm.Agent.Tracer.CurrentTransaction。在生产代码中,您应确保 CurrentTransaction 不为 null

EnsureParentId

编辑

如果事务尚未具有 ParentId,则调用此方法会生成一个新 ID,将其设置为此事务的 ParentId,并将其作为 string 返回。

这可以关联 JavaScript 真实用户监控 (RUM) 代理为初始页面加载创建的 span 与后端服务的事务。

如果您的服务动态生成 HTML 页面,则使用此方法的值初始化 JavaScript RUM 代理可以分析在浏览器中与在后端服务中花费的时间。

要在 ASP.NET Core 中启用 JavaScript RUM 代理,请使用 .NET 代理的当前事务初始化 RUM 代理

<script>
	elasticApm.init({
		serviceName: 'MyService',
		serverUrl: 'https://127.0.0.1:8200',
		pageLoadTraceId: '@Elastic.Apm.Agent.Tracer.CurrentTransaction?.TraceId',
		pageLoadSpanId: '@Elastic.Apm.Agent.Tracer.CurrentTransaction?.EnsureParentId()',
		pageLoadSampled: @Json.Serialize(Elastic.Apm.Agent.Tracer?.CurrentTransaction.IsSampled)
		})
</script>

有关更多信息,请参阅 JavaScript RUM 代理文档

Dictionary<string,string> Custom

编辑

自定义上下文用于向事务添加非索引的自定义上下文信息。非索引意味着数据在 Elasticsearch 中不可搜索或不可聚合,并且您无法基于数据构建仪表板。但是,非索引信息对于其他原因很有用,例如提供上下文信息以帮助您快速调试性能问题或错误。

如果键包含任何特殊字符(.*"),它们将被替换为下划线。例如,a.b 将存储为 a_b

Dictionary<string,string> Labels 不同,此属性中的数据不会被截断。

Agent.Tracer.CaptureTransaction(transactionName, transactionType, (transaction) =>
{
	transaction.Custom["foo"] = "bar";
	transaction.End();
});

void SetService(string serviceName, string serviceVersion) ( [1.7] 在 1.7 中添加。 )

编辑

覆盖每个事务的服务名称和版本。当您在单个进程中托管多个服务时,这很有用。

如果未设置,事务将与默认服务关联。

此方法具有两个 string 参数

  • serviceName:要与事务关联的服务的名称。
  • serviceVersion:要与事务关联的服务的版本。

用法

var transaction = agent.Tracer.StartTransaction("Transaction1", "sample");
transaction.SetService("MyServiceName", "1.0-beta1");

它也可以与 Filter API ( [1.5] 在 1.5 中添加。 ) 一起使用

Agent.AddFilter( transaction =>
{
	transaction.SetService("MyServiceName", "1.0-beta1");
	return transaction;
});

Context

编辑

您可以将其他上下文附加到手动捕获的事务。

如果您使用的 Web 框架的代理不自动捕获事务(请参阅 Web 框架),您可以通过设置事务的 Context 属性的各种属性来添加与捕获的事务相关的上下文。例如

Agent.Tracer.CaptureTransaction("MyCustomTransaction",ApiConstants.TypeRequest, (transaction) =>
{
  transaction.Context.Request = new Request(myRequestMethod, myRequestUri);

  // ... code executing the request

  transaction.Context.Response =
     new Response { StatusCode = myStatusCode, Finished = wasFinished };
});

Span API

编辑

span 包含有关作为事务一部分执行的特定代码路径的信息。

例如,如果在记录的事务中发生数据库查询,则可以创建表示此数据库查询的 span。在这种情况下,span 的名称将包含有关查询本身的信息,而类型将包含有关数据库类型的信息。

ISpan StartSpan(string name, string type, string subType = null, string action = null)

编辑

启动并返回一个新的自定义 span,作为给定 span 的子 span。与 ITransaction 上的 ISpan StartSpan(string name, string type, string subType = null, string action = null) 方法非常相似,但在此情况下,新创建的 span 的父级是 span 本身。

重要的是在 span 结束后调用 void End() 或使用 CaptureSpan 方法。最佳实践是在 try-catch-finally 块中使用 span。

示例

ISpan childSpan = parentSpan.StartSpan("Select FROM customer",
     ApiConstants.TypeDb, ApiConstants.SubtypeMssql, ApiConstants.ActionQuery);
try
{
    //execute db query
}
catch(Exception e)
{
    childSpan?.CaptureException(e);
    throw;
}
finally
{
    childSpan?.End();
}

void SetLabel(string key, T value) [1.7.0] 在 1.7.0 中添加。数字和布尔标签需要 APM Server 6.7

编辑

用户定义标签的扁平映射,包含字符串、数字或布尔值。

在 6.x 版本中,标签存储在 Elasticsearch 的 context.tags 下。从 7.x 版本开始,它们存储为 labels 以符合 Elastic Common Schema (ECS)

标签在 Elasticsearch 中被索引,以便它们可以被搜索和聚合。无论如何,您都应该避免将用户指定的数据(例如 URL 参数)用作标签键,因为它可能导致映射爆炸。

span.SetLabel("stringSample", "bar");
span.SetLabel("boolSample", true);
span.SetLabel("intSample", 42);
  • String key:标签键
  • String|Number|bool value:标签值

T TryGetLabel<T>(string key, out T value) [1.7.1] 在 1.7.1 中添加。数字和布尔标签需要 APM Server 6.7+

编辑

value 输出参数中返回 span 的标签。如果 key 不存在,则此方法返回 false。可以使用 SetLabel 方法添加标签。

if(span.TryGetLabel<bool>("foo", out var myLabel))
    Console.WriteLine(myLabel);

Dictionary<string,string> Labels

编辑

此属性已过时,将在未来版本中删除。请改用 void SetLabel() 方法,该方法允许设置字符串、布尔值和数字类型的标签。此属性目前保留是为了不破坏二进制兼容性,并且在序列化时,使用 .SetLabel() 设置的值会与 Labels 组合形成发送到 APM 服务器的标签集,其中 Labels 中的值优先。

Dictionary<string,string> LabelsTransaction API 上类似:用户定义的标签的扁平映射,包含字符串值。

如果键包含任何特殊字符(.*"),它们将被替换为下划线。例如,a.b 将存储为 a_b

在使用自定义标签之前,请确保您了解可用的不同类型的 元数据

避免定义过多的用户指定标签。在索引中定义太多唯一字段是一种可能导致 映射爆炸 的情况。

transaction.CaptureSpan(SpanName, SpanType,
span =>
    {
        span.Labels["foo"] = "bar";
        //application code that is captured as a span
    });

void CaptureException(Exception e)

编辑

捕获异常并将其报告给 APM 服务器。

void CaptureError(string message, string culprit, StackFrame[] frames)

编辑

捕获自定义错误并将其报告给 APM 服务器。

当您想要报告错误但没有 Exception 实例时,通常会使用此方法。

void CaptureErrorLog(ErrorLog errorLog, string parentId = null, Exception exception = null);

编辑

捕获自定义错误并将其报告给 APM 服务器,并附加一个日志。

当您已经在代码中记录错误并且想要将此错误附加到 APM 事务时,通常使用此方法。该日志将作为错误的一部分显示在 APM UI 上,并且它将与给定 span 的事务相关联。

void End()

编辑

结束 span 并将其计划报告给 APM 服务器。

对已结束的 span 实例调用任何方法都是非法的。

Context

编辑

您可以将其他上下文附加到手动捕获的 span。

如果您使用代理不自动捕获 span 的数据库库(请参阅数据访问技术),您可以通过设置 span 的 Context.Db 属性来添加与捕获的数据库操作相关的上下文。例如

Agent.Tracer.CurrentTransaction.CaptureSpan("MyDbWrite", ApiConstants.TypeDb, (span) =>
{
    span.Context.Db = new Database
        { Statement = myDbStatement, Type = myDbType, Instance = myDbInstance };

    // ... code executing the database operation
});

如果您使用代理不自动捕获 span 的 HTTP 库(请参阅网络客户端技术),您可以通过设置 span 的 Context.Http 属性来添加与捕获的 HTTP 操作相关的上下文。例如

Agent.Tracer.CurrentTransaction.CaptureSpan("MyHttpOperation", ApiConstants.TypeExternal, (span) =>
{
    span.Context.Http = new Http
        { Url = myUrl, Method = myMethod };

    // ... code executing the HTTP operation

    span.Context.Http.StatusCode = myStatusCode;
});

CaptureSpan

编辑

这是一个方便的方法,它在给定 span 上启动并结束一个子 span 并捕获未处理的异常。

ITransaction 上的 CaptureSpan 方法非常相似,但在此情况下,新创建的 span 的父级是 span 本身。

它有 3 个必需的参数

  • name:span 的名称
  • type:span 的类型
  • 以下类型之一,引用您要捕获为事务的代码

    • Action
    • Action<ITransaction>
    • Func<T>
    • Func<ITransaction,T>
    • Func<Task>
    • Func<ITransaction,Task>
    • Func<Task<T>>
    • Func<ITransaction,Task<T>>

和 2 个可选参数

  • supType:span 的子类型
  • action:span 的操作

以下代码等效于 ISpan StartSpan(string name, string type, string subType = null, string action = null) 部分中带有方便 API 的上一个示例。它会自动启动和结束 span 并报告未处理的异常。s 参数使您可以访问表示您刚刚创建的 span 的 ISpan 实例。

span.CaptureSpan("SampleSpan", ApiConstants.TypeDb, (s) =>
{
    //execute db query
}, ApiConstants.SubtypeMssql, ApiConstants.ActionQuery);

CaptureTransaction API 类似,此方法还支持带有 Func<Task> 重载的 async 方法。

span 的持续时间将是 async lambda 表达式的第一行和最后一行之间的时间跨度。

此示例演示如何将返回结果 (Task<T>) 的 async 代码块作为 span 进行跟踪

var asyncResult = await span.CaptureSpan("Select FROM customer", ApiConstants.TypeDb, async(s) =>
{
    //application code that is captured as a span
    await Task.Delay(500); //sample async code
    return 42;
});

接受 Task(或 Task<T>)的 CaptureSpan 方法重载的返回值与作为参数传递的 Task(或 Task<T>)实例相同,因此,如果您的应用程序应仅在任务完成后继续,则必须使用 await 关键字调用 CaptureSpan

上面的代码示例使用 Elastic.Apm.Agent.Tracer.CurrentTransaction。在生产代码中,您应确保 CurrentTransaction 不为 null

Filter API ( [1.5] 在 1.5 中添加。 )

编辑

使用 Agent.AddFilter(filter) 来提供过滤器回调。

在将数据发送到 APM 服务器之前,将调用每个过滤器回调。这允许您操作正在发送的数据,例如删除敏感信息(如密码)。

每个过滤器回调按添加顺序调用,并且将接收一个 payload 对象作为唯一的参数,其中包含有关即将发送到 APM 服务器的数据。

过滤器回调是同步的,并且应返回操作后的 payload 对象。如果过滤器回调未返回任何值或返回假值,则不会调用其余的过滤器回调,并且 payload 将不会发送到 APM 服务器。

有 3 个重载的 Agent.AddFilter 方法,带有以下参数

  • Func<ITransaction, ITransaction>:为每个事务调用的过滤器。
  • Func<ISpan, ISpan>:为每个 span 调用的过滤器。
  • Func<IError, IError>:为每个错误调用的过滤器。

以下是 Agent.AddFilter 方法的一些用法示例。

删除特定数据库的所有 span

Agent.AddFilter((ISpan span) =>
{
	if (span.Context?.Db?.Instance == "VerySecretDb")
		return null;
	return span;
});

隐藏一些数据

Agent.AddFilter((ITransaction transaction) =>
{
	transaction.Context.Request.Url.Protocol = "[HIDDEN]";
	return transaction;
});