故障排除
编辑故障排除
编辑使用本节中的信息来排除常见问题并查找常见问题的答案。第一步,请确保您的堆栈与 Agent 的支持的技术兼容。
如果您无法找出问题所在,请不要担心;我们随时为您提供帮助。如果您是拥有支持合同的现有 Elastic 客户,请在Elastic 支持门户中创建工单。如果不是,请在APM 讨论论坛中发帖。
请附加您的调试日志,以便我们分析问题。将完整的日志上传到像https://gist.github.com这样的服务。日志应包含从应用程序启动到执行第一个请求的所有内容。
没有数据发送到 APM Server
编辑如果既没有错误也没有性能指标被发送到 APM Server,最好先检查您的日志并查找应用程序启动时的输出。
如果您在代理日志中没有看到任何可疑内容(没有警告或错误),建议将日志级别更改为Trace
以进行进一步调查。
收集代理日志
编辑启用全局文件日志记录。
编辑无论代理以何种方式运行,获取代理调试信息的最简单方法是启用全局文件日志记录。
指定以下环境变量中的至少一个将确保代理将日志记录到文件中
-
OTEL_LOG_LEVEL
(可选) -
探查器应记录的日志级别。有效值为
- trace
- debug
- info
- warn
- error
- none
默认值为warn
。更详细的日志级别(如trace
和debug
)可能会影响探查器自动检测的运行时性能,因此仅建议用于诊断目的。
如果ELASTIC_OTEL_LOG_TARGETS
未明确设置为包含file
,则仅当使用trace
或debug
配置时才会启用全局文件日志记录。
-
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
设置为trace
或debug
,则默认值为file
。
ASP.NET Core
编辑如果您按照ASP.NET Core文档中使用UseAllElasticApm
或UseElasticApm
方法将代理添加到您的应用程序,它将与ASP.NET Core 日志记录基础结构集成。这意味着代理将获取配置的日志记录提供程序并像任何其他组件日志一样记录。
在这种情况下,LogLevel
APM 代理配置(例如,设置ELASTIC_APM_LOG_LEVEL
环境变量)**不会**控制代理日志的详细程度。代理日志由来自IConfiguration
的 ASP.NET Core 日志记录配置控制,通常通过appsettings.json
配置。
例如,appsettings.json
中的以下配置将 APM 代理日志限制为日志级别为Warning
或更高的日志
其他日志记录系统
编辑如果您已使用日志记录系统(如NLog、Serilog或类似系统),您可以通过在代理的内部记录器和您的日志记录系统之间创建适配器来将代理日志重定向到您的日志记录系统。
首先实现来自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 包结合使用时,您使用UseElasticApm
或UseAllElasticApm
方法启用代理。对 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 的跨度的堆栈跟踪。如果这对您的环境来说过于频繁,请考虑部分或完全禁用堆栈跟踪捕获。
- 要禁用跨度的堆栈跟踪捕获,但继续捕获错误的堆栈跟踪,请将
SpanStackTraceMinDuration
(性能)设置为-1
,并将StackTraceLimit
(性能)保留为其默认值。 - 要完全禁用堆栈跟踪捕获 - 这在大多数应用程序中可以显着降低代理开销 - 请将
StackTraceLimit
(性能)设置为0
。
ElasticApmModule 无法加载或捕获事务,并且在 IISExpress 上未生成任何代理日志
编辑使用 Visual Studio 和 IISExpress 调试应用程序时,也需要使用Integrated
托管管道模式。在解决方案资源管理器中选择您的 Web 应用程序项目,然后按 F4 加载属性窗口。如果托管管道模式设置为经典模式,则 ElasticApmModule 将无法加载。
例如
应更改为
您可能需要重新启动 Visual Studio 以使这些更改完全生效。
Azure 应用服务/ASE 和采样
编辑Azure/ASE 为传入集群的请求添加设置为未采样的跟踪标头。
Elastic APM .NET 代理(以及可能其他正确处理 W3C Trace Parent 标头采样的代理)将服从传入请求的 traceparent 标头采样。结果,跟踪/跨度将不会发送到 APM 服务器/集成,因此 APM UI 不会显示任何内容。
我们建议使用trace_continuation_strategy
设置为restart
或restart_external
,以便 APM .NET 代理忽略传入的 traceparent 标头采样标志。