日頃の行い

個人的な日頃の行いをつらつら書いてます\\\\ ٩( 'ω' )و ////

webpackでERROR in Entry module not found: Error: Can't resolve 'babel' と言われて怒られた

久しぶりにwebpackを触ったらタイトル通り怒られてしまったので
その時調べたメモです。
webpackのversionは3.8.1でした。
エラー内容はこんな感じ

$make webpack/admin
path/to/npm run webpack -- --config ./webpack.config.js

> webpack-hello@1.0.0 webpack /Users/a-tanaka/booster
> webpack --watch "--config" "./webpack.config.js"


Webpack is watching the files…

Hash: 4f6ee5333597035827a3
Version: webpack 3.8.1
Time: 48ms

ERROR in Entry module not found: Error: Can't resolve 'babel' in '/Users/a-tanaka/booster'
BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders.
                 You need to specify 'babel-loader' instead of 'babel',
                 see https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed

その時のwebpack.config.jsはこんな形

module.exports = {
    entry: {
        main :__dirname + "/main.js",
    },
    output: {
        path: __dirname + '/dist/',
        filename: '[name].bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel'
            }
        ]
    },
    resolve: {
        extensions: ['*', '.js']
    }
};

結論から言うとmodule.loaders[0].loaderの babelbabel-loader に変える必要があるみたいですね

変更後

module.exports = {
    entry: {
        main :__dirname + "/main.js",
    },
    output: {
        path: __dirname + '/dist/',
        filename: '[name].bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader'
            }
        ]
    },
    resolve: {
        extensions: ['*', '.js']
    }
};

変更後に実行すると大丈夫そうでした。

$make webpack/correct
path/to/npm run webpack -- --config ./webpack.config.corrent.js

> webpack-hello@1.0.0 webpack /Users/a-tanaka/booster
> webpack "--config" "./webpack.config.corrent.js"

Hash: 8bee2d00eb6691bcae24
Version: webpack 3.8.1
Time: 433ms
         Asset     Size  Chunks             Chunk Names
main.bundle.js  2.51 kB       0  [emitted]  main
   [0] ./main.js 38 bytes {0} [built]

webpack1.xから2.xになる際にloaderのsufiixもつけないといけなくなったみたいですね。
そんな触ってなかったっけな・・・という思いが強いですw

https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed

検証用に使ったコードはgistに置いたので参考になれば幸いです。

https://gist.github.com/ara-ta3/dd980bb3e014659339bf3739ff939e05

参考

terraformを使ってさくらのクラウド上にサーバを立ち上げる

ISUCON7予選と同じ環境を立ち上げたいなーと思ってsakura cloudのterraformを触ってみたのでそのメモです。
第一歩目として単にサーバを立ち上げて見ました。
さくらのクラウドユーザコミュニティによる公認ツールがあるようなのでそれを使いました。

github.com

やることは

  1. API Tokenの取得
  2. terraformの設定を書く
  3. 実行する

という感じです。

1. API Tokenの取得

すごくまとまっていたので、ここを参考にすれば一発です。

インストールガイド - Terraform for さくらのクラウド

2. terraformの設定を書く

resource "sakuracloud_disk" "disk01"{
    name = "disk01"
    source_archive_id = "${data.sakuracloud_archive.ubuntu.id}"
    password = "password" # ssh用のパスワードなのでいい感じに変更する必要あり
}

# サーバー
resource "sakuracloud_server" "server01" {
    name = "server01"
    disks = ["${sakuracloud_disk.disk01.id}"]
    tags = ["@virtio-net-pci"]
}

data sakuracloud_archive "ubuntu" {
  os_type = "ubuntu"
}

ちょっとはまったところ

最低限の設定を書きたかったので下記記事を参考にしたのですが、

knowledge.sakura.ad.jp

resource "sakuracloud_disk" "disk01"{
    # ディスク名
    name = "disk01"
    # コピー元アーカイブ(CentOS 7.3 64bitを利用)
    source_archive_id = "112900062806"
    # パスワード
    password = "YOUR_PASSWORD_HERE"
}

