LoginSignup
2
0

AWS Distro for OpenTelemetry で Laravel から AWS X-ray に trace を送ってみる

Last updated at Posted at 2023-12-19

この記事は、AWS Containers Advent Calendar 2023 の 19 日目 (12/19) のエントリーです。

PHP のフレームワーク Laravel で、ADOT (AWS Distro for OpenTelemetry) を利用した trace の送信を試した備忘録です。
正直、設定の書き方がわかっていないので、正しい書き方などのツッコミをお待ちしております。

AWS Distro for OpenTelemetry とは、OpenTelemetry プロジェクトの AWS がサポートするディストリビューションです。

各言語ごとの対応状況は以下にあります。
https://opentelemetry.io/docs/instrumentation/#status-and-releases
PHP が trace に対応しているため、PHP Laravel を利用して trace の送信を試してみます。

基本的にはこちらの手順を参考にして trace を AWS X-Ray に送信します。

Laravel プロジェクト作成

Composer を使ってパッケージ/ライブラリ管理を行うため、まず Composer をインストールします。
インストール手順は こちら にありますが、Mac だと brew でインストール することができます。

$ brew install composer

こちらの手順 に沿って、Laravel のプロジェクトを作成します。

$ composer create-project laravel/laravel example-app

Laravel を起動します。

$ cd example-app
$ php artisan serve

http://localhost:8000 にアクセスすると初期画面が表示されます。
スクリーンショット 2023-12-17 15.19.55.png

OpenTelemetry の自動計装

Automatic Instrumentation を使ってみます。
Automatic Instrumentation を利用するには、PHP 8.0 以上と、OpenTelemetry の PHP 拡張モジュール が必要です。

拡張モジュールは pecl、 picklephp-extension-installer が利用可能です。
それぞれの方法での インストール方法はこちら にあります。今回は pecl でのインストールを行ってみます。
pecl は PHP 拡張モジュールのリポジトリで、 pear パッケージシステムを経由して使用可能です。
まずソースからビルドするために必要なものを設定します。

$ brew install gcc make autoconf

pecl で OpenTelemetry の PHP 拡張モジュールをビルド、インストールします。

$ pecl install opentelemetry

ここでいくつかエラーがでました。

Build process completed successfully
Installing '/usr/local/Cellar/php/8.3.0/pecl/20230831/opentelemetry.so'

Warning: mkdir(): File exists in System.php on line 294
PHP Warning:  mkdir(): File exists in /usr/local/Cellar/php/8.3.0/share/php/pear/System.php on line 294

Warning: mkdir(): File exists in /usr/local/Cellar/php/8.3.0/share/php/pear/System.php on line 294
ERROR: failed to mkdir /usr/local/Cellar/php/8.3.0/pecl/20230831

/usr/local/Cellar/php/8.3.0/pecl/20230831 が無いようです。
確認してみると、/usr/local/Cellar/php/8.3.0/pecl/usr/local/lib/php/pecl のシンボリックリンクになっていましたが、pecl というディレクトリが作られていませんでした。

$ cd /usr/local/lib/php/    
$ ll
total 0
lrwxr-xr-x@ 1 kajihiro  admin  39 12 17 00:32 20230831 -> ../../Cellar/php/8.3.0/lib/php/20230831
lrwxr-xr-x@ 1 kajihiro  admin  36 12 17 00:32 build -> ../../Cellar/php/8.3.0/lib/php/build

原因までは調べていませんが、pecl ディレクトリを作成し、20230831 ディレクトリの中身をコピーしたところ正常にインストールが行われました。

php.ini に拡張モジュールを設定し、確認します

php.ini
extension=opentelemetry.so
$ php -m | grep opentelemetry
opentelemetry

これで OpenTelemetry の PHP 拡張モジュールが設定されました。
しかし、 2023年12月時点では、Automatic Instrumentation は trace に対応していないようです・・・
https://opentelemetry.io/docs/instrumentation/php/automatic/

Installing the OpenTelemetry extension by itself will not generate traces. You must also install the SDK and one or more instrumentation packages for the frameworks and libraries that you are using, or alternatively write your own.

なので、trace を送る設定を手動で入れていきます。

OpenTelemetry の手動計装

手動での trace の設定は こちらの手順 で進めていきます。
PHP 用 OpenTelemetry SDK を使用するには、psr/http-client-implementation と psr/http-factory-implementation の依存関係を満たすパッケージが必要です。ここでは、両方を提供する Guzzle を使用します。
PSR (PHP Standards Recommendations) とは、PHP-FIG (PHP Framework Interop Group) が策定している PHP のコーディング規約です。

必要なパッケージをインストールしていきます。

$ composer require guzzlehttp/guzzle
$ composer require \
  open-telemetry/sdk \
  open-telemetry/exporter-otlp

こちらの手順 を見ながら trace の計装をしていきます。

