故障排除

编辑

使用本节中的信息来排除常见问题并查找常见问题的答案。第一步,请确保您的堆栈与 Agent 的支持的技术兼容。

如果您无法找出问题所在,请不要担心;我们随时为您提供帮助。如果您是拥有支持合同的现有 Elastic 客户,请在Elastic 支持门户中创建工单。如果不是,请在APM 讨论论坛中发帖。

请附加您的调试日志,以便我们分析问题。将完整的日志上传到像https://gist.github.com这样的服务。日志应包含从应用程序启动到执行第一个请求的所有内容。

没有数据发送到 APM Server

编辑

如果既没有错误也没有性能指标被发送到 APM Server,最好先检查您的日志并查找应用程序启动时的输出。

如果您在代理日志中没有看到任何可疑内容(没有警告或错误),建议将日志级别更改为Trace以进行进一步调查。

收集代理日志

编辑

启用全局文件日志记录。

编辑

无论代理以何种方式运行,获取代理调试信息的最简单方法是启用全局文件日志记录。

指定以下环境变量中的至少一个将确保代理将日志记录到文件中

OTEL_LOG_LEVEL (可选)

探查器应记录的日志级别。有效值为

  • trace
  • debug
  • info
  • warn
  • error
  • none

默认值为warn。更详细的日志级别(如tracedebug)可能会影响探查器自动检测的运行时性能,因此仅建议用于诊断目的。

如果ELASTIC_OTEL_LOG_TARGETS未明确设置为包含file,则仅当使用tracedebug配置时才会启用全局文件日志记录。

OTEL_DOTNET_AUTO_LOG_DIRECTORY (可选)

写入日志文件的目录。如果未设置,则默认为

  • %PROGRAMDATA%\elastic\apm-agent-dotnet\logs(Windows 上)
  • /var/log/elastic/apm-agent-dotnet(Linux 上)

运行探查器进程的用户帐户必须具有写入目标日志目录的权限。具体来说,请确保在 IIS 上运行时,应用程序池标识在目标目录中具有写入权限。

ELASTIC_OTEL_LOG_TARGETS (可选)

探查器日志的目标的用分号分隔的列表。有效值为

  • file
  • stdout

如果设置了OTEL_DOTNET_AUTO_LOG_DIRECTORY或将OTEL_LOG_LEVEL设置为tracedebug,则默认值为file

ASP.NET Core

编辑

如果您按照ASP.NET Core文档中使用UseAllElasticApmUseElasticApm方法将代理添加到您的应用程序,它将与ASP.NET Core 日志记录基础结构集成。这意味着代理将获取配置的日志记录提供程序并像任何其他组件日志一样记录。

在这种情况下,LogLevel APM 代理配置(例如,设置ELASTIC_APM_LOG_LEVEL环境变量)**不会**控制代理日志的详细程度。代理日志由来自IConfiguration的 ASP.NET Core 日志记录配置控制,通常通过appsettings.json配置。

例如,appsettings.json中的以下配置将 APM 代理日志限制为日志级别为Warning或更高的日志

"Logging": {
  "LogLevel": {
    "Default": "Information",
    "Elastic.Apm": "Warning" 
  }
},

通过为Elastic.Apm类别设置日志级别来控制代理日志的详细程度

其他日志记录系统

编辑

如果您已使用日志记录系统(如NLogSerilog或类似系统),您可以通过在代理的内部记录器和您的日志记录系统之间创建适配器来将代理日志重定向到您的日志记录系统。

首先实现来自Elastic.Apm.Logging命名空间的IApmLogger接口

internal class ApmLoggerAdapter : IApmLogger
{
	private readonly Lazy<Logger> _logger;
	public bool IsEnabled(ApmLogLevel level)
	{
		// Check for log level here.
		// Typically you just compare the configured log level of your logger
		// to the input parameter of this method and return if it's the same/higher or not
	}

	public void Log<TState>(ApmLogLevel apmLogLevel, TState state, Exception e, Func<TState, Exception, string> formatter)
	{
		// You can log the given log into your logging system here.
	}
}

可以在我们的 GitHub 存储库中看到 NLog 的示例实现。

然后告诉代理使用ApmLoggerAdapter。对于 ASP.NET(经典),请将以下代码放入应用程序的HttpApplication实现中的Application_Start方法,该方法通常位于Global.asax.cs文件中

using Elastic.Apm.AspNetFullFramework;

namespace MyApp
{
	public class MyApplication : HttpApplication
	{
		protected void Application_Start()
		{
			AgentDependencies.Logger = new ApmLoggerAdapter();

			// other application setup...
		}
	}
}

在初始化期间,代理会检查是否配置了其他记录器——代理只执行此操作一次,因此在流程的早期设置它非常重要,通常在Application_Start方法中。

通用 .NET 应用程序

编辑

如果上述情况都不适用于您的应用程序,您仍然可以使用记录器适配器并将代理日志重定向到 .NET 日志记录系统(如 NLog、Serilog 或类似系统)。

为此,您需要一个IApmLogger实现(请参见上文),您需要在代理设置期间将其传递给Setup方法

Agent.Setup(new AgentComponents(logger: new ApmLoggerAdapter()));

日志中出现以下错误:The singleton APM agent has already been instantiated and can no longer be configured.

编辑

请参阅“抛出InstanceAlreadyCreatedException异常”。

抛出InstanceAlreadyCreatedException异常

编辑

