公共 API编辑

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

初始化编辑

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:接收所有捕获事件(如跨度、事务和指标)的组件。默认实现序列化所有事件并将它们发送到 Elastic APM 服务器
  • 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 捕获数据库调用

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

跟踪器 API编辑

跟踪器允许您访问当前活动的事务,并允许您手动启动事务。

您可以使用代理上的静态属性访问 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编辑

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

如果没有当前跨度,此方法将返回 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(在 <v.7.0 中以前为 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编辑

此属性已过 obsolete,将在未来版本中删除。请改用 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 服务器。

在已结束的 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> 标签不同,此属性中的数据不会被修剪。

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");

它也可以与过滤器 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 的子级。这与 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 服务器 6.7 编辑

用户定义的标签与字符串、数字或布尔值的平面映射。

在 6.x 版本中,标签存储在 Elasticsearch 的 context.tags 下。从 7.x 版本开始,它们存储为 labels 以符合弹性通用模式 (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 服务器 6.7+ 编辑

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

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

Dictionary<string,string> 标签编辑

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

类似于Dictionary<string,string> 标签事务 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

过滤器 API ( [1.5] 在 1.5 中添加。 )编辑

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

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

每个过滤器回调都按添加顺序调用,并将接收一个有效负载对象,该对象包含即将发送到 APM 服务器的数据作为唯一参数。

过滤器回调是同步的,应该返回操作后的有效负载对象。如果过滤器回调不返回任何值或返回虚假值,则不会调用剩余的过滤器回调,并且不会将有效负载发送到 APM 服务器。

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

  • 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;
});