public/index.php
require __DIR__.'/../vendor/autoload.php';
use OpenTelemetry\API\Globals;
$tracerProvider = Globals::tracerProvider();
$tracer = $tracerProvider->getTracer(
  env('OTEL_SERVICE_NAME'),
  '1.0.0', //version
  env('OTEL_EXPORTER_OTLP_ENDPOINT'), //schema url
);
$span = $tracer->spanBuilder(env('OTEL_SERVICE_NAME'))->startSpan();
//do some work
$span->end();

※設定値を環境変数から読み込むようにしています。
が、ここでエラーが発生しています。

Use of unknown class: 'OpenTelemetry\\API\\Globals'

どうやら必要なパッケージが足りないようなので追加をします。

$ composer require open-telemetry/api

Laravel 起動

関連するコンポーネントと一緒に Laravel を起動し、HTTP でリクエストを受けるために docker compose を利用して構築を行います。この際に trace を送るための otel-collector コンテナも一緒に起動します。
ファイル構成は以下のようになっています。

php
├── nginx
│   ├── Dockerfile
│   └── conf.d
│       ├── default.conf
│       └── default.conf.template
└── phpfpm
    ├── Dockerfile
    ├── example-app
    └── php.ini
FROM nginx:alpine
ADD ./conf.d /etc/nginx/conf.d

RUN ln -sf /dev/stdout /var/log/nginx/access.log
RUN ln -sf /dev/stderr /var/log/nginx/error.log

後に記載しますが、envsubst を使って環境変数から設定を持ってくるようにしています。

php/nginx/conf.d/default.conf.template
server {
    listen       8080;
    charset      utf-8;

    root /var/www/html/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        
        fastcgi_pass ${LARAVEL_HOST}:9000;
        fastcgi_index index.php;
        include       fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

}

nginx のビルドの際に環境変数から値を取得して default.conf を生成するようにしています。

docker-compose.yaml
version: '3'
services:
  nginx-php:
    build:
      context: ./php/nginx
      dockerfile: ./Dockerfile
    volumes:
      - ./php/phpfpm/example-app:/var/www/html
    ports:
      - 8080:8080
    depends_on:
      - phpfpm
    environment:
      LARAVEL_HOST: phpfpm
    command: sh -c "envsubst '$$LARAVEL_HOST' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
  phpfpm:
    build:
      context: ./php/phpfpm
      dockerfile: ./Dockerfile
    volumes:
      - ./php/phpfpm/example-app:/var/www/html
    ports:
      - 9000:9000
    environment:
      OTEL_PHP_AUTOLOAD_ENABLED: true
      OTEL_SERVICE_NAME: "local-laravel-app"
      OTEL_TRACES_EXPORTER: otlp
      OTEL_EXPORTER_OTLP_PROTOCOL: http/protobuf
      OTEL_EXPORTER_OTLP_ENDPOINT: 'http://otel-collector:4318'
      OTEL_PROPAGATORS: baggage,tracecontext
  otel-collector:
    image: public.ecr.aws/aws-observability/aws-otel-collector:latest
    command: [ "--config=/etc/otel-agent-config.yaml" ]
    environment:
      - AWS_PROFILE=default
      - AWS_REGION=us-east-1
    volumes:
      - ./otel-config.yaml:/etc/otel-agent-config.yaml
      - ~/.aws/credentials:/root/.aws/credentials:ro
      - ~/.aws/config:/root/.aws/config:ro
    ports:
      - 4317:4317
      - 4318:4318

otel-collector が AWS X-ray の API を実行できるように credential 情報を渡しています。こちらはローカルで実行する場合の設定なので、ローカル PC に保存されている credential 情報をコンテナの volume に渡して利用しています。

environment:
  - AWS_PROFILE=default
  - AWS_REGION=us-east-1
volumes:
  - ./otel-config.yaml:/etc/otel-agent-config.yaml
  - ~/.aws/credentials:/root/.aws/credentials:ro
  - ~/.aws/config:/root/.aws/config:ro

コンテナを起動します。
コンテナ開発用のオープンソースクライアント「Finch」を利用しています。

$ finch compose -f docker-compose.yaml up -d

localhost で起動している nginx にアクセスします。

http://localhost:8080
スクリーンショット 2023-12-19 19.31.22.png

Trace データの確認

AWS X-ray に trace が送られているか確認します。
スクリーンショット 2023-12-19 19.07.10.png
スクリーンショット 2023-12-19 19.07.52.png

無事 trace データが送られていました。

まとめ

ローカルの Laravel から OpenTelemetry を利用して trace を送る手順を試してみました。
本番環境で動かす場合 (Amazon EKS や Amazon ECS で動かす場合) は、credential や環境変数の情報を適宜 AWS Systems Manager Session ManagerAWS Secrets Manager に保存・利用してください。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0