【问题标题】:NewRelic transaction traces in a Ruby GemRuby Gem 中的 NewRelic 事务跟踪
【发布时间】:2013-12-20 05:28:48
【问题描述】:

我正在开发一个我想添加 NewRelic 监控的 Ruby gem。 gem 用于作为守护进程运行并由bluepill 监控的脚本中。我跟着“Monitoring Ruby background processes and daemons”开始。

我确认 gem 正在与 NewRelic 建立连接,因为该应用程序显示在我的门户中,但是,没有事务跟踪或正在调用的代码的任何指标故障。

这是我的 gem 的“入口”点,因为我试图围绕调用方法手动启动代理:

require 'fms/parser/version'
require 'fms/parser/core'
require 'fms/parser/env'

require 'mongoid'

ENV['NRCONFIG'] ||= File.dirname(__FILE__) + '/../newrelic.yml'
require 'newrelic_rpm'

module Fms
  module Parser
    def self.prepare_parse(filename)
      ::NewRelic::Agent.manual_start
        Mongoid.load!("#{File.dirname(__FILE__)}/../mongoid.yml", :development)
        Core.prepare_parse(filename)    
      ::NewRelic::Agent.shutdown
    end
  end
end

我也尝试将其添加到模块中:

   class << self
      include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
      add_transaction_tracer :prepare_parse, :category => :task
    end

我不完全确定我还能做什么。我确认代理能够与服务器通信并启用事务跟踪。后台应用程序选项卡中也没有显示任何内容。

这是迄今为止我从代理日志中获得的最有用的信息:

[12/23/13 21:21:03 +0000 apivm (7819)] INFO : Environment: development
[12/23/13 21:21:03 +0000 apivm (7819)] INFO : No known dispatcher detected.
[12/23/13 21:21:03 +0000 apivm (7819)] INFO : Application: MY-APP
[12/23/13 21:21:03 +0000 apivm (7819)] INFO : Installing Net instrumentation
[12/23/13 21:21:03 +0000 apivm (7819)] INFO : Finished instrumentation
[12/23/13 21:21:04 +0000 apivm (7819)] INFO : Reporting to: https://rpm.newrelic.com/[MASKED_ACCOUNT_NUMBER]
[12/23/13 22:12:06 +0000 apivm (7819)] INFO : Starting the New Relic agent in "development" environment.
[12/23/13 22:12:06 +0000 apivm (7819)] INFO : To prevent agent startup add a NEWRELIC_ENABLE=false environment variable or modify the "development" section of your newrelic.yml.
[12/23/13 22:12:06 +0000 apivm (7819)] INFO : Reading configuration from /var/lib/gems/1.9.1/gems/fms-parser-0.0.6/lib/fms/../newrelic.yml
[12/23/13 22:12:06 +0000 apivm (7819)] INFO : Starting Agent shutdown

这里唯一真正关心的是“未检测到已知的调度程序”。

我正在尝试做的事情可能吗?

【问题讨论】:

  • newrelic.log 中有什么内容?
  • 您是否尝试通过在您的newrelic.yml 中设置agent_enabled: true 来强制它运行?您是否也在开发过程中尝试这样做?也许尝试切换到developer_mode: true
  • 如果您不确定日志记录是否正确...尝试在设置 NRCONFIG 环境变量后添加:ENV['NEW_RELIC_LOG'] ||= File.dirname(__FILE__) + '/../log/newrelic_agent.log'
  • 还可以尝试将::NewRelic::Agent.manual_start 移到require 'newrelic_rpm' 之后的右侧

标签: ruby newrelic


【解决方案1】:

我在 New Relic 工作,想添加一些有关newrelic_rpm gem 最新版本的最新详细信息。 TrinitronX 是在正确的轨道上,但不幸的是,代码示例和博客文章是基于一个非常旧的 gem 版本,并且从那时起内部结构发生了显着变化。好消息是,较新版本的代理应该会使这更简单。

首先,我应该说我假设您的进程作为守护进程存活了很长时间,并反复调用prepare_parse

一般来说,您在 prepare_parse 方法中插入的显式 manual_startshutdown 调用应该是不必要的 - 除了一些特殊情况(某些 rake 任务和交互式会话)。 New Relic 代理将在需要时自动启动。您可以在此处查看有关 Ruby 代理何时自动启动以及如何控制此行为的详细信息:

