2018年4月27日金曜日

tideways で PHP のパフォーマンスを測定する

弊社で管理しているシステムの本番環境に tideways を試験的に導入してみました。
まだトライアル期間中で色々と機能を試しているところですが、導入にあたっての疑問点などをまとめておきます。

特徴

プロファイラとしての主だった特徴は、この辺りです
  • SaaS 型のサービスなので管理コストが不要
  • 本番環境に導入できる
代替サービスとして blackfire がありますが、こちらは年間プランしかないので試用期間後の有料版契約のハードルが重く、まずは tideways を試してみることにしました。

SaaS 型のサービスなので管理コストが不要

管理コストを考えたときに、月数千円~2万円の範囲であれば、メンテナンス工数よりも安上がりだと判断しました。もちろんこの辺りはプロジェクトの規模・メンバ構成・ビジネス的なキャッシュフローの質によって変わるところではあります。

本番環境に導入できる

また、「事件は開発環境で起きているんじゃない、本番環境で起きているんだ!」ということで今回は本番環境に導入できることを重要視しました。
(選択肢から Xdebug 等が除外されます)

導入方法

びっくりするぐらいに簡単です。

まずは、ユーザ登録をするとダッシュボードから組織をアプリを作成することができるので、作成します。


インストール

Create Application すると、このような導入手順が表示されるので、素直に yum install するだけです。

OS を切り替えると、OS 毎に異なるコマンドを表示してくれます。

設定

同じように設定内容が API KEY と共に表示されているので、素直に設定します。
php.ini で設定する例

こちらも、設定方法を切り替えると方法に応じた設定を表示してくれます。

framework は指定してもしなくても問題ありません。
指定することのメリットは、トランザクション名を自動的に生成してくれることです。
指定しない/指定したのに働かない 場合は、このように手動で設定します。
<?php

class Dispatcher
{
    public function dispatch($controllerClass, $actionName)
    {
        // Add this four lines to set the transaction name
        $transactionName = $controllerClass . '::' . $actionName;
        if (class_exists('Tideways\Profiler')) {
            \Tideways\Profiler::setTransactionName($transactionName);
        }

        $controller = new $controllerClass();
        return $controller->$actionName();
    }
}
https://tideways.io/profiler/article/40-transactions より

成功すると、こんな感じでログが表示されます。

パフォーマンスが悪い箇所が分かっている場合は、"HTTP" などと表示してくれています。

で、特定のトランザクション名を選択すると、取得した Trace が表示されます。
取得できる Trace 数には制限があるので、全ての処理を Trace しているわけではないので、無い時もあります。(どういう基準で Trace しているのかはわかりません。。)

Trace があれば、選択するとこのようにタイムラインを表示してくれます。

ここまで見れれば、大抵の問題は解決できるでしょう。

以上。

2018年4月4日水曜日

Azure VM がエラー「This suggests the guest OS has not been properly prepared to be used as a VM image (with CreateOption=FromImage)」で起動しない。

問題発生…

Azure でカスタムイメージを作成して、そこから VM を作成したところ「This suggests the guest OS has not been properly prepared to be used as a VM image (with CreateOption=FromImage)」エラーが発生して VM を起動することができませんでした。

原因は、、

色々と調べたところ、VM が「This suggests the guest OS has not been properly prepared to be used as a VM image (with CreateOption=FromImage)」エラーで起動できなくなったのは、カスタムイメージの作成時に「プロビジョニング解除」の処理を忘れたまま、イメージを作成したのが原因のようでした。

カスタムイメージの作成時には、「プロビジョニング解除」を行ってから、VM の割り当てを解除→キャプチャの手順を踏む必要がありますが、それをすっ飛ばしていました。

積んだ…?

それに気づいたので、さあ「プロビジョニング解除」をやり直そう!と思っても、1度キャプチャして一般化された VM を再び起動することはできず。
残されたのは

  • 一般化された使えないVM(ゴミ)
  • 使えないカスタムイメージ(ゴミ)

という状況。元の環境を復旧するすべはないように思えました。。。

たどり着いたゴール!

最終的に解決に導いたのはこの記事。色々検索すると、2017年頃に作成された MS 製の記事が色々と見つかります。ユーザが Googling でトラブルシューティングできるように力を入れてますね。

解決方法は、「ディスクから再び VM を作成し直す。」でした。
要するに、

  • 「ディスク」を残したまま、キャプチャして使えなくなった VM を破棄
  • 「ディスク」から VM を作成すると、VM 復活!

ということでした。

詳細は、こちらの記事にをご確認くださいませ。
https://blogs.technet.microsoft.com/jpaztech/2017/11/21/cannot-start-vm/

Happy googling life!

2018年4月2日月曜日

Azure で Linux VM を複製(コピー)する。

