Статьи

Использование новых метрик Relic для мониторинга всего

Когда вы впервые знакомитесь с New Relic , легко быть пораженным всеми функциями . Но, как и в случае с большинством инструментов, когда вы медленно поднимаетесь по кривой обучения и знакомитесь с функциями, предоставляемыми из коробки, вы начинаете удивляться, как все это свисает под капотом, и если есть еще что-то, что вы можете сделать с тем, что у вас есть в рука.

Сегодня я расскажу о том, как New Relic на самом деле отслеживает транзакции и как вы можете подключиться к процессу. Мы быстро взглянем на поддержку, оказываемую New Relic для мониторинга фоновых заданий, а также рассмотрим пользовательские метрики New Relic, их использование и преимущества, которые вы получите от этого. К концу у вас будет более глубокое понимание того, как работает New Relic, и вы сможете использовать его более полно. Другими словами, у нас будет более глубокое знание наших инструментов — то, к чему должен стремиться каждый разработчик.

Давайте начнем с краткого обзора того, как на самом деле подключается New Relic для отслеживания производительности вашего приложения.

Спонсированный контент

Это содержание было заказано New Relic и было написано и / или отредактировано командой Tuts +. Наша цель в отношении спонсируемого контента состоит в том, чтобы публиковать соответствующие и объективные учебные пособия, тематические исследования и вдохновляющие интервью, которые предлагают реальную образовательную ценность нашим читателям и позволяют нам финансировать создание более полезного контента.


Это может показаться немного магическим, вы включаете драгоценный камень в свой Gemfile :

1
gem ‘newrelic_rpm’

И так или иначе New Relic контролирует весь ваш код. Конечно, это всего лишь код, поэтому давайте посмотрим, как New Relic на самом деле оснащает ваше приложение, чтобы оно могло начать отслеживать его, когда требуется гем агента. Мы сделаем это в контексте приложения Rails 4.

Первое, что нужно посмотреть, это newrelic_rpm.rb , в котором есть следующий соответствующий код:

01
02
03
04
05
06
07
08
09
10
11
12
if Rails::VERSION::MAJOR.to_i >= 3
  module NewRelic
    class Railtie < Rails::Railtie
 
      initializer «newrelic_rpm.start_plugin» do |app|
        NewRelic::Control.instance.init_plugin(:config => app.config)
      end
    end
  end
else

Поэтому Railtie создается, когда версия Rails выше трех, получает одноэлементный экземпляр NewRelic::Control (когда он инициализируется) и вызывает init_plugin . Когда NewRelic::Control экземпляр NewRelic::Control он выясняет, какой фреймворк работает (в нашем случае Rails 4) и загружает некоторый соответствующий код; мы можем увидеть это в new_relic/control/class_methods#load_framework_class . init_plugin метод init_plugin в new_relic/control/instance_methods . Интересный код здесь:

1
2
3
4
5
6
if Agent.config[:agent_enabled] && !NewRelic::Agent.instance.started?
  start_agent
  install_instrumentation
  load_samplers unless Agent.config[:disable_samplers]

Важным является вызов install_instrumentation . Реализация живет в new_relic/control/instrumentation . Пропуск шаблонных битов позволяет определить, какие файлы инструментов нужно загрузить, а затем требует их один за другим. В нашем случае, он будет загружать файлы в new_relic/agent/instrumentation/rails4 . Одним из файлов здесь является action_controller.rb , когда это требуется, в конечном итоге он выполняет следующий код с помощью некоторой магии метапрограммирования :

1
2
3
4
5
6
7
8
executes do
  class ActionController::Base
    include NewRelic::Agent::Instrumentation::ControllerInstrumentation
    include NewRelic::Agent::Instrumentation::Rails4::ActionController
  end
  NewRelic::Agent::Instrumentation::ActionControllerSubscriber \
    .subscribe(/^process_action.action_controller$/)
end

И здесь мы ActionController::Base к сути: ActionController::Base (от которой наследуются все ваши контроллеры) получает несколько модулей, наиболее важным из которых является NewRelic::Agent::Instrumentation::ControllerInstrumentation . Это начало того, как New Relic начинает отслеживать все ваши действия контроллера как «транзакции». Конечно, это несколько упрощенное представление, и мы скрываем много деталей, но оно дает вам представление о том, как New Relic контролирует ваш код. Вопрос в том, как вы можете использовать эту информацию?