の部分でsource_archive_idが今現在異なっているらしく * sakuracloud_disk.disk01: Failed to create SakuraCloud Disk resource: Error in response: &sacloud.ResultErrorValue{IsFatal:true, Serial:"...", Status:"400 Bad Request", ErrorCode:"param_res_not_found", ErrorMessage:"不適切な要求です。パラメータで指定されたリソースが存在しません。IDをご確認ください。"} と怒られてしまいました。

sakura cloudのpublic archiveと言うもののIDみたいですが、
それがちょくちょく更新されて変わっているみたいですね。

なので先程書いた例のように

data sakuracloud_archive "ubuntu" {
  os_type = "ubuntu"
}

と書いてあげて、 source_archive_id = "${data.sakuracloud_archive.ubuntu.id}" を利用すればいい感じに出来るようです。
os_typeに記載できるのはこのあたりにありました。

terraform-provider-sakuracloud/data_resource.md at cf50171462b9fc40ca4d68d99f84b72e009279a5 · sacloud/terraform-provider-sakuracloud · GitHub

3. 実行する

あとはterraformを実行するだけです。
さくっと行けそうだったのでdockerでやりました。
makefileに書いたのでこれを使うと make apply token=... secret=... みたいな感じで実行できます。

token=
secret=
SAKURA=init apply plan destroy

$(SAKURA):
  docker run -it --rm \
      -e SAKURACLOUD_ACCESS_TOKEN=$(token) \
      -e SAKURACLOUD_ACCESS_TOKEN_SECRET=$(secret) \
      -v $(PWD):/workdir \
      sacloud/terraform $@

https://hub.docker.com/r/sacloud/terraform/

ちょっとはまったところ

インストールガイドを見ながら実行したんですが、
微妙にコマンドが違っていて動かなかったですw
latestのimageで実行するとmountするディレクトリが現在異なっているようでした。

今のところ下記のように書いてありますが、 /work のところを /workdir に変える必要があります。
Dockerhubの方のREADMEでは /workdir になっていたのでわかって良かったです。

# ×
$ docker run -it --rm \
         -e SAKURACLOUD_ACCESS_TOKEN=[さくらのクラウド APIトークン] \
         -e SAKURACLOUD_ACCESS_TOKEN_SECRET=[さくらのクラウド APIシークレット] \
         -v $PWD:/work \
         sacloud/terraform apply
# ◯
$ docker run -it --rm \
         -e SAKURACLOUD_ACCESS_TOKEN=[さくらのクラウド APIトークン] \
         -e SAKURACLOUD_ACCESS_TOKEN_SECRET=[さくらのクラウド APIシークレット] \
         -v $PWD:/workdir \
         sacloud/terraform apply

追記

書いた直後に中の方が直してくださいました!
すごい!はやい!
今ドキュメントの方は動く形になっているかと思います

追記ここまで

下記がapplyしてdestroyまで実行したときの流れです。
はじめにinitする必要があるようでした。

### terraform plan

$make token=xxx secret=yyy plan
docker run -it --rm \
        -e SAKURACLOUD_ACCESS_TOKEN=xxx \
        -e SAKURACLOUD_ACCESS_TOKEN_SECRET=yyy \
        -v /Users/a-tanaka/sakura:/workdir \
        sacloud/terraform plan
Plugin reinitialization required. Please run "terraform init".
Reason: Could not satisfy plugin requirements.

Plugins are external binaries that Terraform uses to access and manipulate
resources. The configuration provided requires plugins which can't be located,
don't satisfy the version constraints, or are otherwise incompatible.

1 error(s) occurred:

* provider.sakuracloud: new or changed plugin executable

Terraform automatically discovers provider requirements from your
configuration, including providers used in child modules. To see the
requirements and constraints from each module, run "terraform providers".

error satisfying plugin requirements
make: *** [plan] Error 1

# terraform init

$make token=xxx secret=yyy init
docker run -it --rm \
        -e SAKURACLOUD_ACCESS_TOKEN=xxx \
        -e SAKURACLOUD_ACCESS_TOKEN_SECRET=yyy \
        -v /Users/a-tanaka/sakura:/workdir \
        sacloud/terraform init

Initializing provider plugins...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

# terraform plan