在受监控进程的早期阶段,代理可能会抛出InstanceAlreadyCreatedException异常,并显示以下消息:“The singleton APM agent has already been instantiated and can no longer be configured.”,或者出现包含相同消息的错误日志。当您尝试多次初始化代理时,就会发生这种情况,这是禁止的。允许每个进程存在多个代理实例会导致问题,例如为每个实例捕获事件和指标多次,或者为事件序列化和传输到 APM Server 创建多个后台线程。

请参阅公共代理 API的初始化部分,以获取有关代理初始化工作原理的更多信息。

例如,如果您多次调用Elastic.Apm.Agent.Setup方法,或者如果您调用Elastic.Apm.Agent上的隐式初始化代理的其他方法,然后在已初始化的代理上调用Elastic.Apm.Agent.Setup方法,则可能会发生此问题。

另一个示例可能是当您将公共代理 API 与 IIS 模块或 ASP.NET Core NuGet 包结合使用时,您使用UseElasticApmUseAllElasticApm方法启用代理。对 IIS 模块的第一次调用和UseElasticApm/UseAllElasticApm方法在内部都会调用Elastic.Apm.Agent.Setup方法来初始化代理。

您可以在 IIS 模块初始化或UseElasticApm/UseAllElasticApm调用执行之前可能执行的代码中使用Elastic.Apm.Agent类的公共代理 API。如果发生这种情况,这些操作将失败,因为代理已隐式初始化。

为了防止在这些情况下出现InstanceAlreadyCreatedException,首先使用Elastic.Apm.Agent.IsConfigured方法检查代理是否已初始化。检查后,您可以安全地使用公共代理 API 中的其他方法。这将防止意外的隐式代理初始化。

ASP.NET 正在使用 LegacyAspNetSynchronizationContext,并且异步代码可能无法正常工作

编辑

如果您看到此警告被记录,则表示您的经典 ASP.NET 应用程序在怪癖模式下运行,并且正在使用已弃用但向后兼容的异步上下文。当异步代码引入线程切换时,这可能会阻止我们的代理正常工作,因为此上下文无法可靠地恢复HttpContext.Items

要退出怪癖模式,必须在 web.config 中显式指定运行时

<httpRuntime targetFramework="4.5" />

在此处阅读有关 ASP.NET 怪癖模式的更多信息:https://devblogs.microsoft.com/dotnet/all-about-httpruntime-targetframework

SqlEventListener 无法捕获 SQL 语句(无法从 ProcessingSpans 中删除)。

编辑

当我们的 SQL 事件侦听器无法找到活动事务时,我们会记录此警告。这仅在应用程序在怪癖模式下运行的 IIS 下观察到。请参阅“ASP.NET 正在使用 LegacyAspNetSynchronizationContext,并且异步代码可能无法正常工作”部分以获取更多背景信息和可能的修复方法。

HttpDiagnosticListenerFullFrameworkImpl 没有当前事务,跳过为传出 HTTP 请求创建跨度

编辑

当我们的传出 HTTP 侦听器无法获取当前事务时,我们会记录此跟踪警告。这仅在应用程序在怪癖模式下运行的 IIS 下观察到。请参阅“ASP.NET 正在使用 LegacyAspNetSynchronizationContext,并且异步代码可能无法正常工作”部分以获取更多背景信息和可能的修复方法。

异常:System.PlatformNotSupportedException:此操作需要 IIS 集成管道模式

编辑

如果经典 ASP.NET 应用程序在强制使用经典管道模式的应用程序池下运行,则会出现此异常。这会阻止我们的代理修改标头,从而导致分布式跟踪中断。

代理仅支持 IIS7 及更高版本,其中集成管道模式是默认模式。

启动挂钩失败

编辑

如果启动钩子集成抛出异常,可以通过启用全局日志收集获取更多详细信息。

代理导致过高的开销

编辑

一个好的起点是所有选项汇总。其中有多个设置带有Performance关键字,可以帮助您根据需要调整代理。

代理中最耗费资源的操作通常是堆栈跟踪捕获。默认情况下,代理仅捕获持续时间超过 5 毫秒且堆栈帧数限制为 50 的跨度的堆栈跟踪。如果这对您的环境来说过于频繁,请考虑部分或完全禁用堆栈跟踪捕获。

ElasticApmModule 无法加载或捕获事务,并且在 IISExpress 上未生成任何代理日志

编辑

使用 Visual Studio 和 IISExpress 调试应用程序时,也需要使用Integrated托管管道模式。在解决方案资源管理器中选择您的 Web 应用程序项目,然后按 F4 加载属性窗口。如果托管管道模式设置为经典模式,则 ElasticApmModule 将无法加载。

例如

Classic Managed Pipeline Mode in Properties

应更改为

Integrated Managed Pipeline Mode in Properties

您可能需要重新启动 Visual Studio 以使这些更改完全生效。

Azure 应用服务/ASE 和采样

编辑

Azure/ASE 为传入集群的请求添加设置为未采样的跟踪标头。

Elastic APM .NET 代理(以及可能其他正确处理 W3C Trace Parent 标头采样的代理)将服从传入请求的 traceparent 标头采样。结果,跟踪/跨度将不会发送到 APM 服务器/集成,因此 APM UI 不会显示任何内容。

我们建议使用trace_continuation_strategy设置为restartrestart_external,以便 APM .NET 代理忽略传入的 traceparent 标头采样标志。