Вы вряд ли окажетесь в ситуации, когда вы используете веб-фреймворк, для которого у New Relic еще нет инструментария (в мире Ruby), но, допустим, у вас есть. Зная, что мы знаем сейчас, мы можем легко вручную контролировать действия контроллера этой пользовательской платформы. Если у нас есть контроллер, как это:

1
2
3
4
5
class CustomController
  def custom_action
    …
  end
end

Мы можем инструмент это так:

1
2
3
4
5
6
7
8
class CustomController
  include NewRelic::Agent::Instrumentation::ControllerInstrumentation
 
  def custom_action
    …
  end
  add_transaction_tracer :custom_action
end

Теперь ваш метод контроллера будет отслеживаться как транзакция так же, как отслеживаются действия Rails. Конечно, если вы развернули свою собственную веб-среду, которая включает в себя код обработки базы данных, вам потребуется проделать дополнительную работу, чтобы обработать большую часть этого кода, чтобы позволить New Relic контролировать не только действия контроллера. Но общая идея остается здравой.

Приведенный выше шаблон становится более полезным, когда вы хотите, чтобы New Relic отслеживал фоновые задания в вашем приложении. У вас гораздо больше шансов накатить какой-нибудь пользовательский фоновый код обработки заданий, чем на собственный веб-фреймворк. На самом деле, мы изначально делали это с Tuts +, хотя сейчас мы переходим на Sidekiq. Если вы используете одну из известных систем фоновых заданий, таких как Sidekiq , Resque или Delayed Job , в New Relic уже есть встроенные инструменты, но если вы выполнили свою собственную работу, вышеприведенный шаблон — это все, что вам нужно для мониторинга ваших задач.

Например, наши пользовательские фоновые задания Tuts + были обычными классами ruby, которые отвечали на метод execute , поэтому все, что нам нужно сделать, это:

1
2
3
4
5
6
7
8
class SomeBackgroundJob
  include NewRelic::Agent::Instrumentation::ControllerInstrumentation
 
  def execute
    …
  end
  add_transaction_tracer :custom_action, category: :task
end

Последний бит, category: :task , должен гарантировать, что New Relic не отслеживает ее как веб-транзакцию, а вместо этого обрабатывает ее как фоновую задачу и отображает ее на вкладке фоновых задач в интерфейсе New Relic. Если мы создадим базовый класс для всех наших работ, мы сможем разместить инструментарий там, и дочерние классы унаследуют его, поэтому нам не нужно беспокоиться о выполнении вышеупомянутого в каждом классе работ.

Интересно, что даже веб-транзакции, которые New Relic автоматически отслеживает, не являются священными. Например, вы можете добавить некоторые пользовательские параметры для отправки в New Relic для транзакции, которая выполняется в данный момент (если вы включили параметры захвата).

01_capture_parameters

Вы можете сделать это в любой момент во время транзакции. Все, что вам нужно сделать, это вызвать ::NewRelic::Agent.add_custom_parameters(:key => 'value') в любое время, и передаваемые вами параметры будут добавлены к данным параметров, которые вы видите внутри New Relic. Например, если у нас был контроллер, который выглядел так:

1
2
3
4
5
class HelloController < ApplicationController
  def index
    ::NewRelic::Agent.add_custom_parameters(:hello => ‘world’)
  end
end

Медленные транзакции дали бы нам следующее:

02_custom_parameter_display

Это не все, что мы можем сделать. Мы можем сегментировать транзакцию во время ее выполнения, переименовав ее. Допустим, мы хотим трактовать транзакцию как особенную, когда она выполняется конкретным пользователем. Вы можете сделать что-то вроде этого:

