Newrelic APMを使う上で覚えておくと便利なTips

# はじめに

グリー株式会社開発本部のwithgodです。

NewRelicさんからAdvent Calendarのお誘いを受けましたので何かお役に立てればと思いTipsを並べてみます。

NewRelic導入前に予め知ってると微妙に役に立ちそうな物を書いてみます。

# 注釈

コードは全てPHPでの設定例ですが、他言語でも同様の設定は行えるはずです。

こんな書き方もあるよ、という例になればと思い同じ事も複数の書き方を行っております。
(文字列を精査する場合にstrposやpreg_matchなど複数使い記述を統一していない)

コードの設定はなるべく実行されるスクリプトの起動直後に実行されるようにした方が良いです。後ろの方の場合到達前に未指定で実行される可能性があります。

# Tips

## Application名はini以外でも実行時に設定出来る

* https://docs.newrelic.com/docs/agents/php-agent/php-agent-api/newrelic_set_appname

同一のコードでアプリケーション名を変えたり、一つのホストで複数のアプリを動かしていたりbatch job等でアプリケーション名を変更したい場合に利用できます。
iniはサーバ毎に変更可能ですが、コードで統一して変更出来た方が嬉しいことが多く弊社ではコード側で変更することが多いです。

```php
if (extension_loaded(newrelic)) {
	$appname = 'default';
	if (isset($_SERVER['SERVER_NAME'])) {
		if ($_SERVER['SERVER_NAME'] == 'games.example.net') {
			$appname = 'games';
		} elseif ($_SERVER['SERVER_NAME'] == 'dev-games.example.net') {
			$appname = 'dev-games';
		}
	}
	// vhost以外での切り分けならdocument_rootも有効です
	if ($_SERVER['DOCUMENT_ROOT'] == '/var/www/app1') {
		$appname = 'app1';
	}

	if (php_sapi_name() == 'cli') {
		$appname .= '-cli';
	}

	newrelic_set_appname($appname);
}
```

## transaction名は任意の指定が出来る

* https://docs.newrelic.com/docs/agents/php-agent/php-agent-api/newrelic_name_transaction

laravelのように著名なフレームワークを利用していれば自動的にtransaction名を指定してくれますが、マイナーなフレームワークを利用していたりしてURL rewriteをしてたりすると全て index.php に纏められてしまいます。

それらを避けたり、分割されてしまうURLを一つに纏めたい時などは次のようにコードで任意の値が利用可能です。

```php
if (extension_loaded(newrelic)) {
	$trx_name = 'unknown';

	// REQUEST URLだけで上手く動作しない場合、$_SERVERに含まれる REDIRECT_URL, REQUEST_URI, SCRIPT_NAME 辺りが参考になると思われます
	$trx_name = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : 'no_uri';
	$tmp	  = explode('?', $trx_name, 2);
	$trx_name = $tmp[0];

	// index.php?controller=shop&action=index 
	// 上記のようなURLパターンの場合見やすくしたければ次のように出来ます
	if (isset($_REQUEST['controller']) && isset($_REQUEST['action'])) {
		$trx_name =  '/' . $_REQUEST['controller']. '/' . $_REQUEST['action'];
	}

	// ロジック的には同一なのに別URLと認識されてしまい大量の transaction が発行されてしまう場合一つに纏めたい場合は次のように出来ます
	// あまりにも大量のtransactionを発行した場合、newrelicのレポートを停止される場合もあるためその回避にも有効です。
	// /battle/{battleid} => /battle/b026324c6904b2a9cb4b88d6d61c81d1
	if (preg_match('#/battle/[0-9a-f]{32}#i', $trx_name)) {
		$trx_name = '/battle/*';
	}
	// /gvg/{yyyy}/{mmdd}/{seqid} => /gvg/2019/1201/01
	if (preg_match('#/gvg/([0-9]{4})/([0-9]{4})/([0-9]+)#', $trx_name, $matches)) {
		$trx_name = '/gvg/' . $matches[1] . '/*/*';
	}

	newrelic_name_transaction($trx_name);
}
```

## transactionを送信しないようにする

管理画面やファイルダウンロード等で結果送信の必要が無い場合送信自体を取りやめることが出来ます。

* https://docs.newrelic.com/docs/agents/php-agent/php-agent-api/newrelic_ignore_transaction

```php
if (extension_loaded('newrelic')) {
	switch ($_SERVER['REQUEST_URI']) {
		case(preg_match('#\.(mp[34]|mov|flv)$#', $_SERVER['REQUEST_URI'])):
		case(strpos($_SERVER['REQUEST_URI'], '/admin') == 0):
			newrelic_ignore_transaction();
			break;
	}
}
```

## RUM機能(Newrelic Browser)を無効化する

newrelic extensionはコンテンツ内容にあわせて Newrelic Browserを動作させるためのJavascriptを自動挿入します。
ただ、クライアント環境によってはエラーになってしまいます。(ex. amp, ガラケー)

ampはampで専用のサーバで処理しているのであればnewrelic.iniで一括停止も出来ますが、環境が同居している場合はコードで抑止出来ます。

* https://docs.newrelic.com/docs/agents/php-agent/php-agent-api/newrelic_disable_autorum
* https://docs.newrelic.com/docs/browser/new-relic-browser/troubleshooting/browser-javascript-injection-causes-problems-page
* https://docs.newrelic.com/docs/agents/php-agent/configuration/php-agent-configuration#inivar-autorum

```php
if (extension_loaded('newrelic')) {
	if (
		strpos($_SERVER['REQUEST_URI'], '/amp/') !== FALSE) ||
		strpos($_SERVER['HTTP_USER_AGENT'], 'DoCoMo') !== FALSE)
	) {
		newrelic_disable_autorum();
	}
}
```

## newrelicを入れる際に一括で対応コードを入れたい

最近の環境であれば殆どの場合 composer が利用されいて Bootstrap に当たる物が存在しますが、古い環境に導入する場合だと共通のファイルが存在しないことがあります。

Webはせめて共通のファイルがあったりしますが、batchは沢山書き捨てられていたりも多々あります。

そのような場合、 auto_prepend_file(PHP_INI_PERDIR) を使うことで一律でファイルを読み込ませることが出来ます。

* https://www.php.net/manual/ja/ini.core.php#ini.auto-prepend-file

```
; Automatically add files before PHP document.
; http://php.net/auto-prepend-file
auto_prepend_file = /path/to/newrelic-bootstrap.php
```

本記事で説明してる物をまとめたファイルを作ってここに指定することによって全てに反映することが出来ます。

##