Автоматический запуск профайлера в New Relic
Date November 19th, 2013 Author Vitaly Agapov
Несколько лет назад я уже писал статью про свой игрушечный Perl'овый скриптик, авторизующийся на странице. Новой практической задачи пришлось ждать довольно долго. Но она появилась. После недавнего обновления клиентов New Relic у них появилась возможность профилировать все потоки приложения (Java, Ruby, да хоть PHP), чтобы была возможность определить, в каких тредах и на каких методах происходит потеря времени. Запуск профайлера производится из веб-интерфейса, куда надо сначала залогиниться. А очень хотелось записывать дампы по расписанию или, допустим, по наступлению некоего события вроде слишком высокого времени ответа или высокой загрузки CPU.
А пол-дела уже и сделано. Осталось припомнить основы работы с модулем LWP::UserAgent и посмотреть firebug'ом, как проходит авторизация, подстановка CSRF-токенов и отправка форм в интерфейсе New Relic.
Дальше я просто приведу сам скрипт с разбросанными тут и там комментариями. Думаю, больше ничего не понадобится.
001.
#!/usr/bin/perl
002.
use
LWP::UserAgent;
003.
use
HTML::Entities;
004.
use
Data::Dumper;
005.
006.
my
$debug
= 0;
007.
my
$login
=
'mylogin'
;
008.
my
$pwd
=
'mypassword'
;
009.
my
$urlGetLogin
=
"https://rpm.newrelic.com/login"
;
010.
my
$urlPostLogin
=
"https://rpm.newrelic.com/session"
;
011.
my
$urlGetProfiler
=
"https://rpm.newrelic.com/accounts/my_acc_id/applications/my_app_id/profiles"
;
012.
my
$urlPostProfiler
=
"https://rpm.newrelic.com/accounts/my_acc_id/applications/my_app_id/profiles"
;
013.
my
$profileDuration
= 2;
014.
015.
my
$ua
= LWP::UserAgent->new;
016.
017.
# Забираем страницу с формой логина и получаем куки с идентификатором сессии и находим CSRF-токен
018.
my
$req
=
$ua
->get(
$urlGetLogin
);
019.
020.
my
$csrfToken
= getToken(
$req
->content);
021.
my
$cookie
=
$req
->{_headers}->{
'set-cookie'
};
022.
my
$uiSession
= getSession(
$cookie
);
023.
if
(!
$uiSession
|| !
$csrfToken
|| !
$req
->{_msg} eq
"OK"
) {
print
"Cannot get login page\n"
;
exit
1; }
024.
025.
# Отправляем POST на логин, из которого опять забираем новые куки
026.
$req
=
$ua
->post(
$urlPostLogin
,
027.
[
028.
'authenticity_token'
=>
$csrfToken
,
029.
'login[email]'
=>
$login
,
030.
'login[password]'
=>
$pwd
,
031.
'login[remember_me]'
=> 0,
032.
'login[oauth_signin]'
=>
''
,
033.
'utf8'
=>
'✓'
,
034.
],
035.
cookie =>
$cookie
036.
);
037.
038.
$cookie
=
$req
->{_headers}->{
'set-cookie'
};
039.
my
$loggedIn
= getLoggedIn(
$cookie
);
040.
print
Dumper(
$req
)
if
(
$debug
);
041.
042.
# Если в куке nr_zd_logged_in нет значения true, значит логин не удался и можно расходиться
043.
if
(
$loggedIn
ne
'true'
) {
print
"Cannot login\n"
;
exit
1; }
044.
045.
# Забираем страницу с формой запуска профайлера. Здесь нас опять интересует CSRF-токен, а также Agent-ID.
046.
$req
=
$ua
->get(
$urlGetProfiler
,
047.
cookie =>
$cookie
048.
);
049.
$csrfToken
= getToken(
$req
->content);
050.
051.
print
Dumper(
$req
)
if
(
$debug
);
052.
my
$realAgentId
= getRealAgentId(
$req
->content);
053.
054.
# И, наконец, POST на запуск профайлера. У нас есть кука с сессией, Agent-ID, CSRF-токен. В общем, всё для успешного запуска
055.
$req
=
$ua
->post(
$urlPostProfiler
,
056.
[
057.
'authenticity_token'
=>
$csrfToken
,
058.
'profile[duration]'
=>
$profileDuration
,
059.
'profile[real_agent_id]'
=>
$realAgentId
,
060.
'utf8'
=>
'✓'
,
061.
],
062.
cookie =>
$cookie
063.
);
064.
065.
# В случае успешного запроса мы должны вывести "ОК"
066.
print
$req
->{_msg};
067.
print
Dumper(
$req
)
if
(
$debug
);
068.
069.
exit
0;
070.
071.
# Функции для парсинга заголовков и тел сообщений
072.
sub
getToken {
073.
my
$content
=
shift
;
074.
if
(
$content
=~ /<meta name=
"csrf-token"
content=
"(.+?)"
\/>/) {
075.
# В токене могут присутствовать HTML-коды, поэтому нам пригодится модуль HTML::Entities и функция decode_entities
076.
return
decode_entities(
$1
);
077.
}
078.
return
0;
079.
}
080.
sub
getRealAgentId {
081.
my
$content
=
shift
;
082.
if
(
$content
=~ /name=
"profile\[real_agent_id\]"
type=
"radio"
value=
"(\d+)"
/) {
083.
return
$1
;
084.
}
085.
return
0;
086.
}
087.
sub
getSession {
088.
my
$cookie
=
shift
;
089.
if
(
$cookie
=~ /_newrelic_ui_session=(.+?);/) {
090.
return
$1
;
091.
}
092.
return
0;
093.
}
094.
sub
getLoggedIn {
095.
my
$cookie
=
shift
;
096.
foreach
(@{
$cookie
}) {
097.
if
(/nr_zd_logged_in=(.+?);/) {
098.
return
$1
;
099.
}
100.
}
101.
return
0;
102.
}
Tags: Perl
Category:
Perl |
No comments »