$make token=xxx secret=yyy plan
docker run -it --rm \
        -e SAKURACLOUD_ACCESS_TOKEN=xxx \
        -e SAKURACLOUD_ACCESS_TOKEN_SECRET=yyy \
        -v /Users/a-tanaka/sakura:/workdir \
        sacloud/terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

data.sakuracloud_archive.ubuntu: Refreshing state...

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + sakuracloud_disk.disk01
      id:                        <computed>
      connector:                 "virtio"
      graceful_shutdown_timeout: "60"
      name:                      "disk01"
      password:                  <sensitive>
      plan:                      "ssd"
      server_id:                 <computed>
      size:                      "20"
      source_archive_id:         "112901206585"
      zone:                      <computed>

  + sakuracloud_server.server01
      id:                        <computed>
      cdrom_id:                  <computed>
      core:                      "1"
      disks.#:                   <computed>
      dns_servers.#:             <computed>
      gateway:                   <computed>
      graceful_shutdown_timeout: "60"
      interface_driver:          "virtio"
      ipaddress:                 <computed>
      macaddresses.#:            <computed>
      memory:                    "1"
      name:                      "server01"
      nic:                       "shared"
      nw_address:                <computed>
      nw_mask_len:               <computed>
      packet_filter_ids.#:       <computed>
      tags.#:                    "1"
      tags.0:                    "@virtio-net-pci"
      zone:                      <computed>


Plan: 2 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

# terraform apply

$make token=xxx secret=yyy apply
docker run -it --rm \
        -e SAKURACLOUD_ACCESS_TOKEN=xxx \
        -e SAKURACLOUD_ACCESS_TOKEN_SECRET=yyy \
        -v /Users/a-tanaka/sakura:/workdir \
        sacloud/terraform apply

data.sakuracloud_archive.ubuntu: Refreshing state...
sakuracloud_disk.disk01: Creating...
  connector:                 "" => "virtio"
  graceful_shutdown_timeout: "" => "60"
  name:                      "" => "disk01"
  password:                  "<sensitive>" => "<sensitive>"
  plan:                      "" => "ssd"
  server_id:                 "" => "<computed>"
  size:                      "" => "20"
  source_archive_id:         "" => "112901206585"
  zone:                      "" => "<computed>"
sakuracloud_disk.disk01: Still creating... (10s elapsed)
sakuracloud_disk.disk01: Still creating... (20s elapsed)
sakuracloud_disk.disk01: Still creating... (30s elapsed)
sakuracloud_disk.disk01: Still creating... (40s elapsed)
sakuracloud_disk.disk01: Still creating... (50s elapsed)
sakuracloud_disk.disk01: Still creating... (1m0s elapsed)
sakuracloud_disk.disk01: Still creating... (1m10s elapsed)
sakuracloud_disk.disk01: Still creating... (1m20s elapsed)
sakuracloud_disk.disk01: Creation complete after 1m28s (ID: 112901361233)
sakuracloud_server.server01: Creating...
  cdrom_id:                  "" => "<computed>"
  core:                      "" => "1"
  disks.#:                   "" => "1"
  disks.0:                   "" => "112901361233"
  dns_servers.#:             "" => "<computed>"
  gateway:                   "" => "<computed>"
  graceful_shutdown_timeout: "" => "60"
  interface_driver:          "" => "virtio"
  ipaddress:                 "" => "<computed>"
  macaddresses.#:            "" => "<computed>"
  memory:                    "" => "1"
  name:                      "" => "server01"
  nic:                       "" => "shared"
  nw_address:                "" => "<computed>"
  nw_mask_len:               "" => "<computed>"
  packet_filter_ids.#:       "" => "<computed>"
  tags.#:                    "" => "1"
  tags.0:                    "" => "@virtio-net-pci"
  zone:                      "" => "<computed>"
sakuracloud_server.server01: Still creating... (10s elapsed)
sakuracloud_server.server01: Still creating... (20s elapsed)
sakuracloud_server.server01: Creation complete after 29s (ID: 112901361336)

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

# terraform destroy

$make token=xxx secret=yyy destroy
docker run -it --rm \
        -e SAKURACLOUD_ACCESS_TOKEN=xxx \
        -e SAKURACLOUD_ACCESS_TOKEN_SECRET=yyy \
        -v /Users/a-tanaka/sakura:/workdir \
        sacloud/terraform destroy

