故障排除
编辑故障排除编辑
使用本节中的信息对常见问题进行故障排除,并找到常见问题的答案。第一步,请确保您的堆栈与代理的支持的技术兼容。
如果您无法确定问题所在,请不要担心;我们随时为您提供帮助。如果您是拥有支持合同的现有 Elastic 客户,请在Elastic 支持门户中创建故障单。如果不是,请在APM 讨论论坛中发帖。
请附上您的调试日志,以便我们分析问题。将完整日志上传到https://gist.github.com等服务。日志应包含从应用程序启动到第一个请求执行的所有内容。
没有数据发送到 APM 服务器编辑
如果既没有错误也没有性能指标发送到 APM 服务器,最好先检查您的日志并查找应用程序启动时的输出。
如果您在代理日志中没有看到任何可疑内容(没有警告或错误),建议将日志级别设置为Trace
以进行进一步调查。
收集代理日志编辑
收集日志的方式取决于应用程序的设置。
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
或更高级别的日志
ASP.NET Classic编辑
ASP.NET(经典)没有预定义的日志记录系统。默认情况下,代理配置为使用源名称"Elastic.Apm"
将日志消息发送到System.Diagnostics.TraceSource
。TraceSource 遵循 APM 代理配置中定义的日志级别。通常,您将使用web.config
中的应用程序设置来配置首选日志级别。
System.Diagnostics.TraceSource 要求指定TRACE
编译器指令,默认情况下,调试和发布构建配置都指定了该指令。
可以使用<system.diagnostics>
部分的 web.config 配置TraceListeners 来监视跟踪源的日志消息。例如,以下 web.config 部分将 Elastic.Apm 日志消息写入名为 my_log_file.log 的文件
<configuration> <!-- other sections .... --> <system.diagnostics> <sources> <source name="Elastic.Apm"> <listeners> <add name="file" type="System.Diagnostics.TextWriterTraceListener" initializeData="my_log_file.log" /> </listeners> </source> </sources> </system.diagnostics> </configuration>
其他日志记录系统编辑
如果您有现有的日志记录系统,例如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()));
日志中出现以下错误:单例 APM 代理已被实例化,无法再进行配置。
编辑
请参阅“抛出InstanceAlreadyCreatedException
异常”。
抛出InstanceAlreadyCreatedException
异常编辑
在受监控进程的早期阶段,代理可能会抛出InstanceAlreadyCreatedException
异常,并显示以下消息:“单例 APM 代理已被实例化,无法再进行配置。”,或者出现包含相同消息的错误日志。当您尝试多次初始化代理时会发生这种情况,这是不允许的。允许多个代理实例每个进程都会导致问题,例如多次捕获每个实例的事件和指标,或者为事件序列化和传输到 APM 服务器使用多个后台线程。
有关代理初始化工作原理的更多信息,请查看公共代理 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
方法来初始化代理。
您可以在代码中使用公共代理 API 和Elastic.Apm.Agent
类,这些代码可能会在 IIS 模块初始化或UseElasticApm
/UseAllElasticApm
调用执行之前执行。如果发生这种情况,这些操作将失败,因为代理已被隐式初始化。
为了防止在这些情况下出现InstanceAlreadyCreatedException
,首先使用Elastic.Apm.Agent.IsConfigured
方法检查代理是否已初始化。检查后,您可以安全地使用公共代理 API 中的其他方法。这将防止意外的隐式代理初始化。
ASP.NET 正在使用 LegacyAspNetSynchronizationContext,并且可能无法很好地处理异步代码编辑
如果您看到记录了此警告,则表示您的经典 ASP.NET 应用程序正在 quirks 模式下运行,并且正在使用已弃用但向后兼容的异步上下文。当异步代码引入线程切换时,这可能会阻止我们的代理正常工作,因为此上下文无法可靠地还原HttpContext.Items
。
要退出 quirks 模式,必须在 web.config 中显式指定运行时
<httpRuntime targetFramework="4.5" />
在此处详细了解 ASP.NET quirks 模式:https://devblogs.microsoft.com/dotnet/all-about-httpruntime-targetframework
SqlEventListener 无法捕获 sql 语句(无法从 ProcessingSpans 中删除)。编辑
当我们的 SQL 事件侦听器无法找到活动事务时,我们会记录此警告。仅在应用程序在 quirks 模式下运行时,才会在 IIS 下观察到这种情况。有关更多背景信息和可能的修复方法,请参阅“ASP.NET 正在使用 LegacyAspNetSynchronizationContext,并且可能无法很好地处理异步代码”部分。
HttpDiagnosticListenerFullFrameworkImpl 没有当前事务,跳过为传出的 HTTP 请求创建 span编辑
当我们的传出 HTTP 侦听器无法获取当前事务时,我们会记录此跟踪警告。这仅在 IIS 下以 quirks 模式运行应用程序时才会观察到。有关更多背景信息和可能的修复方法,请参阅“ASP.NET 正在使用 LegacyAspNetSynchronizationContext,并且可能无法很好地处理异步代码”部分。
异常:System.PlatformNotSupportedException:此操作需要 IIS 集成管道模式编辑
如果在强制使用经典管道模式的应用程序池下运行经典 ASP.NET 应用程序,则会发生此异常。这会阻止我们的代理修改标头,从而破坏分布式跟踪。
该代理仅在 IIS7 及更高版本(其中 集成管道模式
为默认模式)上受支持。
启动钩子失败编辑
如果 启动钩子 集成引发异常,则可以通过在启动应用程序之前设置 ELASTIC_APM_STARTUP_HOOKS_LOGGING
环境变量来获取更多详细信息
set ELASTIC_APM_STARTUP_HOOKS_LOGGING=1
然后在环境变量可见的上下文中运行应用程序。设置此值后,除了写入标准输出外,还会将 ElasticApmAgentStartupHook.log
文件写入包含启动钩子程序集的目录。
代理导致开销过大编辑
一个好的起点是 所有选项摘要。有多个设置带有 性能
关键字,可以帮助您根据需要调整代理。
代理中最昂贵的操作通常是堆栈跟踪捕获。默认情况下,代理仅捕获持续时间为 5 毫秒或更长的 span 的堆栈跟踪,并且限制为 50 个堆栈帧。如果在您的环境中这太多了,请考虑部分或完全禁用堆栈跟踪捕获
- 要禁用 span 的堆栈跟踪捕获,但继续捕获错误的堆栈跟踪,请将
SpanStackTraceMinDuration
(性能) 设置为-1
,并将StackTraceLimit
(性能) 保留为默认值。 - 要完全禁用堆栈跟踪捕获(这在大多数应用程序中会大大降低代理开销),请将
StackTraceLimit
(性能) 设置为0
。
ElasticApmModule 不加载或捕获事务,并且在 IISExpress 上没有生成代理日志编辑
使用 Visual Studio 和 IISExpress 调试应用程序时,也需要使用 集成
托管管道模式。在解决方案资源管理器中选择您的 Web 应用程序项目,然后按 F4 加载属性窗口。如果托管管道模式设置为经典,则 ElasticApmModule 将不会加载。
例如
应该改为
您可能需要重新启动 Visual Studio 才能使这些更改完全生效。