1
2
3
4
5
6
7
8
class HelloController < ApplicationController
  def index
    new_relic_name = NewRelic::Agent.get_transaction_name
    if current_user.name == ‘Joe Customer’
      NewRelic::Agent.set_transaction_name(«#{new_relic_name} — Joe Customer»)
    end
  end
end

Теперь эта транзакция будет обрабатываться как отдельная транзакция в интерфейсе New Relic:

03_segmented_transaction

Даже по умолчанию в инструментах New Relic есть место для настройки, но иногда, как и у Captain Kirk , вам просто нужно больше энергии. Это где пользовательские метрики приходят.


В свое время вы бы использовали пользовательские метрики для мониторинга таких вещей, как обмен данными с внешними сервисами и использование различных распространенных инструментов, таких как Redis . В наши дни у New Relic есть лучшие способы мониторинга этого материала , так зачем нам нужны собственные метрики? Я обнаружил, что пользовательские метрики полезны в четырех ситуациях:

  • контрольный код, который New Relic не видит
  • контрольный код, который вы не контролируете
  • скрипты мониторинга
  • мониторинг абсолютно пользовательских событий

Давайте кратко рассмотрим каждый из них.

New Relic довольно хорошо разбивает производительность различных методов приложения в трассировке транзакций, но иногда вы можете увидеть что-то подобное в трассировке:

04_uninstrumented_code

Кажется, есть код приложения, который New Relic по какой-то причине не смог установить. Что мы можем сделать, так это помочь New Relic (и нам самим) с помощью некоторых пользовательских метрик. Нам нужно выяснить, какой метод New Relic имел проблемы с мониторингом, и подключить некоторые пользовательские метрики, чтобы отслеживать, сколько времени потребовалось для выполнения этого метода. Это тогда появится во всех последующих следах. Допустим, у нас есть класс с методом, который мы хотим отслеживать с помощью пользовательских метрик:

1
2
3
4
5
class Order
  def amount
    …
  end
end

Мы можем начать отслеживать метод amount следующим образом:

01
02
03
04
05
06
07
08
09
10
require ‘new_relic/agent/method_tracer’
 
class Order
  include ::NewRelic::Agent::MethodTracer
 
  def amount
    …
  end
  add_method_tracer :amount, ‘Custom/amount’
end

Второй параметр add_method_tracer — это имя, которое эта пользовательская метрика получит в интерфейсе New Relic. Имена метрик — это разделенные косой чертой строки, и все пользовательские метрики должны начинаться с ‘Custom /’. Например, вы можете назвать свою пользовательскую метрику как «Custom / <имя_класса> / <имя_метода>». В этот момент вы начнете видеть метод amount в следах транзакций в интерфейсе New Relic. Но что, если наш метод amount очень сложен, и мы хотим отслеживать его части, которые, как мы подозреваем, являются медленными? Я советую вам реорганизовать свой метод — он слишком большой, но если вы не можете этого сделать, вы можете использовать произвольный код следующим образом:

01
02
03
04
05
06
07
08
09
10
11
class Order
  extend ::NewRelic::Agent::MethodTracer
 
  def amount
    …
    self.class.trace_execution_scoped([‘Custom/amount/complex_code’]) do
      …complex code…
    end
    …
  end
end

Теперь инструментальная часть метода будет сообщаться отдельно в ваших транзакциях. Если вы ранее инструктировали сам метод, ваша новая «внутренняя» метрика будет сгруппирована под предыдущей.

Это, безусловно, самый распространенный способ использования пользовательских метрик в вашем коде, но в любом случае давайте рассмотрим другие.

Часто вы можете использовать библиотеку, которая, как вы подозреваете, замедляет работу вашего приложения. Новая Реликвия по умолчанию не станет инструментом для вас, так что вы можете сделать? Вы можете разветвлять гем и добавить некоторые инструменты, используя метод, который мы видели выше, но существует еще более простое решение — использовать инициализаторы. Допустим, вы используете библиотеку foobar которой есть класс Foo с bar методов, которая, как вы подозреваете, содержит медленный код. Все, что вам нужно сделать, это создать инициализатор foobar_instrumentation.rb и поместить в него следующее:

1
2
3
4
5
6
7
require ‘new_relic/agent/method_tracer’
 
Foo.class_eval do
  include ::NewRelic::Agent::MethodTracer
 
  add_method_tracer :bar
end

Как вы можете видеть, код очень похож на тот, что был у нас выше, New Relic разработает разумное имя для вашей новой пользовательской метрики на основе имени класса и метода, и вы начнете видеть его в следах транзакций. Используйте это, чтобы определить, действительно ли эта подозрительная библиотека приводит к тому, что ваш код работает плохо, но не держите эту инструментацию постоянно. Он спамит ненужные инициализаторы в вашем приложении Rails и загрязняет ваш пользовательский интерфейс New Relic пользовательскими метриками, которые вам не нужно постоянно отслеживать.

Одна часть веб-приложений, которой часто пренебрегают, — это скрипты. Перефразируя презентацию, которую я сделал недавно — они все еще являются рабочим кодом и должны рассматриваться как таковые. Вы не хотите, чтобы производственный код работал плохо, особенно если вы выполняете его на постоянной основе с помощью заданий cron (или аналогичного метода, который не является фоновым заданием в вашей системе), поэтому мы можем использовать New Relic, чтобы выяснить, ваши сценарии медленные

Вы можете использовать свой код сценария с помощью пользовательских метрик, как описано выше. Он не будет отображаться в следах транзакций, поскольку он не будет частью транзакции. Однако вы сможете создать собственную панель мониторинга на основе собранных вами метрик, которая должна дать вам представление о том, плохо ли работает ваш скрипт.

Другая вещь, которую вы можете сделать, это обработать ваш скрипт как тип фонового задания и соответствующим образом его NewRelic::Agent::Instrumentation::ControllerInstrumentation (включая NewRelic::Agent::Instrumentation::ControllerInstrumentation и т. Д.). Он будет объединен с другими фоновыми заданиями в пользовательском интерфейсе, но вам не нужно беспокоиться о пользовательских панелях мониторинга.

Единственное предостережение со сценариями: New Relic периодически отправляет данные по сети. С помощью одноразового скрипта, который выполняется быстро, вам нужно будет убедиться, что собранные данные действительно будут отправлены, поэтому вам может потребоваться отключить агент New Relic вручную. Хорошее практическое правило — вручную запускать агент в начале каждого сценария и выключать его в конце:

1
2
3
4
5
6
7
require ‘newrelic_rpm’
 
::NewRelic::Agent.manual_start
 
… codez …
 
::NewRelic::Agent.shutdown

Таким образом, вам никогда не придется удивляться, почему ваши данные не отображаются в пользовательском интерфейсе.

Одна из интересных особенностей New Relic заключается в том, что он позволяет использовать преимущества пользовательского интерфейса и средств агрегирования данных для показателей, которые не имеют никакого отношения к производительности (теоретически). Например, вы можете захотеть получить представление о том, как часто пользователи регистрируются в вашем приложении, частоте продаж или общей сумме, которую пользователи платят при совершении покупок. Это больше бизнес-показателей, чем показателей производительности, но если отслеживать их по отдельности слишком сложно, вы можете использовать New Relic для этого.

Новая Relic позволяет записывать пользовательские метрики напрямую с помощью двух вызовов API:

  • record_metric
  • increment_metric

Вы можете использовать record_metric для отслеживания любой метрики, у которой есть сумма, и increment_metric довольно record_metric . Таким образом, мы можем, например, сделать это:

1
2
3
4
5
6
7
8
def purchase(amount)
  ::NewRelic::Agent.record_metric(‘Custom/purchase_amount’, amount)
  ::NewRelic::Agent.increment_metric(‘Custom/purchase_count’)
end

Единственный способ увидеть эти показатели в пользовательском интерфейсе — это создать несколько пользовательских панелей мониторинга. Я должен упомянуть, что это было бы несколько «творческим» использованием New Relic API, так как он разработан с учетом данных о производительности, но это, безусловно, удобная вещь, чтобы знать, когда вам нужно собрать быструю информационную панель вместе и не хочу создать кучу дополнительной инфраструктуры.


Конечно, вся эта сила имеет свою стоимость. Если вы соберете слишком много пользовательских метрик, это может замедлить работу вашего приложения. Это также может замедлить работу пользовательского интерфейса New Relic и затруднить интерпретацию данных, поскольку New Relic свернет аналогичные показатели в итоговые. New Relic рекомендует сохранить количество пользовательских метрик ниже 2000 . Я обнаружил, что пользовательские показатели лучше всего использовать периодически. Внесите необходимый код, воспользуйтесь инструментарием, чтобы решить возникшую проблему, а затем удалите инструментарий. Таким образом, вы решаете свои проблемы с производительностью, и количество используемых вами пользовательских показателей вряд ли будет слишком большим.


Мы newrelic_rpm внутреннюю часть newrelic_rpm и узнали, как сообщить New Relic о коде, который вы рассматриваете как веб-транзакцию. Мы рассмотрели, как изменять транзакции на лету, как отслеживать фоновые задания и различные ситуации, в которых имеет смысл использовать пользовательские метрики. Вы можете многое сделать с New Relic, помимо функциональности, которую он предоставляет «из коробки», и теперь вы гораздо более способны использовать ее в полной мере. Но всегда есть чему поучиться, например, как создавать собственные панели мониторинга на основе показателей, которые вы собираете, или как отслеживать инфраструктуру с помощью плагинов . Мы рассмотрим эти и другие темы в следующих статьях, поэтому не забывайте проверять их часто. И, как всегда, если у вас есть вопрос, вы хотите поделиться своей историей New Relic или просто сказать привет, не забудьте оставить комментарий.