data.sakuracloud_archive.ubuntu: Refreshing state...
sakuracloud_disk.disk01: Refreshing state... (ID: 112901361233)
sakuracloud_server.server01: Refreshing state... (ID: 112901361336)

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  - sakuracloud_disk.disk01

  - sakuracloud_server.server01


Plan: 0 to add, 0 to change, 2 to destroy.

Do you really want to destroy?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

sakuracloud_server.server01: Destroying... (ID: 112901361336)
sakuracloud_server.server01: Still destroying... (ID: 112901361336, 10s elapsed)
sakuracloud_server.server01: Destruction complete after 15s
sakuracloud_disk.disk01: Destroying... (ID: 112901361233)
sakuracloud_disk.disk01: Destruction complete after 2s

Destroy complete! Resources: 2 destroyed.

destroy前コンソールを見たら作成されていました。
さくっと作れるので、これで設定書いてISUCON7予選の環境を再現していきたいです。
2ファイルしかないのでコピペで十分そうですが、
使ったMakefileなどはここに置きました。

github.com

ISUCON7で予選落ちしてきた

去年同様に id:hoto17296id:jp_taku2 と一緒にDarkというチームで出てきました。
結果は26772点!

f:id:arata3da4:20171023182952p:plain

去年は0点で、26722 / 0 = ∞(?)倍のスコアなのでこれこそ圧倒的成長ですね!

arata.hatenadiary.com

最終的なランキングも出てましたが、144(=12 ^2)位でした。
きりがいい。
全ランキングが出ると、来年はもっと上位目指すぞという気持ちになっていいですね。
優勝目指すぞ!ってなって、負けたとしても去年よりはあがった!とかわかるととても嬉しいです。

isucon.net