Azure で VM を複製しようとしたら、まとまった情報がなく意外と手間だったので記録しておきます。

前提

  • GUI でやってます。Power Shell は使いません
  • 複製元とする VM が起動中(SSH接続可能)であることが必要です
  • 複製元とする VM は停止が必要です
  • Linux VM です

基本手順

VM を複製する基本手順は以下の 4STEP です。
  1. VM のプロビジョニングを解除
  2. VM を停止
  3. VM をキャプチャしてイメージを作成
  4. イメージから VM を作成

VM のプロビジョニングを解除

複製元としたい VM に SSH で接続し、プロビジョニング解除用のスクリプトを実行します。以下の手順です。(※SSH の情報は複製元としたい VM の情報に置き換えてください)

VM に SSH 接続します。
bash
ssh azureuser@52.174.34.95
VM のプロビジョニングを解除します。
bash
sudo waagent -deprovision+user -force
SSH セッションを閉じます。
bash
exit

※ https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/tutorial-custom-images#deprovision-the-vm より引用

VM の停止

GUI から VM を停止させます


VM を停止する

VM をキャプチャしてイメージを作成

キャプチャボタンを押下して、


キャプチャ

作成するイメージ名とそのリソースグループを入力して、イメージを作成します。
ここで作成するイメージから、新規に VM を作成できるようになります。

イメージの作成

成功すると、このようにリソースグループに "イメージ" というリソースが追加されます。


イメージが追加された

イメージから VM を作成

そうすると、作成したイメージから、「VM の作成」ができるようになります。


「VM の作成」ができる


その後は、いつもの VM 作成画面になります。
必要事項を入力していけば完了。


いつもの VM 作成画面

以上。

参考

https://docs.microsoft.com/ja-jp/azure/virtual-machines/linux/tutorial-custom-images#deprovision-the-vm



2018年4月1日日曜日

Lumin SDK を Unity / Unreal Engine 4 で Hello World.

Lumin SDK をインストールして、Unity と Unreal Engine 4 で Hello World したときのメモです。

Lumin SDK とは?

Magic Leap One で動くアプリを開発するための SDK です。
こちらから DL できます。
https://creator.magicleap.com/home

Magic Leap One とは?

この辺を見てください。
https://japanese.engadget.com/2017/12/20/ar-magic-leap-one-2018/

Lumin SDK x Unity / Unreal Engine 4 で Hello World するまで

基本的には、ここの Tutorials に沿っていくだけでできます。
https://creator.magicleap.com/home

それが終わったら、環境別の Tutorial へ。


とくに躓くことはありません。

インストールするものなど、全体像

インストール手順はこちらから
  • Magic Leap Package Manager
  • Lumin SDK(Magic Leap Remote や Simulator を含む)
  • Unity または Unreal Engine 4

Magic Leap Package Manager

Magic Leap Remote

シミュレータ

Unity

Unreal Engine 4

以上。

2018年3月22日木曜日

Lumin SDK mabu コマンドで json.decoder.JSONDecodeError: Invalid \escape: line 12 column 37 (char 570) が発生する

Magic Leap が Lumin SDK を公開したとのことでさっそく遊んでいますが、躓いたことがあったので記録しておきます。
ちなみに、 Windows10 x64 環境でやっています。

json.decoder.JSONDecodeError: Invalid \escape: line 12 column 37 (char 570) が発生

コンパイルと実行を試しているところで、こんなエラーがでました。
json.decoder.JSONDecodeError: Invalid \escape: line 12 column 37 (char 570)

なんか json で怒られているのだけど、さっぱりわからず。
そもそも json なんて作ってないし、同ディレクトリに sample.json はあるけれどまず関係ないだろって内容でした。

vswhere.exe が日本語を返している

幸いにも stack trace が出ているので追ってみると、どうやら Visual Studio の環境設定を vswhere.exe から json で取得しており、その項目 description に日本語文字列が入っています。エラーメッセージ(line 12 column 37)から見ても、"個々" の "々" の位置らへんを指しているので、コイツが悪さしていると考えて間違いなさそうでした。

vswhere.exe 実行結果、description 部分

全体

良くわからない時は思い切る

