これは
New Relic や Datadog の APM 以外の APM を探して三千里している過程で、無料で試せる Elastic APM に出会ったので、Docker を利用して Elastic APM を動かす環境 (Rails を利用する) を作ってみたのでメモしておきます。
Elastic APM とは
あの Elastic 社が提供している APM (Application Performance Monitoring/Management) サービスで、アプリケーションのパフォーマンス監視ができるソフトウェアです。
Elastic APM の特徴としては、
- OSS として提供されているので、ソフトウェア自体は無償で利用出来る
- 多少馴染みのある Kibana で利用出来る
- エラー情報 (Stack Trace 等の情報) も統合することが出来る (らしい
- もちろん、Ruby や Rails でも利用出来る
Elastic APM 5min Setup
用意するもの
リポジトリ
注意
- 事前に Docker と docker-compose が利用出来るようにしておくこと
docker-compose.yml
version: '3' services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:7.7.1 environment: - discovery.type=single-node - bootstrap.memory_lock=true - cluster.name=docker-cluster - cluster.routing.allocation.disk.threshold_enabled=false - ES_JAVA_OPTS=-Xms512m -Xmx512m volumes: - es_data:/usr/share/elasticsearch ports: - 9200:9200 ulimits: memlock: soft: -1 hard: -1 apm: image: docker.elastic.co/apm/apm-server:7.7.1 volumes: - ./apm/apm-server.yml:/usr/share/apm-server/apm-server.yml depends_on: - elasticsearch - kibana ports: - 8200:8200 kibana: image: docker.elastic.co/kibana/kibana:7.7.1 depends_on: - elasticsearch environment: ELASTICSEARCH_URL: http://elasticsearch:9200 ELASTICSEARCH_HOSTS: http://elasticsearch:9200 ports: - 5601:5601 api: build: . ports: - "3000:3000" depends_on: - db volumes: - .:/app environment: ELASTIC_APM_SERVER_URL: http://apm:8200 command: bundle exec rails s -p 3000 -b '0.0.0.0' db: image: mysql:5.7 volumes: - mysql_data:/var/lib/mysql/ environment: MYSQL_ROOT_PASSWORD: password ports: - "3306:3306" volumes: mysql_data: es_data:
Dockerfile
FROM ruby:2.7.2 RUN apt-get update -qq && apt-get -y install \ build-essential \ libpq-dev \ nodejs RUN mkdir /app COPY Gemfile /app WORKDIR /app RUN gem install bundler && bundle install
Gemfile
この Gemfile はサンプルアプリケーション環境に Rails をインストールする為だけに利用され、rails new
する際に上書きされます。
# frozen_string_literal: true source "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } gem 'rails', '~> 6.0.4', '>= 6.0.4.6'
apm/apm-server.yml
このファイルが Elastic APM サーバーの設定ファイルです。
apm-server: host: "0.0.0.0:8200" kibana: enabled: true host: kibana:5601 rum: enabled: true output: elasticsearch: hosts: ["elasticsearch:9200"] setup: kibana: host: kibana:5601 template: settings: index: number_of_replicas: 0
database.yml.patch
database.yml の設定内容を更新する為のパッチファイルです。
--- config/database.yml.bk 2022-03-06 11:53:00.000000000 +0900 +++ config/database.yml 2022-03-06 11:53:12.000000000 +0900 @@ -14,8 +14,8 @@ encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root - password: - host: localhost + password: password + host: db development: <<: *default
run-test.sh
起動したサンプルアプリケーションにリクエストを投げまくるテスト用シェルスクリプトです。
#!/bin/bash while true do curl -s -X POST -H "Content-Type: application/json" -d '{"name": "hoge"}' http://localhost:3000/users -o /dev/null -w '%{http_code}\n' curl -s -X GET http://localhost:3000/users -o /dev/null -w '%{http_code}\n' sleep 1 done
セットアップ
ファイル構成
初期段階 (リポジトリを git clone
した段階) では、以下のようなファイル構成になっています。
$ tree . . ├── Dockerfile ├── apm │ └── apm-server.yml ├── database.yml.patch ├── docker-compose.yml └── run-test.sh 1 directory, 5 files
Rails がインストールされているコンテナイメージを作成
$ docker-compose build --no-cache
Rails 環境を API モードで作成 (DB は MySQL)
$ docker-compose run api rails new . --force --database=mysql --api
Elastic APM の gem を追加
$ echo "gem 'elastic-apm'" >> Gemfile
もう一回、Rails コンテナイメージを作成
$ docker-compose build --no-cache
scaffold
$ docker-compose run --rm api rails generate scaffold User name:string
database.yml を設定
$ cd config $ patch < ../database.yml.patch $ cd ../
データベース作成、マイグレーション
$ docker-compose run --rm api rails db:create $ docker-compose run --rm api rails db:migrate
全部のコンテナを起動
$ docker-compose up -d
正常に全てのコンテナが起動すると、下図のように 5 つのコンテナが起動している状態になると思います。
$ docker-compose ps Name Command State Ports ---------------------------------------------------------------------------------------------------------------------------------- elastic-apm-sandbox_api_1 bundle exec rails s -p 300 ... Up 0.0.0.0:3000->3000/tcp,:::3000->3000/tcp elastic-apm-sandbox_apm_1 /usr/local/bin/docker-entr ... Up 0.0.0.0:8200->8200/tcp,:::8200->8200/tcp elastic-apm-sandbox_db_1 docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp,:::3306->3306/tcp, 33060/tcp elastic-apm-sandbox_elasticsearch_1 /tini -- /usr/local/bin/do ... Up 0.0.0.0:9200->9200/tcp,:::9200->9200/tcp, 9300/tcp elastic-apm-sandbox_kibana_1 /usr/local/bin/dumb-init - ... Up 0.0.0.0:5601->5601/tcp,:::5601->5601/tcp
run-test.sh を実行
$ ./run-test.sh
Try! Elastic APM
Kibana にアクセス
コンテナが正常に起動した後、ブラウザで、以下の URL にアクセスします。
http://localhost:5601
APM メニューにアクセス
下図の APM をクリックします。
Services
Name
の App
をクリックします。
Transactions
UsersController#create
のリンクをクリックすると、下図のようにリクエストをトレース (API コールやデータベースのクエリ等) をドリルダウンして確認することが出来ます。
15 分くらい触ってみた感想
- New Relic ほど色々出来るわけでは無さそう
- ひとまず、アプリケーション内部のレイテンシー等の最低限の機能は提供されていそう
- シュッと Docker で試せるのは良い