一週間夏休みを取っていたせいで、一番の懸念は当日の朝起きれるかでしたが起きれて良かったです。
(開始時刻遅くなっちゃったけど
開始時刻が遅れたので少しゆっくり目に行ったらインクの塗り合いが行われてたのがハイライトです。

やったこと

Appサーバ2台、DBサーバ1台の構成で、言語はPHPを選びました。

当日はprivateにしていましたが、ここのレポジトリを使ってコードを置いたりしていました。

github.com

あとは30分毎に今どんな状況だっけみたいな話をしたり誰がどこやってるかみたいなのを整理したりしました。

f:id:arata3da4:20171021211437j:plain

最後の1時間にsplatoonのラスト1分のBGMを流すとめちゃくちゃ焦ってよかったです(?)

www.youtube.com

f:id:arata3da4:20171024191434j:plain

便利だったこと

去年もやったんですが、Makefileによくやる作業をまとめるの便利です。

application server用のMakefile

nginx_log=/tmp/nginx-access.log

alp:
  sudo cat $(nginx_log)|alp --sum --aggregates "/icons/.+"

alp/less:
  sudo cat $(nginx_log)|alp --sum --aggregates "/icons/.+"|less -Ss

restart/php:
  sudo systemctl restart isubata.php.service

clean/nginx:
  sudo rm -f $(nginx_log)
  $(MAKE) restart/nginx

restart/nginx:
  sudo systemctl restart nginx.service

db server用のMakefile

slow_query=/var/log/mysql/mysql-slow.log

slow/ptquery:
  sudo pt-query-digest $(slow_query)

clean/slow:
  sudo rm -f $(slow_query)
  sudo systemctl restart mysql.service

mysql:
  mysql -uisucon -pisucon isubata

例えばnginxのログを一度削除して、nginxを再起動したいみたいなコマンドを作ったりしました。
ログを削除するときにログの場所どこだっけとか、
systemctlのコマンドこれであってるっけとか考えなくて良くて、
make clean/nginx でログを削除して、nginxをリスタートできます。
便利!
去年は色々書いてたけど、今年はあまり書かなかったので、みんなあんまり使ってなかったのが悲しかったです。
コマンドが1コマンドが多いから特にいらんかったみたいな話もありました。
来年はもうちょっと色々書いて便利にしていきたい。

ベンチマーカーも公開されたので、復習していこうと思います。
運営の方々当日大変だったと思いますがとても楽しめました!
ありがとうございました!

github.com

PHPのプロファイリングが出来るblackfireを試してみた

またもやISUCONで使おうと思ってblackfireをいうものを試してみました。
有料な機能も結構ありますが、
無料で使える機能でもどのメソッドがどれくらいの回数呼ばれてるのかとか、
どれくらいの割合を使っているのかとかがわかって便利でした。

blackfire.io

今回検証に利用したコードはここに置きました。

github.com

blackfireに既に登録済みで、server id, server tokenが手に入っていて、
docker-composeとGNU makeが入ってれば make compose id={server id} token={server token} で動かせるはずです。

やること

  • blackfireに登録してserver id, server tokenを取得
  • サーバにblackfire agentのインストール
  • blackfireのchrome extensionをインストール
  • プロファイリングする

という感じです。

1. blackfireに登録してserver id, server tokenを取得

しましょう!
Login - Blackfire

2. サーバにblackfire agentのインストール

この辺をやるだけです。

Installation - Blackfire

Dockerで作成した時のログはこんな感じでした。

# Configuring the Debian Repository

Step 4/10 : RUN wget -O - https://packagecloud.io/gpg.key | apt-key add -
 ---> Running in ee7d25eb98d1
converted 'https://packagecloud.io/gpg.key' (ANSI_X3.4-1968) -> 'https://packagecloud.io/gpg.key' (UTF-8)
--2017-10-15 16:41:40--  https://packagecloud.io/gpg.key
Resolving packagecloud.io (packagecloud.io)... 50.97.198.58, 2607:f0d0:2101:270::2
Connecting to packagecloud.io (packagecloud.io)|50.97.198.58|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3889 (3.8K) [application/octet-stream]
Saving to: 'STDOUT'

     0K ...                                                   100% 53.7M=0s

2017-10-15 16:41:40 (53.7 MB/s) - written to stdout [3889/3889]

OK
 ---> 032abc5bc6fb
Removing intermediate container ee7d25eb98d1
Step 5/10 : RUN echo "deb http://packages.blackfire.io/debian any main" | tee /etc/apt/sources.list.d/blackfire.list
 ---> Running in be9b5a302725
deb http://packages.blackfire.io/debian any main
 ---> 0437a3abc6ce
Removing intermediate container be9b5a302725
Step 6/10 : RUN apt-get update
 ---> Running in 44f15f9f8197
Hit http://security.debian.org jessie/updates InRelease
Ign http://deb.debian.org jessie InRelease
Get:1 http://security.debian.org jessie/updates/main amd64 Packages [547 kB]
Hit http://deb.debian.org jessie-updates InRelease
Get:2 http://packages.blackfire.io any InRelease [23.2 kB]
Hit http://deb.debian.org jessie Release.gpg
Get:3 http://deb.debian.org jessie-updates/main amd64 Packages [23.1 kB]
Hit http://deb.debian.org jessie Release
Get:4 http://deb.debian.org jessie/main amd64 Packages [9063 kB]
Get:5 http://packages.blackfire.io any/main amd64 Packages [1138 B]
Fetched 9658 kB in 4s (2006 kB/s)
Reading package lists...
 ---> 7bb05b5d43cc
Removing intermediate container 44f15f9f8197

# Configuring the Debian Repository -- ここまで
# Installing the Agent

Step 7/10 : RUN apt-get install -y blackfire-agent
 ---> Running in 792b428f7e45
Reading package lists...
Building dependency tree...
Reading state information...
The following NEW packages will be installed:
  blackfire-agent
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 6004 kB of archives.
After this operation, 16.4 MB of additional disk space will be used.
Get:1 http://packages.blackfire.io/debian/ any/main blackfire-agent amd64 1.14.1 [6004 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 6004 kB in 22s (263 kB/s)
Selecting previously unselected package blackfire-agent.
(Reading database ... 12926 files and directories currently installed.)
Preparing to unpack .../blackfire-agent_1.14.1_amd64.deb ...
Unpacking blackfire-agent (1.14.1) ...
Processing triggers for systemd (215-17+deb8u7) ...
Setting up blackfire-agent (1.14.1) ...
creating blackfire system user


    ADDITIONAL STEP REQUIRED!

    If this is a new install please run:

    sudo blackfire-agent --register
    sudo /etc/init.d/blackfire-agent start

 ---> 3129728f20d6
Removing intermediate container 792b428f7e45

# sudo blackfire-agent -register
# 上記コマンドを実行するとインタラクティブにserver id, server tokenを設定してくれます。
# しかし、最終的には /etc/blackfire/agent に書き込まれるのでここではserver id, tokenを設定したファイルを置いています。

Step 8/10 : COPY ./blackfire.ini /etc/blackfire/agent
 ---> fb9e504cb609
Step 9/10 : RUN /etc/init.d/blackfire-agent restart
 ---> Running in dea658865681
Restarting Blackfire Agent: blackfire-agent.
 ---> 58a923e72362
Removing intermediate container dea658865681

# Installing the Agent  -- ここまで
# Installing the Blackfire CLI tool は飛ばします
# Installing the PHP Probe

Step 10/10 : RUN apt-get install blackfire-php
 ---> Running in 1dc806414984
Reading package lists...
Building dependency tree...
Reading state information...
Suggested packages:
  php5-common php5-cli php7.1-cli php7.1-common
The following NEW packages will be installed:
  blackfire-php
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 2006 kB of archives.
After this operation, 5532 kB of additional disk space will be used.
Get:1 http://packages.blackfire.io/debian/ any/main blackfire-php amd64 1.18.0 [2006 kB]
debconf: delaying package configuration, since apt-utils is not installed
Fetched 2006 kB in 9s (214 kB/s)
Selecting previously unselected package blackfire-php.
(Reading database ... 12938 files and directories currently installed.)
Preparing to unpack .../blackfire-php_1.18.0_amd64.deb ...
Unpacking blackfire-php (1.18.0) ...
Setting up blackfire-php (1.18.0) ...
blackfire-php install completed.

# Installing the PHP Probe -- ここまで
# これをやれば php.ini 周りの設定にblackfireの設定が追加されます。
# なので php -i | grep blackfireをやった時にblackfireが設定されていることがわかるはずです。
# されていない場合は別のバージョンのphpにインストールされている可能性があるので
# extension=blackfire.so とか設定に追加すればもしかしたら動くかも・・・w

$ php -i |grep blackfire
Additional .ini files parsed => /usr/local/etc/php/conf.d/zz-blackfire.ini
    with blackfire v1.18.0~linux-x64-non_zts71, https://blackfire.io, by SensioLabs
blackfire
blackfire.agent_socket => unix:///var/run/blackfire/agent.sock => unix:///var/run/blackfire/agent.sock
blackfire.agent_timeout => 0.25 => 0.25
blackfire.env_id => no value => no value
blackfire.env_token => no value => no value
blackfire.log_file => no value => no value
blackfire.log_level => 1 => 1
blackfire.server_id => no value => no value
blackfire.server_token => no value => no value

3. blackfireのchrome extensionをインストール

blackfire cliを使えばなんか出来るっぽいですが、
とりあえずchrome拡張を入れて動かした感じです。

Google Chrome - Blackfire

4. プロファイリングする

プロファイリングしたいページに行って、
chrome拡張を利用するとこんな感じになります。

f:id:arata3da4:20171016021409p:plain

f:id:arata3da4:20171016021418p:plain

f:id:arata3da4:20171016021427p:plain

そして View Call Graph を押すと下記のようなページが出るはずです。
なんか便利そう!

f:id:arata3da4:20171016021538p:plain

感想

  • なんか便利そうなので仕事でも使っていこうかなと思いました(小並感

phpredisをPHP7系で触るためにやったこと

ISUCONでredis使おうと思った時にPHPからredis触ったこと無いなということに気がついたので、
触れる用にphpredisを試してみた備忘録です。
利用したPHPのversionは 7.1.10 です。

php -v
PHP 7.1.10 (cli) (built: Oct 10 2017 01:16:36) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies

phpredisはCで書かれたPHP Extensionなのでbuildしてphp.iniに設定を追加する必要があります。

github.com

やることは、phpredisのレポジトリをcloneしてビルドし、php.iniに設定を追加するだけです。

https://github.com/phpredis/phpredis#installation

検証に利用したコードはここに置きました。

github.com

検証に利用したコードではDockerfile内で行いました。 設定が反映されているかは php -i で確認できます。

# 反映されている場合
$php -i |grep -e redis -e Redis 
Additional .ini files parsed => /usr/local/etc/php/conf.d/redis.ini
redis
Redis Support => enabled
Redis Version => develop
Registered save handlers => files user redis rediscluster
This program is free software; you can redistribute it and/or modify

# 反映されていない場合
$php -i |grep -e redis -e Redis
This program is free software; you can redistribute it and/or modify

雑に値をsetするphpコードを書いてみました。

<?php

function connect($server, $port = 6379, $db = 0): \Redis {
    $redis = new \Redis();
    $success = $redis->connect($server, $port);
    if ($success !== true) {
        throw new \Exception(spritnf('failed to connect to %s. port: %s', $server, $port));
    }
    $success = $redis->select($db);
    if ($success !== true) {
        throw new \Exception(spritnf('failed to select database %s. server: %s. port: %s', $db, $server, $port));
    }

    return $redis;
}


function main() {
    // docker-composeのlinksで追加しているのでredisとなっています。
    // アドレス入れる場合は下記のような形になります。
    // $redis = connect('127.0.0.1');
    $redis = connect('redis');
    $redis->set('xxx', 'aaa');
    $redis->set('yyy', 'bbb');
    $saved = $redis->get('yyy');
    var_dump($saved);
}

main();

実行すると var_dump の結果が出るだけですね。

$php main.php
string(3) "bbb"

redis-cliで確認すると xxx, yyy というkeyに書き込まれているのがわかります。

$redis-cli
127.0.0.1:6379> keys *
1) "yyy"
2) "xxx"