对于像这样监控后台任务,从概念上讲,您可能需要两个级别的工具:事务跟踪器和方法跟踪器。您已经有一个事务跟踪器,但您可能还想在 prepare_parse 方法中发生的主要工作块周围添加方法跟踪器。这样做可以让您更好地了解每个 prepare_parse 调用中发生的情况。您可以在此处找到有关添加方法跟踪器的详细信息:

按照您调用add_transaction_tracer 的方式,您对prepare_parse 的调用应在New Relic UI 的“后台任务”选项卡上显示为事务。

这里的一个警告可能是您将其作为守护程序运行。 Ruby 代理使用后台线程与 New Relic 服务器进行异步通信。由于线程不会在对fork() 的调用中复制,这意味着您有时必须在fork() 之后手动重新启动代理(请注意,Ruby 的Process.daemon 在下面使用fork,因此它也包含在内)。这是否必要取决于newrelic_rpm 的要求和对fork / daemon 的调用的相对时间(如果在调用fork / daemon 之前不需要newrelic_rpm ,你应该很好,否则见下文)。

分叉问题有两种解决方案:

  1. 从分叉的孩子手动调用NewRelic::Agent.after_fork,就在分叉之后。

  2. 如果您使用的是 newrelic_rpm 3.7.1 或更高版本,则有一个实验性选项可以自动重新启动后台线程,您可以通过设置 restart_thread_in_children: true 在 newrelic.yml 文件中启用该选项。目前默认关闭,但可能会成为代理未来版本的默认行为。

如果您仍然遇到问题,newrelic_agent.log 文件是您调试事物的最佳选择。您需要通过在 newrelic.yml 文件中设置 log_level: debug 来增加详细程度,以获得更详细的输出。

【讨论】:

  • 这是我在 SO 上见过的最详细的客户支持答案;希望我能投上一百万票!
  • 哇,谢谢@JulianaA!我知道在分叉后关闭代理是最佳的,但我不知道 New relic 代理的后台进程实际上是如何自己启动的。很高兴了解NewRelic::Agent.after_fork
  • 是的——请在文档中添加NewRelic::Agent.after_fork。我正在使用dante 进行守护进程,NewRelic 默默地停止报告该进程的数据。解决方法是在守护进程中调用.after_fork
  • 请注意 - 上面提到的 restart_thread_in_children 配置设置在 Ruby 代理的 3.8.0 版本中默认启用,因此您不再需要显式指定它。
【解决方案2】:

要调试此问题,请尝试以下代码:

require 'fms/parser/version'
require 'fms/parser/core'
require 'fms/parser/env'

require 'mongoid'

ENV['NRCONFIG'] ||= File.dirname(__FILE__) + '/../newrelic.yml'
# Make sure NewRelic has correct log file path
ENV['NEW_RELIC_LOG'] ||= File.dirname(__FILE__) + '/../log/newrelic_agent.log'

require 'newrelic_rpm'
::NewRelic::Agent.manual_start

# For debug purposes: output some dots until we're connected to NewRelic
until NewRelic::Agent.connected? do
  print '.'
  sleep 1
end

module Fms
  module Parser
    class << self
      include ::NewRelic::Agent::Instrumentation::ControllerInstrumentation
      add_transaction_tracer :prepare_parse, :category => :task
    end
    def self.prepare_parse(filename)
        Mongoid.load!("#{File.dirname(__FILE__)}/../mongoid.yml", :development)
        Core.prepare_parse(filename)

      # Force the agent to prepare data before we shutdown
      ::NewRelic::Agent.load_data
      # NOTE: Ideally you'd want to shut down the agent just before the process exits... not every time you call Fms::Parser#prepare_parse
      ::NewRelic::Agent.shutdown(:force_send => true)
    end
  end
end

我感觉这可能与在 bluepill 启动的守护进程中运行 gem 的代码有关。理想情况下,我们希望在守护进程分叉后尽快在进程中启动 NewRelic 代理。在需要文件时将其放在库的要求之后。

我们也很可能希望在后台任务进程退出之前停止 NewRelic 代理,而不是每次调用 Fms::Parser#prepare_parse 方法时。但是,出于我们的目的,这应该为您提供足够的调试信息以继续,因此您可以确保任务在第一次运行时与 New Relic 联系。我们也可以尝试使用:force_send =&gt; true 来确保我们发送数据。

参考资料:

【讨论】:

  • 我在 New Relic 工作。这篇博文和信息已经过时了——如果@randombits 使用的是去年的代理版本,它将无法正常工作。一位同事即将发布更新的答案。
猜你喜欢
  • 2020-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-21
相关资源
最近更新 更多