なんか encoding が不正なんだな、と思い調べてみましたが、python ではエンコード問題が多発するようで、関連記事が見つかりまくりました(笑
ただ python を書いたことがないので結局正解がよくわからず、思い切って description の項目を削除するように変更してみました。

msvc.py (638行目の locate 関数)
    @staticmethod
    def locate():
        if HOSTOS == OS_WIN:
            vswhere_file_path = os.path.join(
                os.environ["ProgramFiles(x86)"],
                "Microsoft Visual Studio",
                "Installer",
                "vswhere.exe"
            )

            if os.access(vswhere_file_path, os.F_OK):
                cmd = [
                    vswhere_file_path,
                    "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64",
                    "-format", "json",
                ]

                out = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

                if out and out.returncode == 0:
                    json_string = out.stdout.decode("utf-8", "replace") if out.stdout else "[]"

                    # 日本語文字列が入ってくるので、思い切って description を削除
                    import re
                    json_string = re.sub(r'"description".+,', "", json_string)

                    json_data = json.loads(json_string)

こんな感じに。

そうすると、エラーが解消され実行することができました。

めでたし。




2018年3月19日月曜日

PHPUnit を Composer でインストールする。それだけ。

PHPUnit を初めてインストールしました。
あまりにも当たり前すぎて、ググった記事にはない内容もあるので記録しておきます。

前提

  • Windows 環境です(Unix/Mac 環境でもほぼ同じですが)

PHPUnit を Composer でインストール

インストール方法はいくつかありますが、composer を使います。

以下の composer.json を準備して、
{
    "require-dev": {
        "phpunit/phpunit": "7.0.*"
    }
}

インストール。
composer install

実行ファイルが以下の場所に出来ます(※これを探しました笑)
project_root/vendor/bin/phpunit.bat

project_root/vendor/bin/ に PATH を通して
(画像は RapidEE を使ってます)


Version 確認コマンドが働いたらインストール確認まで完了。
phpunit.bat --verion

Version 確認コマンドの実行結果。オッケー。
PS C:\Git\60_GitLab\sample_project> phpunit.bat --version
PHPUnit 5.0.10 by Sebastian Bergmann and contributors.

以上。

参考

https://phpunit.readthedocs.io/ja/latest/installation.html

2018年3月18日日曜日

Selenium + Chrome の環境が一瞬で構築できたというアレ。

前提

さて Selenium を試してみようか!
と思った時点で、こんな環境でした。
  • Windows10 64bit
  • Chrome はもちろんインストール済
  • php もインストール済
    • そしてパスが通っている
  • composer もインストール済
    • そしてパスが通っている

ブラウザのオートメーションと言えば昔は…

余談ですが、昔やったときは VB かなんかで IE を CreateObject して、なんか色々頑張ってやる感じで、まぁブラウザの操作自動化しても良いけどクソ面倒くさいよ。むしろ AutoHotKey とかでキー操作を自動化したほうが早いわ。ぐらいに思っていましたが…、時代は大分前進していたようで。

Selenium で Chrome を自在に動かす。しかも一瞬で。

さて、早速準備ですがやることはこれだけです。
  1. PHP 用ドライバを DL
  2. Windows 用 Chrome ドライバを DL

PHP 用ドライバを DL

composer.json にこう書いてインストールするだけです。
{
    "require": {
        "facebook/webdriver": "1.5.*"

    }
}
※最新版の Version は GitHub で確認してください

インストール。どん。
composer install
以上。

Windows 用 Chrome ドライバを DL

ここから「chromedriver_win32.zip」をダウンロードして解凍するだけです。
64bit 専用はないので、64bit でも 32bit 版で動かします。
linux と mac 版も置いてありありますね。
※最新版の Version はこちらで確認してください

Selenium の Hello world

ここまでできたら、あとはソースがあれば動きます。
試しに Google で Hello world を検索して見ます。

ソースはこんな感じ。

hello_world.php
<?php
require_once './vendor/autoload.php';

use Facebook\WebDriver\Chrome\ChromeDriver;
use Facebook\WebDriver\WebDriverExpectedCondition;
use Facebook\WebDriver\WebDriverBy;

function hello_world()
{
    // 環境変数にドライバパスを設定
    putenv('webdriver.chrome.driver=' . __DIR__ . '\chromedriver.exe');
    
    // Chrome を起動してページ遷移する
    $driver = ChromeDriver::start();
    $driver->get("https://www.google.co.jp/?q=helloworld");
    // 【検索】ボタンを押下
    $elem = $driver->findElement(WebDriverBy::name('btnK'));
    $elem->click();

    sleep(3);
    $driver->close();
}

hello_world();

※ facebook webdriver の API 一覧はこちら

最終的なフォルダ構成は、こうなっています。

あとはコレを実行すると、、
php hello_world.php

ブラウザが立ち上がり…

https://www.google.co.jp/?q=helloworld に遷移して【Google 検索】をクリックし…

検索結果のページが表示され…

3秒待機したら終了します。

はい、ここまで一瞬ですね。素晴らしい。
正直、こんなに簡単だとは思っていませんでした。

これで、ローカルでの自動化環境は整いました。
あとは API などを見ながら味付けしていく感じかと思います。
今回は、目的がローカル環境で達成できたので、 Selenium Server を使用していません。

次は、Selenium Server と組み合わせてみたいと思います。

以上。

補足

今回は facebook 製のを使いましたが、PHP の Web driver は公式では 3つ紹介されています。

参考