もっと色々やりたい場合はUsageが充実していたのでそっちが参考になりそうです。

https://github.com/phpredis/phpredis#usage

そんなに難しくないので使う際には使っていこうと思いました。

terraform v0.8.8からv0.10.3に移行した時remote state周りでやったことメモ

気がついたらterraformのバージョンが上がってました。
使ってた時は0.8.xだった気がしたけど、
この前見たら0.10.xになってて、なるほど〜となりました。

細かいCHANGE LOGは terraform/CHANGELOG.md at master · hashicorp/terraform · GitHub をみるとして、
0.9.x から terraform remote hogehoge がなくなっていたので
0.10.x のversionでresourceのremote管理する方法を確認してみました。

確認は v0.10.3terraform plan したら出てきたURLを参考にしました。

$terraform --version
Terraform v0.10.3

$terraform plan
Deprecation warning: This environment is configured to use legacy remote state.
Remote state changed significantly in Terraform 0.9. Please update your remote
state configuration to use the new 'backend' settings. For now, Terraform
will continue to use your existing settings. Legacy remote state support
will be removed in Terraform 0.11.

You can find a guide for upgrading here:

https://www.terraform.io/docs/backends/legacy-0-8.html

www.terraform.io

↑のページの流れに沿って、移行の手順を書いてみました。

