Cloud Run (フルマネージド) にNew Relic APMを入れる

# はじめに
Cloud Runで稼働するWebアプリケーションを、New Relic APMでトレースしてみた話。

「[Cloud Run](https://cloud.google.com/run)」はGoogle Cloudのコンピューティングサービスの1つで、Knativeベースのフルマネージドなコンテナ実行サーバーレスプラットフォーム。コンテナでパッケージされたWebアプリを気軽にデプロイ & 公開できる。



Cloud Runには「フルマネージド」と「for Anthos」の2種類があり、今回は「フルマネージド」のCloud RunにNew Relic APMを導入した。

参考 : Cloud Run for Anthosへの導入については、[New RelicさんのBlog](https://blog.newrelic.com/product-news/new-relic-observability-for-google-cloud-anthos-and-cloud-run-deployments/
)で紹介されている

# 実装
デモ用にWebアプリケーションを実装し、トレースするためのNew Relic APMを導入する。

## Webアプリケーション

- Python 3.8.6
- フレームワーク : [Fast API](https://fastapi.tiangolo.com/ja/)

また、外部との通信をデモするため[httpbin.org](https://httpbin.org/)を活用する。

以下、今回のサンプルコード

```python:app.py
from fastapi import FastAPI
import requests

app = FastAPI()


@app.get("/")
def get_root():
    return {"Hello": "World"}


@app.get("/delay/{sec}")
def get_delay(sec: int):
    """
    sec秒遅延させる
    """
    requests.get("https://httpbin.org/delay/{}".format(sec))
    return {"sec": sec}


@app.post("/anything")
def post_anything():
    """
    情報を返す
    """
    r = requests.post("https://httpbin.org/anything")
    return r.json()
```

動作確認 実行

```bash
pip install fastapi
pip install uvicorn
pip install requests
uvicorn app:app --reload --host 0.0.0.0 --port 8000
```

## New Relic APM設定

インストールの仕方はDockerコンテナへの通常のインストール方法と同じ。

[Install the Python agent for Docker](https://docs.newrelic.co.jp/docs/agents/python-agent/installation/install-python-agent-docker)

`newrelic`モジュールをインストールし、`newrelic-admin run-program`を先頭につけて実行することで、APMエージェントによってトレースがされる。

Dockerfileは以下の通り。

```dockerfile:Dockerfile
FROM python:3.8.6-alpine

# Allow statements and log messages to immediately appear in the Knative logs
ENV PYTHONUNBUFFERED True

WORKDIR /opt/app
COPY . .

RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 8000

CMD ["newrelic-admin", "run-program", "uvicorn", "app:app", "--reload", "--host", "0.0.0.0", "--port", "8000"]
```

## サンプルコード
https://github.com/mmclsntr/newrelic_cloudrun_python

# Cloud Runへデプロイ
Dockerリポジトリには、最近GAとなったArtifact Resistryを使う。

- 対象のGCPプロジェクトのArtifact RegistryからDockerリポジトリを作成。リポジトリ名は「newrelictest」にする。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/22fafff7-9553-42d6-a1c4-5d20d09174a2.png)

- [Dockerに対する認証の設定](https://cloud.google.com/artifact-registry/docs/docker/authentication)を行う
- ローカルからビルド & プッシュ

```bash
docker build -t newrelic-cloudrun-python .
docker tag newrelic-cloudrun-python asia-northeast1-docker.pkg.dev/{GCP ProjectID}/newrelictest/newrelic-cloudrun-python
docker push asia-northeast1-docker.pkg.dev/{GCP ProjectID}/newrelictest/newrelic-cloudrun-python
```

- Cloud Runへデプロイする。今回はArtifact Registry画面からデプロイする。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/d1117a78-0c0e-7a1c-aadc-0c992f7b1f49.png)
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/51af0c35-e6a5-db80-1cb5-212149bed407.png)
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/9e1f779e-d634-2f2f-da8e-fb7d4f0f2ff0.png)
ポートは8000に設定。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/a5e6b8ab-be04-ae8d-a004-0eb3a775e5e0.png)
環境変数にNew Relic設定用のパラメータを指定。

パラメータ (一例)

|名前|説明|
|---|---|
|NEW_RELIC_LICENSE_KEY|ライセンスキー (必須)|
|NEW_RELIC_APP_NAME|アプリ名 (必須)|
|NEW_RELIC_DISTRIBUTED_TRACING_ENABLED|分散トレーシングのON/OFF (任意)|

[参考](https://docs.newrelic.co.jp/docs/agents/python-agent/configuration/python-agent-configuration)

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/99a39e27-4250-f5ae-c1d2-f30c7b74335c.png)
今回は未認証(公開)に設定。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/ecde6cae-b40e-3679-539a-3ee47bc57d92.png)

デプロイ。
デプロイ成功。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/630c07b3-5a9e-5c37-e462-e40c47cc8a5d.png)

生成されたURLに、いくつかリクエストを送っておく

```bash
curl https://newrelic-cloudrun-python-xxxxxx-an.a.run.app
curl https://newrelic-cloudrun-python-xxxxxx-an.a.run.app/delay/4
curl https://newrelic-cloudrun-python-xxxxxx-an.a.run.app/anything -X POST
```

# APM画面
トレース情報がNew Relicに送られているかどうか、New Relic APMの画面を確認する。

以下のような形で、リクエストイベントがトレースされ情報が表示される。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/12a5ab85-2654-3011-4134-9aa1a2e6fcd5.png)

ホスト名はlocalhostで認識される模様
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/cc1b7892-426f-4a3b-f2b7-2d58c10e21cc.png)

今回`NEW_RELIC_DISTRIBUTED_TRACING_ENABLED`を`true`にしているため、分散トレーシングの情報についてもこのように表示される。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/42adbdc2-e73f-22cd-9571-eb71ecf6f000.png)

その他レポートについても通常通り収集される。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241369/0502a1a6-0aba-045e-7a55-14e8c99af0e3.png)


# まとめ
APMのDockerコンテナへの通常のインストール方法と変わりなく、エージェントをDockerfileに記載して、あとは実行時に任意のNew Relicの環境変数を設定すればOK。気軽に導入できた。