1. terraform v0.8.x で remote state を持ってくる

With the older Terraform version (version 0.8.x), run terraform remote pull. This will cache the latest legacy remote state data locally. We’ll use this for a backup in case things go wrong.

古いversionのterraformでローカルに最新の状態を持ってきて、
古いバージョンはここからダウンロードできました。

Terraform Versions | HashiCorp Releases

2. .terraform/terraform.tfstate のバックアップ

Backup your .terraform/terraform.tfstate file. This contains the cache we just pulled. Please copy this file to a location outside of your Terraform module.

何かあった時用にバックアップをとっておきましょう。
私はとりあえず /tmp に置きました。

3. backendの設定

Configure your backend in your Terraform configuration. The backend type is the same backend type as you used with your legacy remote state. The configuration should be setup to match the same configuration you used with remote state.

www.terraform.io

backendの設定を↑ページを参考に追加しましょう。
backendの設定がファイルになったんですね。
設定ファイルはこんな感じになりました。

backend.tf

terraform {
    backend "s3" {
        bucket = "terraform-sample-tfstate"
        key = "sample.tfstate"
        region = "ap-northeast-1"
    }
}

もしくはこのように最低限の設定ファイルを書いて、
initコマンド時にoptionで指定することもできます。

terraform {
    backend "s3" {}
}
$terraform init \
    -backend-config="bucket=terraform-sample-tfstate" \
    -backend-config="key=sample.tfstate" \
    -backend-config="region=ap-northeast-1" 
# backend configオプションにはファイルを指定するのかと思ったら違いました(ヘルプ読まないせい

(backend configの使い方はここで気が付きました。
Terraform backend init: settings in -backend-config file are ignored · Issue #13552 · hashicorp/terraform · GitHub

4. initコマンドの実行

Run the init command. This is an interactive process that will guide you through migrating your existing remote state to the new backend system. During this step, Terraform may ask if you want to copy your old remote state into the newly configured backend. If you configured the identical backend location, you may say no since it should already be there.

あとはinitコマンドを打つだけです。

$terraform init \
        -backend=true \
        -force-copy \
        -get=true \
        -input=false

Initializing the backend...
New backend configuration detected with legacy remote state!

Terraform has detected that you're attempting to configure a new backend.
At the same time, legacy remote state configuration was found. Terraform will
first configure the new backend, and then ask if you'd like to migrate
your remote state to the new backend.



Successfully configured the backend "s3"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Checking for available provider plugins on https://releases.hashicorp.com...
- Downloading plugin for provider "aws" (0.1.4)...

The following providers do not have any version constraints in configuration,
so the latest version was installed.

To prevent automatic upgrades to new major versions that may contain breaking
changes, it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration, with the constraint strings
suggested below.

* provider.aws: version = "~> 0.1"

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

# terraform {
#    backend "s3" {}
# }
# backend.tfが↑のときは↓のようなコマンドになります

$terraform init \
        -backend-config="bucket=terraform-sample-tfstate" \
        -backend-config="key=sample.tfstate" \
        -backend-config="region=ap-northeast-1" \
        -backend=true \
        -force-copy \
        -get=true \
        -input=false

5. terraform planを実行してstateが正しいか確認

Verify your state looks good by running terraform plan and seeing if it detects your infrastructure. Advanced users may run terraform state pull which will output the raw contents of your state file to your console. You can compare this with the file you saved. There may be slight differences in the serial number and version data, but the raw data should be almost identical.

terraform planを実行してみて、問題なさそうか確認します。

$terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

aws_s3_bucket.terraform-sample-tfstate: Refreshing state... (ID: terraform-sample-tfstate)
No changes. Infrastructure is up-to-date.

This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, Terraform
doesn't need to do anything.

up-to-dateみたいなので問題なさそうです。
init時にbackendの設定がうまくいっていない場合、
はじめにplanしたときみたいに Deprecation warning みたいなのが出ます。
その時はbackendの設定がうまく言ってないはずなので、
initを頑張るといい感じになるかなと思います・・・

最終的にできたレポジトリはこんな感じでした。
S3は確か名前の重複ができない気がしたのでそのままでは試せないかもしれないですが、
参考になれば幸いです。
terraformガンガン進んでいって追いつくの大変だけど、とても便利なので使っていきたいと思います。

github.com

Golangのsqlxでテーブルをjoinした結果をstructにbindする

ちょい前に簡単なSQLをstructにbindしたり、
IN句を使ったりしたやつは書いたんですが、
joinした時とか、structがstructを持ってる場合、
dbタグをどうやってbindするんだろうと思ったら、
友人が記事見つけてくれたので試してみました。

arata.hatenadiary.com

arata.hatenadiary.com

最終的にはSQLエイリアス (AS …) のほうで . でつなげれば良いみたいでした。
SQLをこんな感じにhoge.fooエイリアスとして利用して、

SELECT h.id AS "hoge.id", h.foo AS "hoge.foo", f.id AS id, f.bar AS bar 
FROM fuga AS f 
JOIN hoge AS h ON f.hoge_id = h.id

Fuga structにbindしようとすると Fuga.Hoge.Foo にその値がbindされるようでした。

type Hoge struct {
    ID  int    `db:"id"`
    Foo string `db:"foo"`
}

type Fuga struct {
    ID   int    `db:"id"`
    Hoge Hoge   `db:"hoge"`
    Bar  string `db:"bar"`
}

検証に使ったコードはこんな感じでした。

gist.github.com

join周りもいい感じにbindしてくれて便利。

参考