BigQueryとAirtableをGASとZapierで自動連携してNPSアンケートチェックを効率化した話

こんにちは、エニグモカスタマーマーケティング事業本部で出品審査などを担当している杉山です。この記事はEnigmo Advent Calendar 2021の10日目の記事です。

昨年のアドベントカレンダーでは、日頃の担当業務についてWantedlyで書きましたが、今回は開発者ブログにお邪魔しました。

エンジニアではなくビジネスサイドの人間ですが、通常業務の傍らITツールを駆使して、ユーザー対応の現場の自動化や効率化などに取り組んでいます。

どうしても手元で作業が必要で、エンジニアに開発してもらうほどではないんだけど、これが自動になったら楽なのに!とかもっと効率よく日々の業務をこなして価値の高い仕事に取り組みたいよー!と思う瞬間がありませんか?私はあります。もう毎日のようにあります。

もちろん大規模な運用改善やシステムの導入などはエンジニアと一緒に開発したほうが圧倒的にいいという案件も多々あるので見極めが必要ですが、ひとまず現場の人間が(ほぼ)ノーコードでいろいろできると、エンジニアのリソースが空くまでのその場を凌いだり、新しいことについて考えて取り組む余裕を作り出すことができます。今回はそんなお話の一つです。

餅は餅屋ですから専門家から見れば拙いやり方をしている面もあるかとは思いますが、そこは何卒多めに見ていただければ幸い。

NPSアンケートのチェック運用をツールの自動連携で効率化する

本日のテーマは、BigQueryのデータをデイリーでAirtableに自動連携して、BUYMAのNPSアンケートチェック業務の効率化をした話を書きたいと思います。

NPS(ネットプロモータースコア)とは、EC事業者にとっては定番ですが、取引が完了したお客様に任意で答えていただいている、BUYMAの顧客のロイヤリティを計測するためのアンケート調査です。

NPSの回答には、BUYMAや出品者様のお取引についての貴重なご意見が詰まっています。エニグモではNPS専用のプロジェクトチームを部門横断で結成し、回答を全てチェック、アクティブサポートや今後の開発・施策の検討に活用させていただいています。

これまでのNPSチェック運用と課題

NPSプロジェクトでは、毎日いただく数百のアンケートすべてに目を通し、気になるものをピックアップして定期MTGで今後の対応を議論しています。チェック作業は曜日ごとにプロジェクトメンバーで分担して行っているのですが、それがなかなか手間のかかる作業となっており、また、チェック対応結果の活用という点でも課題が多くありました。

いままでのやり方

Gmailにデイリーで送られる回答データを確認し、Gmail上に対応ログを残す

f:id:enigmo7:20211207173705p:plain
Gmailで送られるNPSアンケートのサマリ例

課題
  • チェックに時間がかかりすぎる
    • データに直接チェック結果を書き込むことができないので、気になったポイントなどをメモする場合コピペしてドキュメントを整形する作業を毎回する必要がある
  • ピックアップのMTGで決まった対応について、進捗管理がしづらい
    • 議論のログがメールにしかないため、対応担当者が手元で別途タスクリストを作ったり情報をメモしておかないといけない
  • アンケートに答えていただいた方へご連絡する際に、メールリストの作成をするだけで一苦労
    • 手動で再度データを抽出し対応の一覧をExcelで作成、そこからメール送信対象者をチェックしてSQLでメールアドレスリストを抽出……と複雑な手順が必要だった
  • どのアンケートについてどういった議論が起こり、どんな対応を行ったのか、あとから振り返る手段が限られている
    • Gmailの履歴から検索してひとつひとつ中身を見るしかないため、一覧性が低い
    • どんなご意見がどのくらいの件数来ているのかなどを定量的に把握することができない

……といった具合に、NPSアンケートを導入した初期から続く古の運用のため、やりづらいポイントが多数ある状態でした。

チェック運用のツールをGmail→Airtableに移行し効率化

そこで、以下の2点について解決すべく、運用改善を行いました。

  1. アンケートのチェック作業の手間を減らす
  2. 今後の対応のために過去のデータを参照しやすくする

購入者様がアンケートに回答→メンバーが内容チェック→対応内容を決定しタスクリストを作成→進捗管理→回答者様へのご連絡→過去のピックアップ内容の振り返り、という一連の業務の流れを整理し直して、最小限の手数で作業が完了できるようにします。そのために、チェック作業のツールをGmailからデータベースサービスAirtableに移行することにしました。

Airtableは、一言で言うときれいで賢いスプレッドシートです。表形式のデータを直感的に、かつ自由度高く扱うことができるため、多数のデータをチェックして分類したり、追加の情報を手動でメモして管理したり、ということがGoogle Spreadsheet やExcel以上に簡単に見栄え良くできます。

今回はBigQueryから抽出したNPSアンケートのデータを自動でAirtableに同期し、そこでピックアップ運用を全て完結させるようにしました。やることは単にデータの自動同期なのですが、使用ツールが変わるとチェック作業は劇的にやりやすくなります。

※ 今回の記事ではAirtableの細かい使い方については割愛しますが、使いこなせれば本当に便利すぎるサービスなので、おすすめです!

▼参考記事

Excelスプレッドシート!WebプロジェクトのためのAirtable活用術

loftwork.com

使用ツールと自動化の流れ

今回の自動化の流れと使用したツールは以下になります。 f:id:enigmo7:20211207175057j:plain

Google BigQuery

NPSアンケートの回答データが溜まっているDB

Google App Script(GAS)

BigQueryから毎日自動でデータ抽出しスプレッドシートに転記するプログラムを作成

Google Spreadsheet

GASで抽出したデータを一時的に溜め、Zapierのトリガーにするために使用

Zapier

複数のWebサービスを組み合わせて独自の自動ワークフローを作成できるタスク自動化ツール。Spreadsheetに同期したデータをトリガーにして、Airtableに自動転記する設定を作成

zapier.com

Aitable

自動同期したデータの目視チェック、対応ログの記録などを行う

airtable.com

GASでBigQueryからデータ抽出してシートに記入

GASを使ってBigQuery上でSQLを動かし、スプレッドシートにデータを転記するまでのコードは以下のような感じです。これは社内の他のGASやググった内容を参考にあれやこれやしてなんとか作りました。GAS、もう数年間書いては忘れを繰り返しているのですが、今回の対応でやっと結構定着した気がします……。

GASは深夜の3時に毎日起動し前日分を取得するようトリガー設定をしています。

//BigQuery
var projectNumber = 'データ抽出元の任意のプロジェクトNo'; 
 
//スプレッドシート
var ss = SpreadsheetApp.getActiveSpreadsheet();
 
//SQLの結果を出力するシート
var sheetNPS = ss.getSheetByName('任意のシート名');
 
function check() {
  //処理開始メッセージ
 Browser.msgBox("処理をしています。しばらくお待ちください。")
 
 //SQL結果書き出しシートのクリア
 sheetNPS.getRange(2, 1,sheetNPS.getLastRow(),sheetNPS.getLastColumn()).clearContent();
 
 // SQLを生成 
 
var sql =  "任意のクエリ";
 
Logger.log(sql);
 
 // SQLを実行する準備
 var query_results;
 var resource = {
   query : sql,
   timeoutMs: 1000000,
   // Standard SQLを使用する場合はLegacySqlの使用をfalseにする
   useLegacySql: false
 };
  try {
 // SQLを実行
   query_results = BigQuery.Jobs.query(resource,projectNumber);
 }
 
 // エラーが発生したらログ出力、メッセージ出力して終了
 catch (err) {
   Logger.log(err);
   Browser.msgBox(err);
   return;
 }
 
 while (query_results.getJobComplete() == false) {
   try {
     query_results = BigQuery.Jobs.getQueryResults(projectNumber,query_Results.getJobReference().getJobId());
     if (query_results.getJobComplete() == false) {
       Utilities.sleep(3000); //以下の謎のエラーがでたら、この値を増やすか、timeoutMsの値を増やす。「ReferenceError: 「query_Results」が定義されていません。」
     }
   }
   catch (err) {
     Logger.log(err);
     Browser.msgBox(err);
     return;
   }
 }
 
 Logger.log(query_results);
  var resultCount = query_results.getTotalRows();
 var resultValues = new Array(resultCount);
 var tableRows = query_results.getRows();
 
 // 抽出結果を配列(resultValues)に格納
 for (var i = 0; i < tableRows.length; i++) {
   var cols = tableRows[i].getF();
   resultValues[i] = new Array(cols.length);
   for (var j = 0; j < cols.length; j++) {
     resultValues[i][j] = cols[j].getV();
   }
 }
 
 // 配列(resultValues)の内容をシートに出力
 sheetNPS.getRange(2,1,resultCount,tableRows[0].getF().length).setValues(resultValues);
 
Browser.msgBox("完了したよ!") //完了メッセージ
Zapierの設定

次に、スプレッドシートのデータ更新をトリガとしてAirtableにデータを転記するZapierを設定します。 当初はGASでそのままAirtableに転記することを想定して作り始めたのですが、AirtableのAPI Documentをよくよく見ると、一度にAPIで追加できるレコードは10まで、という制限があり、数百行を一気に追加したかったため間にZapを挟むことにしました。

f:id:enigmo7:20211207175259p:plain
トリガにスプレッドシートのレコードの追加もしくはアップデートを指定

f:id:enigmo7:20211207175329p:plain
先ほど作ったGASのシートを指定

f:id:enigmo7:20211207175342p:plain
1行1トリガとして先ほど抽出したデータがテストに出てきます

これでトリガー設定は完了です。

次に、Airtableに転記をするための設定をします。

f:id:enigmo7:20211207175410p:plain
APPにAirtableを選択しアカウントを連携

f:id:enigmo7:20211207175443p:plain
Create Recordを選択

f:id:enigmo7:20211207175529p:plain
あらかじめ作成したAirtable上のカラムとスプレッドシートのデータの対応を設定

f:id:enigmo7:20211207175541p:plain
テストで入力内容を確認し、問題がなければZapをONにする

f:id:enigmo7:20211207175421p:plain
データを同期したAirtableシート

これで、毎日前日分のデータをAirtableに自動同期することができます!!

Zapierのトリガ数の上限を解除する

と、うまくいったかと思いきや、運用開始してみたら問題が発生。

Zapierは動作したトリガ数に応じて課金されていく仕組みなので、誤作動防止のために一度に動くトリガが100件を超えると自動でストップする仕様になっていました。今回作ったZapは毎日数百件ある更新データをひとつひとつトリガとしてZapを動かす設定のため、動かすたびに毎回Zapが止まってしまいました。一時停止したZapはボタンひとつで再開作業をすれば問題なく動くのですが、毎朝対応が必要になるのでこれでは自動化の良さが半減してしまいます。

最初は解決方法がわからず、毎日再開をするひと手間をしばらく続けていたのですが、やっぱりめんどくさい!!

Zapierに問い合わせてみると、トリガ上限を上げてもらえることが判明。リミットを500に設定してもらい、無事に完全自動化することに成功しました。

よく調べるとトラブルシューティングにも該当の内容がありました。サポートはすべて英語なので該当箇所を見つけるのも一苦労ですね……。

zapier.com

新・チェック運用

毎日のデータをAirtableに連携することで、フィルター機能で自由に表示を操作することができるようになったので、アンケートのチェック運用もAirtable上でスムーズに行えるようになりました。 まずは、曜日ごとに分担してチェックをしているため、回答を担当曜日ごとに表示できるようそれぞれのViewを作成。

f:id:enigmo7:20211207175956p:plain
曜日ごとの表示例

担当曜日の回答に目を通して気になるものにはチェックマークをつけていき、コメント欄にメモを記入するだけでピックアップは終了です。

MTGではチェックがついたものについて確認して議論し、決まった対応内容を購入者様・出品者様それぞれの該当欄に記入して対応の進捗や担当者もここで管理します。

f:id:enigmo7:20211207175839p:plain
対応タスクの一覧View

更に、回答いただいたお客様へのご連絡のためのリストもAirtable上のViewで管理できるため、改めてデータ出しをする作業もなくなりました。

f:id:enigmo7:20211207180035p:plain
メール配信のためのリスト

運用変更の結果、実現したこと

今回のツールの変更と自動化で、課題だった以下の点について解決し、かなりの効率化を実現することができました。

  • MTG前のピックアップのための所要時間が削減でき、1日分のチェックに以前は1時間前後かかっていたものを30分程度でできるようになった
  • MTG中にチェックしたものがそのまま対応のタスクリストになるため、進捗が管理しやすくなり対応時間の削減と対応漏れの防止ができた
  • 過去に出てきた類似案件の対応見直しや、特定の出品者様・購入者様に過去どういったご意見が多いかをMTG中にさっと参照することができるようになったため、以前よりも的確なフォローが可能になった
  • 回答者様への一斉連絡のためのメールリスト抽出が自動で完了できるようになり、手動でリストを作成する手間がなくなった

今後の展望

今回の一番の目的だった業務の効率化は十分に達成することができた一方で、データ活用という観点ではまだまだやれることがあると考えています。

現在は個別のアンケートへの対応のみに活用されていますが、ピックアップしたデータを再度データベース内の他の情報と組み合わせてより高度な分析の材料としたり、特定の回答内容の方にのみMDツールと連携して自動でご案内をしたり、などデータが整ったことで活用の幅を広げることができるはず。貴重なお客様の声をサービス改善に繋げるべく、今後も試行錯誤を続けていきたいと思います。

明日の記事の担当は人事総務グループの右川さんです。お楽しみに!


株式会社エニグモ すべての求人一覧

hrmos.co

AWS移行のため、大規模で複雑な負荷テストをやった話

はじめに

こんにちは、インフラエンジニアの 高山 です。

この記事は Enigmo Advent Calendar 2021 の 9 日目の記事です。

現在、BUYMAをオンプレからAWSへ移行するプロジェクトを進めています。 テスト環境の移行は完了し、本番環境の移行をしようというところです。

本番環境の移行をする前に 性能的に問題ないことを確認するため、本番環境と同程度のスペックで検証環境を構築し負荷テストを実施しました。 まだ終わっていませんが、今の時点で得た知見を記事にしようと思います。

負荷テストツール選定

詳細は割愛しますが、 以下のような要件からAWSの分散負荷テストのソリューション(正式名称はDistributed Load Testing on AWS 以下、AWS負荷テストソリューションと呼ぶ)を使うこととしました。

  • 大規模な負荷テストができること
  • 複雑なテストシナリオが作成できること
  • 情報が多いこと
  • 学習コストや構築運用コストが低いこと
  • 費用が安価であること
  • テストシナリオをコードで管理できること

AWS負荷テストソリューションは それ自体の情報は多くないものの JMeterの設定ファイルを読み込むことができるためテストシナリオ作成の情報は多く、テストシナリオをコードで管理できること以外は要件を満たしています。 (ruby-jmeterを使えばコード管理できそうですが、手は出しませんでした。)

AWS負荷テストソリューションの概要

AWS負荷テストソリューションは AWSのマネージドサービスを組み合わせたAWSのソリューションの1つで、AWSが提供しているCloudFormationのテンプレートからスタックを作成すれば、簡単に作成することができます。

導入の説明などは割愛します。 以下を参考にしてください。

テストシナリオ作成

性能的に問題ないことを確認するためには 本番環境と同等の負荷をかける必要があります。 本番環境でのアクセスが多い機能と ログイン/未ログインの割合を調べ、それをテストシナリオにしました。

本番環境の確認

  • ログイン割合

    • 未ログイン状態: 8
    • ログイン状態: 2
      • ログインページへのアクセスは300アクセスに1回程度
  • アクセスの多い機能の割合

    • Web検索: 70
    • Web商品詳細: 90
    • API検索: 35
    • API商品詳細: 35

作成したテストシナリオ

本番環境の確認結果より、1/5の確率でログインするようにしつつ アクセスが多い機能を任意の割合でアクセスするようなテストシナリオを作成しました。

f:id:enigmo7:20211206134416p:plain
作成したテストシナリオ

JMeterの詳細な設定方法などは割愛しますが、ポイントは以下になります。

  • 割合を近似してできるだけ小さい数にした
  • インタリーブコントローラでログインの割合をコントロールするようにした
  • 会員IDリストのcsvファイルを用意してランダムにユーザを変えてログインするようにした
    • (事前に同じパスワードでログインできるように仕込んでおきました)
  • アクセスの割合で特に多い機能のHTTPリクエスサンプラーを割合の数だけ作成
    • さらにそれを5回ループし、ログインを300アクセスに1回程度になるようにした
  • 同じ機能でも、HTTPリクエスサンプラーごとに URLリストファイルを分割して別々のcsvファイルを参照するようにした
    • (同じcsvファイルを使うと、同一スレッドの同じ回で同じURLになってしまったため)

AWS負荷テストソリューションにJMeterの設定ファイルを読み込ませる

f:id:enigmo7:20211206134742p:plain
ファイルアップロード

作成したテストシナリオで外部ファイル(csvファイルやプラグインファイル)を読んでいる場合は、zipにまとめてからアップロードします。

  • ポイント
    • 外部ファイルは相対パスで指定すること
    • テストシナリオの拡張子はjmxとして、複数のjmxファイルは含めないこと
    • ファイルサイズ上限は50MB

AWS負荷テストソリューションのイメージとスクリプト

使用されているコンテナのイメージと実行されるスクリプトを確認してみましょう。

Dockerfileを見ると、コンテナイメージはtaurusを元にしています。 ENTRYPOINTに指定されているスクリプトの中でアップロードしたファイルを読み込んでいる箇所を見てみます。

# download JMeter jmx file
if [ "$TEST_TYPE" != "simple" ]; then
  # Copy *.jar to JMeter library path. See the Taurus JMeter path: https://gettaurus.org/docs/JMeter/
  JMETER_LIB_PATH=`find ~/.bzt/jmeter-taurus -type d -name "lib"`
  echo "cp $PWD/*.jar $JMETER_LIB_PATH"
  cp $PWD/*.jar $JMETER_LIB_PATH

  if [ "$FILE_TYPE" != "zip" ]; then
    aws s3 cp s3://$S3_BUCKET/public/test-scenarios/$TEST_TYPE/$TEST_ID.jmx ./
  else
    aws s3 cp s3://$S3_BUCKET/public/test-scenarios/$TEST_TYPE/$TEST_ID.zip ./
    unzip $TEST_ID.zip
    # only looks for the first jmx file.
    JMETER_SCRIPT=`find . -name "*.jmx" | head -n 1`
    if [ -z "$JMETER_SCRIPT" ]; then
      echo "There is no JMeter script in the zip file."
      exit 1
    fi

    sed -i -e "s|$TEST_ID.jmx|$JMETER_SCRIPT|g" test.json
  fi
fi

スクリプトから以下のことが わかりました。

  • jmxファイルをfindで探しているようなので、zip内のjmxファイルのパスは気にしなくても良さそうですが、含めるjmxファイルは1つだけにする必要がある
  • プラグイン用のjarファイルをJMETER_LIB_PATH配下へコピーしていますが、zipを解凍する前に コピーしているので プラグインは追加できない模様
    • (今回のテストシナリオで使用した追加プラグインRandom CSV Data Set Configのみなのですが、zipに含めなくても使えました 謎です)
$ docker run -it --rm --entrypoint "bash" public.ecr.aws/aws-solutions/distributed-load-testing-on-aws-load-tester:v2.0.0
root@1328dc7cdfdd:/bzt-configs# ls -l
total 1296
-rwxr-xr-x 1 root root   1210 Sep 30 04:16 ecscontroller.py
-rwxr-xr-x 1 root root   1360 Sep 30 04:16 ecslistener.py
-rw-r--r-- 1 root root  16542 Sep 30 04:19 jetty-alpn-client-9.4.34.v20201102.jar
-rw-r--r-- 1 root root  19600 Sep 30 04:19 jetty-alpn-openjdk8-client-9.4.34.v20201102.jar
-rw-r--r-- 1 root root 320564 Sep 30 04:19 jetty-client-9.4.34.v20201102.jar
-rw-r--r-- 1 root root 214251 Sep 30 04:19 jetty-http-9.4.34.v20201102.jar
-rw-r--r-- 1 root root 164646 Sep 30 04:19 jetty-io-9.4.34.v20201102.jar
-rw-r--r-- 1 root root 565135 Sep 30 04:19 jetty-util-9.4.34.v20201102.jar
-rwxr-xr-x 1 root root   2998 Sep 30 04:16 load-test.sh
root@1328dc7cdfdd:/bzt-configs# find ~/.bzt/jmeter-taurus -type d -name "lib"
/root/.bzt/jmeter-taurus/5.2.1/lib
root@1328dc7cdfdd:/bzt-configs# find /root/.bzt/jmeter-taurus/5.2.1/lib -type f -name "*jar" -ls | wc -l
109
root@1328dc7cdfdd:/bzt-configs# find /root/.bzt/jmeter-taurus/5.2.1/lib -type f -name "*jar" -ls | egrep -i "csv"
root@1328dc7cdfdd:/bzt-configs#

分析のための準備

f:id:enigmo7:20211206160828p:plain
Datadog ダッシュボード

AWS負荷テストソリューションのテスト結果レポートを見ても詳細な分析はできないので、詳細な分析をするためには監視ツールで必要なデータを取る必要があります。 今回はDatadogを使い、以下のようなデータを確認できるようにダッシュボードを作成しました。(APMも使っています)

  • 各機能(DBやアプリサーバ、検索サーバ、キャッシュサーバ等)の負荷
  • アプリやLBのbusy/idle worker
  • キャッシュサイズ、キャッシュヒット率、eviction
  • etc

目標値

f:id:enigmo7:20211206153419p:plain
本番環境のある日のスループット/分

負荷テストした結果を分析できても、どの程度の値であればOKと判断できなければ意味がありません。 本番環境のスループットやページごとのレイテンシを調べておき、目標となる値を調査しました。

移行により性能を向上させるというよりは 現状より性能が低下せず移行できることを目標にしているため、 今回は現在の本番環境のスループットやページごとのレイテンシが そのまま目標値となります。

本番環境の全LBサーバのログを合計したところ、ピークタイムのスループットは5万アクセス程度/分でした。 (CDNを利用しているので、オリジンのアクセスのみの計測値です)

負荷テストの流れ

以下のような流れを繰り返し、問題を解決しながら 負荷テストを進めていきました。

  • 同時接続数を少ない数から始め、各サーバの負荷やbusy/idle worker数、スループットを見ながら上げていく
    • workerが枯渇する前に 各機能の負荷やレイテンシが上昇してしまう場合は、その原因を調査して解消
      • (設定のミスや構成的な問題、単純なスペック不足など 低レイヤーから高レイヤーまで様々な問題がでてきました)
  • 問題が解消しworkerが枯渇した状態でも、目標となるスループットに達しない場合は アプリサーバの台数を増設
    • (アプリサーバの台数を増やすと、また別の場所がボトルネックになる場合があるため、徐々に台数を増やします)
  • 目標となるスループットに達しても、各機能の負荷やレイテンシが高くなっていなければOK

AWS負荷テストソリューションの設定値

f:id:enigmo7:20211206161621p:plain
設定項目

Concurrencyは どのように設定すれば良いのか?

  • Task Count : <タスク数(コンテナ数)>
  • Concurrency : <タスク毎の同時接続数(ユーザー数)>

合計の同時接続数(合計ユーザー数)はTask Count x Concurrencyになります。 Task Count=1でConcurrencyを増やせば安上がりなのですが、負荷をかける側にも負荷がかかるので そうはいきません。 Concurrencyの推奨制限は200になっていますが、ECRの負荷を見ながら調節する必要があります。

これはドキュメントユーザー数の決定の項目が詳しかったので、ドキュメントを参照してください。

Ramp Upって必要?

Ramp Upは負荷テスト開始時の暖気運転のためだと思っていて、ずっと0に設定して負荷テストしていたのですが 暖気運転以外でもRamp Upを設定した方が良いケースに遭遇しました。

f:id:enigmo7:20211209094154p:plain
Ramp Upの設定で解消した定期的な負荷上昇

BUYMAではアプリケーションサーバとしてPHPRuby on Railsを使用しています。 PHPで処理している機能は少ないのですが、ログイン処理はPHPを使用しています。

ログイン処理は300アクセスに1回程度ですが、Ramp Upを設定しないと負荷テストのすべてのスレッドが同じタイミングでログイン処理をしようとするため、定期的に負荷が上がるような不可解なグラフになったと考えられます。 (時間経過とともにスレッドごとのタイミングがずれていくため、徐々に解消されていきます)

Ramp Upを設定したところ、定期的な負荷上昇はなくなりました。

どれくらいの時間、負荷テストするべきか?(Hold for)

f:id:enigmo7:20211207135714p:plain
長時間負荷テスト

あたりまえですが、テストをする環境や どんな負荷テストをしたいかにより、どれくらいの時間 負荷をかけるべきか変わってきます。

例えば 徐々にキャッシュがたまり、キャッシュヒット率が上がるにつれてDBへの問い合わせが減っていく様子を確認するため 長時間の負荷テストを実施しました(上記のグラフです)。 キャッシュされた状態でのテストをしたい場合はURLリストを少なくして負荷テストしました。

何をテストしたいかによって 設定を変更したり、負荷テストの時間を調節する必要があります。

AWS負荷テストソリューションの問題

Failed to parse the results.

f:id:enigmo7:20211207203019p:plain
Test Failed

長時間負荷テストを実施したり、何回もテストを作成すると AWS負荷テストソリューションのテスト結果レポートが表示されず、Failed to parse the results.になることがあります。 その場合は 負荷テストはできいて、レポート作成処理に失敗しているだけのようです。

ERROR    finalResults function error ValidationException: Item size to update has exceeded the maximum allowed size

CloudWatch Logsで確認したところ 原因はDynamoDBの制限超過エラーのようなのですが、サポートへ問い合わせたところ 仕様だそうです。

分析は主にDatadogを使用しているため、あまり支障はありませんでした。

ダッシュボードからテストシナリオが消えていく

f:id:enigmo7:20211207202649p:plain
test-400,test-700,test-800が消えたダッシュボード

何個もテストケースを作成して負荷テストしていくとなぜか、ダッシュボードからテストシナリオが消えていくことがあります。 テストシナリオの数ではなく、テストの回数か何かに制限があるようです。

消えたテストシナリオでもタブが残っていれば/URLを覚えていれば、設定が残っていて、テスト実行も可能でした。 こちらはそんなに困らなかったので、サポートへ問い合わせはしていません。

サポートに項目がない

f:id:enigmo7:20211209090705p:plain
サポート その1

f:id:enigmo7:20211209090759p:plain
サポート その2

明らかにDynamoDBの問題の場合はサポートに問い合わせできたのですが、AWS負荷テストソリューション自体の問題の場合は サポートのサービスに項目がありませんでした。

AWS負荷テストソリューション自体の問題は SAの方に聞いてみましょう。

AWS負荷テストソリューションのAPI

30分おきにTask Countを変更して負荷をかけていて APIあったらいいなと思っていたのですが、 今回 ドキュメントを見返していたら、APIありました。 見逃してました。

設定を変えてながら連続して負荷テストするような場合はAPIを使いましょう。

最後に

今回は大きなサービスの移行のための負荷テストで、テスト環境では発生しなかった問題が次々と発生するなど いろいろと大変でした。 負荷テストツールにはあまりコストをかけたくなかったので、AWS負荷テストソリューションを使うことで だいぶラクができたと思います。

これから、バッチサーバなどが動いてDBに負荷をかけている状態でも 性能的に問題ないかなどを確認し、自信を持って本番環境の移行に臨めるようにしていこうと思っています。

明日の記事の担当は カスタマーマーケティング事業本部の 杉山 さんです。お楽しみに。


株式会社エニグモ 正社員の求人一覧

hrmos.co

プロジェクトを運用しての学び8つのこと

はじめに

こんにちは、サーバーサイドエンジニアの@hokitaです。

この記事は Enigmo Advent Calendar 2021 の 8 日目の記事です。

今回はテックリードスクラムマスターとして約8ヶ月間プロジェクトを運用していく中で学んだことを8つ紹介したいと思います。

学び

1. ストーリーポイントと難易度

例えば2ポイントのストーリーがあり、経験の長いAさんは2日、初心者のBさんは4日かかるとします。では作業量が倍と見積もった4ポイントのストーリーはどうでしょうか。Aさんは倍の4日でできたのですが、Bさんは始めての作業だったので3倍の12日かかってしまいました。このようにスキルや難易度によってポイントと工数が単純な比例関係にならないことがよくあります。そのため、メンバーのスキルを認知しつつ、どのような策をとるべきか考える必要がありました。

  • 納期が迫っているなら、Bさんが苦手なタスクをAさんにやってもらう
  • スケジュールに余裕があるなら、Bさんに苦手なタスクをやってもらいながらスキルアップを目指す
  • Aさんに余力があるなら、Bさんを手伝ってもらう(ペアプロを実施するなど)

それぞれメリット・デメリットあるので、その時々で判断する必要があるかと思います。

2. フル稼働ではなく1名助人役になる

プロジェクト開始時は私を含めた2名で開発していました。そのときのベロシティは約7ポイントで、途中で人員を増やし4名になってからは約14ポイント消化できるようになりました。人数が倍になったからベロシティも倍になったと思うかもしれませんが、そうではなく、私はあまり開発をせずに助人役に回っていました。実際には下記のようなことを行っていました。

  • 進捗が著しいタスクを発見して対策を考える
  • ストーリー着手前に一緒に設計を考える
  • コードレビュー
  • 手が空いたときには小さめのストーリーを消化

私が開発に集中することもあったのですが、進捗は逆に低下することが多かったです。開発中に発生する問題は思った以上に工数を膨らませます。それを解消する役がいることで安定した開発スピードを出すことができると気づきました。

3. レビューファースト

スクラム開発ではスプリント内で成果物を残し、ステークホルダーへデモを見せフィードバックを貰うことが重要です。よくあったのが、一人で同時に複数ストーリーを進めて、結局どのストーリーもスプリント内に終わらせることができなかった、というものです。なぜそのようなことが発生するかというと、レビューを返すまでに時間がかかっていることが原因でした。レビュー依頼を出した開発者はレビューが返ってくるまでは他のストーリーに着手するかと思います。そうしているうちに複数ストーリーのマルチタスクとなって、結局どのストーリーも消化できずじまいとなってしまいます。レビューはなるべく早く返して、1つのストーリーを確実に終わらせることが大事です。

4. ベロシティがプレッシャーに

良くなかったなと反省しているのですが、1on1の時に各開発メンバーに「次のスプリントでは○ポイントの消化を目指しましょう」とストーリーポイント基準で目標を設置していました。数値目標で管理しやすいと思っていたのですが結果どうなったかと言うと、コードの品質が下がり、時には仕様を満たないプルリクがくることもありました。個人のコーディングスピードはいきなり上がるものではないので、時間を省くとなればデバッグ時間となっていたのだと思います。それに気づいた後は、まずは安定したアウトプットができること、そして、ポイントはあくまで目安に過ぎないことを意識し、目標は消化ポイントとは別のものに変更しました。

5. レトロスペクティブが自己評価になりがち

レトロスペクティブではメンバーそれぞれがKPT法で書いていました。そこでよく上がってくるものは「〇〇の実装で時間がかかってしまった。なので、〇〇を勉強する」のような自己評価が多かったです。個人の能力を伸ばすことも重要ですが、どちらかというとチームとしてなにができるのかを議論することのほうが重要だと思っています。「〇〇で時間がかかった。」のは相談する機会がなかったのが原因なら「朝会で相談する(相談しやすくする)」やスキルが足りない場合は「詳しい人とペアプロの時間を設ける」というのが良い振り返りかと思います。これは開発している本人だと気づけないことが多いので、他の人が提案してあげることが望ましいです。

6. スプリント内で終わらないストーリーは放置しない

前述したとおりスプリント内で成果物を残すことは重要なことですが、どうしてもストーリーを消化できないことは多々発生します。ストーリーの粒度を小さくすることは心がけていたもののどうしてもそうはならないストーリーもありました。ほとんどの場合次の週にも継続して開発するのですが、なぜ終わらなかったのかを調査し対策することが大切です。例えば一人で行き詰まって終わらなかったのなら、次週はペアプロでそのタスクを最優先で終わらせる、もし思っていた以上に作ることがあった(例えばAという機能を追加するのに実はBという機能を作る必要があったなど)なら、まずストーリーを分解することはできないか、他のメンバーと役割分担はできないか、今のまま続けるとしたらどのくらいかかりそうか、など念入りに調査し対策を考えます。これを怠ると何スプリントにもまたがるストーリーになる可能性があり、開発者のメンタルを下げ、負のスパイラルに陥ることが多い印象です。

7. 早くリリースしたいなら機能を削る

まず下記をスクラムチーム全員で認識を合わせる必要があるかと思います。

  • 開発スピードが劇的に向上しないこと
  • 最初に作成した仕様の大半は不要な機能であること

それを前提に納期へ向けてできることといえば「機能を減らす」もしくは「納期を伸ばす」しか手段はないかと思います。今回のプロジェクトもバックログを全て消化するにはベロシティなどの数値から計算して目標納期に間に合わせるのは「不可能」でした。やったことと言えば、優先度の低い機能をごっそりと削ることでした。リリース後にその削った機能を開発したかというとほとんどの機能は「不必要」でした。

8. 興味を引くスプリントレビューを

本プロジェクトはバックエンドのメンバーが多かったので、デザインは後回しにして簡素なページを作成していき、デモでは毎週動くものを提供していたのですが、ステークホルダーからのフィードバックが薄いことに気付きました。その後デザインが当たった段階でやっといろいろな意見をいただけるようになりました。動けば良いというものではなく、もしデザインファーストなプロトタイプを作っていればもっと早い段階で多くのフィードバックを貰えたかと思われます。機能やステークホルダーのよりけりだと思いますが、興味を引くようなプロトタイプを作ることも重要だと気づきました。

最後に

いかがだったでしょうか。まだまだ未熟ですが、今回の学びを次回のプロジェクトへ生かしていこうと思います。

明日の記事の担当は インフラエンジニア の 高山 さんです。お楽しみに。


株式会社エニグモ 正社員の求人一覧

hrmos.co

決定木分析を使用して、データ分析を行った話

こんにちは、エニグモでデータアナリストをしている井原です。

この記事は Enigmo Advent Calendar 2021 の 7日目の記事です。

今日は、実際に業務で、データ分析をした内容を元に、データアナリストがどのような仕事をしているのかをお話したいと思います。

データアナリストの仕事

世の中では、データアナリストと言われる職種の仕事は多岐に渡ると思います。

データマイニング、データ分析基盤の整備、ビジュアライゼーション、KPIの設計、機械学習モデルの構築、etc...

エンジニアリングやサイエンスの領域と思われるところを担っているデータアナリストの方もいらっしゃるのではないかと思います。

エニグモの場合、データサイエンティストやデータ基盤エンジニアといった、専門家が在籍しています。そのため、データアナリストは、施策の効果検証やサイト上の課題発見といった、ビジネス領域の課題に対して、データ分析で解を出す仕事にフォーカスすることが多いです。

また、エニグモは、データ分析のリテラシーが高く、データアナリストではないディレクターといった職種の人でも、SQLを回して、データの抽出/分析を行うことが普通の文化になっています。

データアナリストとしては、データ分析の設計や手法を深く理解して、アウトプットを出していくことのやりがいを感じながら、仕事の出来る環境になっていると思います。

決定木による売れ筋商品の分析

ここからは、実際に分析した例を元にして、分析手法として使用した決定木分析について、お話したいと思います。

課題

エニグモが運営しているBUYMAでは、CtoCの売買を仲介するプラットフォームビジネスを行っています。

そのため、ECサイトとして、購入者だけではなく、販売を行う出品者に対してのフォローも行うことが必要です。出品者の方に良質な商品を出品していただくことで、売り場としての魅力が向上し、購入者にとっても、良質なサイトになっていくと考えられます。

しかし、良質な商品とは何なのか?想像するものは、人それぞれで異なると思います。そこを、定性的な感覚だけでなく、定量的なデータ分析を行うことで、売り場にあるべき商品を定義し、出品者の方に出品促進を行っていきたい、というのが、今回の課題でした。

分析方法の選定

良質さを決める要素は数多くあると思いますが、今回はまず、基礎的な分析として、商品のブランド、カテゴリ、モデル名の中で、どのような商品が売れているのかを調査しました。また、売れている商品、の定義については、ビジネス側のメンバーと議論のうえ、CVR(出品された商品数のうち、販売された商品数の割合)としました。

早速、日別のデータを取得し、BUYMAの中で主流となるジャケットカテゴリに絞ると、以下のようなデータが確認できます。
※なお、記事内で取り扱っているデータについては、全て、ダミーデータとなります。

f:id:enigmo7:20211129101224p:plain

BUYMAで取り扱われているブランド、カテゴリ、モデル名は、数が多く、クロス集計などで解釈することは困難と思われます。

ブランド、カテゴリ、モデル名をそれぞれ単体で集計することも可能ですが、その場合、あるブランドのCVRが高いと、どのようなカテゴリ、モデルでも高いのか?といった解釈が難しくなります。

今回は、CVRに対して、ブランド、カテゴリ、モデル名といった特徴のうち、どの要素の影響が大きいのか?を分析したいですので、可視性が高く、解釈性のよい決定木分析を使って、分析してみることにしました。影響の大きさを見るには、重回帰分析といった手法もありますが、決定木分析であれば、要素の掛け算(このブランドのこのモデルのCVRが高い、といった見方)も確認できます。
※厳密には、重回帰分析でも要素の掛け算を変数とすることで、出来ないことはありませんが。

実装

pythonを使って、実装していきます。

先ほど取得してきたデータのうち、ブランド、カテゴリ、モデル名、を説明変数とし、CVRを目的変数として予測する決定木モデルを作成します。

環境:
Windows 10 Pro
Python 3.9.9

1.ライブラリのimport
必要なライブラリをインポートします。

import pandas as pd  
import subprocess  

# 可視化を行うためのライブラリ  
import matplotlib.pyplot as plt  

# 回帰の決定木モデルを作成するためのライブラリ  
from sklearn.tree import DecisionTreeRegressor, export_graphviz  
from sklearn.model_selection import train_test_split  
from sklearn.metrics import r2_score  
from sklearn.metrics import mean_absolute_error  

2.データの読み込み
pandasでデータを読み込みます。

df = pd.read_excel("cvr_data.xlsx")[["date", "brand", "cate_name", "model", "listing_count", "sell_count"]] # 必要な列に絞る

# データの確認
print(df.head())
print(df.columns)

3.移動平均に変換する
ECデータの場合、平日より休日の方が多く売れる傾向がありますので、7日間移動平均に変換して、データを均します。
ローデータは、前の要素の9/30の次に次の要素の9/1が来てしまうため、9/7以降のデータに絞り込みます。
※もっとよいやり方がありそうな気がしますが、自分の知識だとこうなりました。

df["listing_count"] = df["listing_count"].rolling(7).mean()
df["sell_count"] = df["sell_count"].rolling(7).mean()
df = df[df["date"] >= "2021-09-07"]

# データの確認
print(df.head(30))

# CVRを計算して、カラムを追加
df["cvr"] = df["sell_count"]/df["listing_count"]

4.変数をダミー変数に変換
今回、使用する予測変数は、全て質的データになるので、そのまま、決定木分析に使用することは、出来ません。
get_dummies関数を使って、ダミー変数に変換します。

df = pd.get_dummies(df, drop_first=True)

# 2の時点と異なることを確認
print(df.columns) 

5.データの分割
予測変数と目的変数、学習用データとテスト用データに分割します。
今回は、モデルの精度を上げることは目的としていないため、テストデータは少なくして、ほとんどのデータを学習データにしました。

exclusion_list = ["cvr", "date", "listing_count", "sell_count"]
include_list = [column for column in df.columns if column not in exclusion_list]

obj_df = df["cvr"]
exp_df = df[include_list]

obj_array = obj_df.values
exp_array = exp_df.values

X_train, X_test, Y_train, Y_test = train_test_split(exp_array, obj_array, test_size=0.01, random_state=222)

6. 決定木モデルの学習
作成したデータで、決定木モデルを学習させます。

# モデルのインスタンス生成
reg = DecisionTreeRegressor(max_leaf_nodes=20)

# 学習によりモデル生成
model = reg.fit(X_train, Y_train)
print(model)

# 評価
y_true = Y_test
y_pred = model.predict(X_test)
print(r2_score(y_true, y_pred))
print(mean_absolute_error(y_true, y_pred))

7. 木構造を画像に保存
モデルの木構造を解釈できるよう、画像に変換します。

dot_data = export_graphviz(model,
    out_file="cvr_data.1.dot",
    filled=True,
    rounded=True,
    feature_names=exp_df.columns
)

subprocess.run("dot -Kdot -Tjpg -Nfontname='MS Gothic' -Efontname='MS Gothic' -Gfontname='MS Gothic' cvr_data.1.dot -o cvr_data.jpg".split()) # 日本語を含むと、文字化けするため、fontを指定

解釈

以上のソースコードを実行すると、以下のような決定木のjpgファイルが出来上がります。

f:id:enigmo7:20211129101816j:plain

出来上がった決定木を見ながら、解釈をしていきます。
注意点として、決定木は、lossが少なくなるように分割していくアルゴリズムであるため、上位に出てくる変数が、必ずしも、CVRを高くする変数とは限りません。
valueを確認しながら、どのような分割がなされているか、確認していきます。

  • まず、カテゴリ_jacketGが最初のノードで分割されるようになっています。
    そして、右に分割されたノードのvalueは0.108と左の0.024のノードよりも高いため、カテゴリが、カテゴリ_jacketGの場合、CVRがかなり高くなると解釈できます。
  • では、カテゴリ_jacketGであれば、なんでもよいかというと、その次の分割を見てみると、ブランドがブランド_BNである場合、valueが0.142、そうでない場合は、0.006となっているため、カテゴリ_jacketGは、ブランド_BNが一強のカテゴリであることが分かります。さらにノードを下ると、ブランド_BNの中でもモデルによって、CVRは異なるようですが、全般的には、高いCVRを擁していることが見てとれます。
  • カテゴリ_jacketGではないノードを見ていくと、いくつかのブランド名でノードが枝分かれするようになっています。カテゴリ_jacketGでなければ、その次は、ブランドの選択が重要である、ということが見てとれます。実際には、企画担当者と会話をしながら、表示されているブランドをグルーピングなどして、整理しました。
  • さらに深く確認しようと思えば、ブランド_BFは、カテゴリによって差がある、カテゴリ_jacketBカテゴリかどうかで、ノードが分かれる、と状況に応じて、確認していくことも可能です。

決定木の場合、初めにも話した通り、視覚的に分析結果を表せるため、ドメイン知識が少なくても、結果の解釈が行いやすいことはメリットではないかと思います。また、企画担当者側も分析結果が分かりやすいので、スムーズに相談が行いやすくなると思います。

なお、解釈性が高い決定木分析ですが、注意点もあります。

まず、決定木分析は機械学習アルゴリズムの中では、精度が高くなりにくい、と言われています。これは、モデルが学習データに過学習しやすく、汎用性が低くなってしまうためです(今回は、生データや、感覚値ともずれていないという判断をして、精度はあまり重視しませんでしたが。)。決定木に限りませんが、あくまでも学習データとして使用したものの説明にしかなっていませんので、将来的にも同じ傾向があるかどうかは、確実ではありません。特に、一時的に強い需要があったデータなどが含まれると、当然、そのデータの影響が強く出てしまうため、注意が必要です。

今後の展望

今回は、比較的、カジュアルな分析でしたので、そこまで、多くない変数で実施しました。感覚としては、企画担当者側も理解しやすかったのではないかと感じましたので、決定木を使ったデータ分析は有用であると考えています。

変数を増やしていくことで、目的とする変数に対して、どういった変数が影響を与えているのか、さらに詳細な分析を行うことも可能と考えられます。

また、決定木アルゴリズムの発展形として、LightGBMやXGBoostなどのアルゴリズムが、データサイエンス分野では、スタンダードになっているようです。他にも、SHAPなど、今回、実施した内容以外で、機械学習モデルの可視化をする方法が研究されており、自分も現在、勉強中です。

最初にお伝えした通り、エニグモには、データアナリストとは別に、データサイエンティストの職種もあります。データサイエンスのプロフェッショナルがいて、通常のデータ分析を企画担当者の方も普通に行っている環境ですので、ビジュアライゼーションやモデルの説明性といった手法を使って、データとビジネスをうまくつなげていくのが、データアナリストの役割ではないかと考えています。

本日の記事は、以上です。読んでいただき、ありがとうございました。

明日の記事の担当はエンジニアの沖田さんです。お楽しみに。


株式会社エニグモ 正社員の求人一覧

hrmos.co

OhMyZshからZinitに乗り換えてみた話

この記事は Enigmo Advent Calendar 2021の6日目の記事です。

こんにちは。BUYMAでWebエンジニアをやっております、岡本です。エニグモに入ってから約1年が経過しました。

学生の時にプログラミングを始めてしばらくbashを使っていたのですが、イケイケの先輩にzshを教えてもらい、zshの機能を拡張するためのプラグインマネージャーにはOhMyZshを勧められ、数年利用していました。この時期に使っていたmacOSの標準シェルはbashで、zshはわざわざインストールするものでした。

1年前にエニグモに入社した頃、支給されたMacBookProに搭載されているmacOSの標準シェルは既にzshになっていました。(標準シェルがzshになったのはmacOS 10.15 Catalina以降です)

せっかくの機会なので気持ちを新たにプラグインマネージャーも替えてみようと思い立ち、いくつかzshプラグインマネージャーを調べたところZinitが良さそうに思えたので導入することにしました。今回は導入した感想を軽く綴ってみようと思います。

github.com

(2021年12月6日閲覧、以下記載URLも同様)

いいところ

いくつか公式ドキュメントでもアピールされていますが、個人的に良いと思うところを挙げます。

zshの起動が速くなる

公式ドキュメントで喧伝されているのがzshの起動スピードについてです。早いことをアピールしています。

Zinit is currently the only plugin manager out there that provides Turbo mode which yields 50-80% faster Zsh startup

訳(Zinitは現在、ターボモードを提供する唯一のプラグインマネージャーであり、Zshの起動が50〜80%速くなります。)

cf. https://github.com/zdharma-continuum/zinit#zinit

ここでターボモードとは何ぞやとなるのですが、waitを使った遅延読み込みのことを指すようです。これについては後ほど紹介しますが、ターボモードを使わなくても従来のプラグインマネージャーと比較するとzshの読み込み速度は高速になっていると思います。

OhMyZshおよびPreztoプラグインとライブラリの読み込みをサポートしている

OhMyZshやPreztoなどを利用していた方もその資産を継承できます。なお私はOhMyZshのプラグインは現在は読み込まずに使っています。気になる方は以下をご覧ください。

参考URL

https://zdharma-continuum.github.io/zinit/wiki/INTRODUCTION/#oh_my_zsh_prezto

使ってみよう

Zinitのインストール方法はこちらからご覧いただけます。

https://github.com/zdharma-continuum/zinit#automatic-installation-recommended

sh -c "$(curl -fsSL https://git.io/zinit-install)"

source ~/.zshrc

zinit self-update

こちらを実行することで~/.local/share/zinit/zinit.gitにzinitがインストールされ、zshrcにzinitの設定が追加されます。

ここから自分好みにカスタマイズしていくわけですが、現時点の私のzshrcを見てみるとこんな感じになってました。1~7行目はromkatv/powerlevel10kを使うために設定しているものです。一言でいうとターミナルのUIをカラフルにしてくれるものです。ペアプログラミングの機会があると「ターミナルのUIがカラフルですね」とよく言われます。ディレクトリ名やブランチ名が見やすいのでOhMyZshを使っている時からずっと使っています。

  1 # Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
  2 # Initialization code that may require console input (password prompts, [y/n]
  3 # confirmations, etc.) must go above this block; everything else may go below.
  4 if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
  5   source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
  6 fi
  7
  8 ### Added by Zinit's installer
  9 if [[ ! -f $HOME/.zinit/bin/zinit.zsh ]]; then
 10     print -P "%F{33}▓▒░ %F{220}Installing %F{33}DHARMA%F{220} Initiative Plugin Manager (%F{33}zdharma/zinit%F{220})…%f"
 11     command mkdir -p "$HOME/.zinit" && command chmod g-rwX "$HOME/.zinit"
 12     command git clone https://github.com/zdharma/zinit "$HOME/.zinit/bin" && \
 13         print -P "%F{33}▓▒░ %F{34}Installation successful.%f%b" || \
 14         print -P "%F{160}▓▒░ The clone has failed.%f%b"
 15 fi
 16
 17 source "$HOME/.zinit/bin/zinit.zsh"
 18 autoload -Uz _zinit
 19 (( ${+_comps} )) && _comps[zinit]=_zinit
 20
 21 # Load a few important annexes, without Turbo
 22 # (this is currently required for annexes)
 23 zinit light-mode for \
 24     zinit-zsh/z-a-rust \
 25     zinit-zsh/z-a-as-monitor \
 26     zinit-zsh/z-a-patch-dl \
 27     zinit-zsh/z-a-bin-gem-node
 28
 29 ### End of Zinit's installer chunk
 30 以下略

さて、プラグインを設定してみます。zshを使う上で外せないのは補完とシンタックスハイライトではないかと思います。

# 補完
zinit light zsh-users/zsh-autosuggestions
# シンタックスハイライト
zinit load zdharma/fast-syntax-highlighting

ここで、プラグインの読み込み方法はloadlightがあります。

loadを使うことでプラグインのトラッキングを可能にします。zinit report {plugin-spec}プラグインの情報を出力し、zinit unload {plugin-spec}プラグインを無効にします。

一方lightを使うとプラグインのトラッキング機能が無効になり、loadに比べて読み込み速度が速くなるようです。

またsnipetを使うと、URLを直接指定する形でプラグインを読み込むことができます。

zinit snippet https://gist.githubusercontent.com/hightemp/5071909/raw/

cf. https://zdharma-continuum.github.io/zinit/wiki/INTRODUCTION/#basic_plugin_loading

このような感じでお好みのプラグインを追加していきましょう。筆者のzshrcをみるとzdharma/history-search-multi-wordというコマンド履歴を検索するプラグインが入っています。

zinit load zdharma/history-search-multi-word

f:id:enigmo7:20211202102734g:plain

設定例はzinitのドキュメントに記載されているので私はこれを参考にして設定したのですが、ここでiceというものが出てきます。

zinit ice pick"async.zsh" src"pure.zsh"
zinit light sindresorhus/pure

zinit ice depth=1; zinit light romkatv/powerlevel10k

zinit iceは直後の行で実行されるloadlightの挙動を変更します。iceの後のpicksrcなどはice-modifiersと呼ばれるもので、 iceという名前の由来は、氷は飲み物に入れて少し経つと溶けることから、変更が一時的なものであることを意味すると公式ドキュメントでは説明されています。ice-modifiersの後ろにクォーテーションやイコールで指定されているのは引数です。ice-modifiersが引数によってzinitの挙動を制御します。例えば上記のpickであれば、引数として与えられた"async.zsh"に実行権限を与えてPATHに追加するようにzinitに対して指示しています。

その他のice-modifiersの用法についてはこちらを参照してください。

https://github.com/zdharma-continuum/zinit#ice-modifiers

おわりに

基本的な使い方はできていると思いますが、まだまだ知らないオプションが多いのでもっと使いこなせるように日々精進したいと思います。

次回の記事の担当はデータアナリストの井原さんです。お楽しみに!!


株式会社エニグモ 正社員の求人一覧

hrmos.co

おすすめポモドーロアプリ4選徹底比較!ポモドーロテクニックによる時間管理術

こんにちは、サーバーサイドエンジニアの竹本です。 この記事は Enigmo Advent Calendar 2021 の3日目の記事です。

みなさまは2021年どのように過ごされましたか、株式会社エニグモでは昨年の新型コロナウイルスの影響で2020年2月からリモートワークに以降したのですが、今年はなんとオフィスが半分になり全社的なリモート体制が整いました。(新オフィスの紹介記事 最高なオフィスにリニューアルしました!!BUYMA/株式会社エニグモ | 株式会社エニグモ ) コロナ禍抜けたら出勤再開しましょうなどの展開はなく、リモートに切り替える機動性の高い会社です🤗 採用情報はコチラ

というわけで、1エンジニアの私もリモートワーク中心の生活が続いております。そういう状況の方は多いのではないでしょうか?

ところで、お家での作業は捗っていますか!? あんまり集中できない日があったり、逆にいつの間にか窓の外が暗くなっていたりなど、色々あるのではないでしょうか?そこでおすすめしたいのがポモドーロテクニックです。

ポモドーロとは

ポモドーロテクニックといって25分作業して5分休憩することによって集中力を持続させることができる作業方法です。

私がポモドーロを始めてみようと思ったのはSOFT SKILLS ソフトウェア開発者の人生マニュアルを読んだことがきっかけでした。ポモドーロテクニック自体は知っていたのですが、作業中にタイマーがなるのが鬱陶しそうで敬遠していました。 しかし本書ではポモドーロテクニックは集中のためのツールというよりも、

  1. ポモドーロ何セットかかるタスクなのかを見積もる (以下記事の中ではポモドーロ1セット=1ポモと単位ポモで表記します)
  2. 実際何ポモかかったのかを計測する
  3. 以上を繰り返す

これにより、タスク見積りの精度が向上していくメリットを中心にポモドーロテクニックを紹介しています。

自分でタイマーをセットして見積りと計測をメモっていっても良いのですが、世にはいっぱいポモドーロアプリがあるので、便利に活用したい! というわけで自分の作業環境や、目的に合っていそうなアプリを探す旅に出ました。

以下の条件で選定しております。

  • 無料で試せる
  • macで利用できる
  • 作業ログを見ることができる

そして条件に合った4つのアプリを実際に試したので紹介させていただきます。

  • Pomofocus
  • Kanban Flow
  • life line
  • Be Focused

Pomofocus

https://pomofocus.io/

  • 「pomodoro timer」でググると一番上に出てくる
  • シンプルなUI
  • タスクにかかるポモドーロのセット数見積りを設定できる
  • 中断できる
  • ログが見れる

f:id:enigmo7:20211201121907p:plain
Pomofocus画面

一番最初に試したのがこのアプリでした。本当にシンプルで簡単に利用することができ、私自身「ポモドーロ、試してみようかな…」という段階でこのアプリに出会うことができたところが今もポモドーロを継続できていることに繋がっていると思います。

またタスクの設定時に何ポモかかりそうか見積りを設定し、実際何ポモ経っているのかを計測できるので、当初の目標とマッチしています。以降紹介するアプリの中でも最も簡便に見積りの入力ができるので気に入っているポモドーロアプリです。

Kanban Flow

https://kanbanflow.com/

  • カンバン的UI
  • サブタスクもチェックボックスで管理できる
  • タスクにかかる時間の見積りが設定できる
  • ログがめっちゃ見やすい
  • 中断しようとすると理由を聞かれる

f:id:enigmo7:20211201121602p:plain
Kanban Flow画面 カンバンはユーザーを招待してチームで管理することもできる

名前の通りカンバンUIで全タスクを一望できるのが便利!

他のアプリは作業中のタスクだけ表示の場合も多いですが、こちらはTodo/DoToday/InProgress/Done全てのステータス(ステータスカラムは編集可能)のタスクが表示されており、またカンバンはプロジェクトごとに管理できるようになっています。

何よりSOFTSKILLS作者ジョンソンメズによって開発されているのもあり、こちらもタスク設定時にタスクにかかる時間の見積り設定が可能です。

しかし作業の中断に厳しい設計になっており、ちょっとトイレ行きたい時にも、タイマーを止めようとすると、ポモドーロを中断させられるし(また0からポモドーロを始める必要がある)急いでいるのに理由を聞かれたりして、まあいっかとタイマー回しながらトイレに行くことが多かったです。

f:id:enigmo7:20211201144021p:plain
ポモドーロ停止理由一覧 停止するときはこのくらいの覚悟を持てということなんですね oyatsuは自分で追加しました

life line

  • 画面上部のメニューバー下に作業時間が可視化される
  • PCで作業しているとタイマーを自動で回してくれる
  • 休憩時間は画面をグレーアウトしてくれる

kanban flowを利用していたあたりに、「ブラウザでのタイマーはわざわざそのページを見に行かなきゃいけなくて面倒だな…」と思っていたところでこちらを試してみました。

mac画面上部のメニューバー下に1日の作業している時間がグラフとして可視化されます。 また、ログを見ると、作業時間、休憩時間が日ごとに確認することができます。

f:id:enigmo7:20211201143230p:plain
life lineログ画面 お昼休みが黒かったり、MTG中は休憩していなかったりが一目瞭然

またlife lineの面白い機能として、一定時間以上PCで作業しているとタイマーが起動し、25分経過すると画面がホワイトアウトして作業を止めることができるのでやや強制的に作業のリズムを作ることができます。

しかし、自動でタイマーが起動する性質上、個別のタスクに関する見積り、計測が難しいです。 ちょっとslack巡回しよ…って時もタイマーが動き出してしまい、「あー今はタスクやってたわけじゃないのにー!」となります。

Be Focused

  • メニューバーで時間を確認できる
  • タイマーのアラーム音をたくさんの中から選べて愉快
  • 見積りも入力できる
    f:id:enigmo7:20211201145332p:plain
    Be Focused画面 アップグレードしたら広告は消えるそうです

やっぱりメニューバーで後何分か確認できるやつが欲しいな!そしてタスクごとにタイマーを手動で動かしたい!と思いこちらのアプリに出会いました。

タスクを追加して、タスク詳細画面から何ポモかかりそうか入力して、タイマーをスタートさせるというシンプルな流れ。

というわけで現在はBe Focusedに落ち着いています。

アプリはさまざまなものが出ているので、ポモドーロを導入する目的にあったアプリを見つけて、良いポモドーロライフをお送りください!

次回の記事の担当は サーバーサイドエンジニア の 岡本さんです。お楽しみに。


株式会社エニグモ 正社員の求人一覧

hrmos.co

コーポレートITの未来を考えた話

f:id:enigmo7:20211110103537p:plain こんにちは、Corporate IT/Business ITを担当している足立 です。

この記事はEnigmo Advent Calendar 2021の 2日目の記事です。

エニグモでは1人目のコーポレートIT担当として未着手な社内IT環境をコツコツ整備してます。 世間一般的には情報システム(情シス)と呼ばれるポジションです。

昨年はコロナ対応について書きましたが、もう早いものであれから1年が経過しました。
今年はコーポレートITの未来を考えた話について書きたいと思います。

コーポレートITの未来って?

早い話、ロードマップ(中期計画)を考えた話になります。
今後、3年間で実施したいIT投資計画を策定し経営層に対し内容を共有しました。

では、何故中期計画を策定したのか?

私がエニグモに来てから2年半以上の月日が経ち、入社直後のミッションとして下記内容がありました。

  • 老朽化した複合機のリプレイス
  • Google Workspaceのプラン変更
  • 紙ベースの権限申請の電子化

それぞれについて書くと長くなるので割愛しますが、上記の目処が立った矢先にコロナ対応、オフィスリニューアルPJがあり 場当たり的な対応を続けて来ました。 とは言え外的要因が起因とした状況でしたが、エニグモの社内システムの環境は大幅に改善されたと思います。

f:id:enigmo7:20211108114225p:plain
入社直後の社内システムの一部
上記の図は私が入社直後の社内システムの一部になります。 管轄が違うシステムも含まれていますが、全社的に使用する物はコーポレートITが管轄しています。

f:id:enigmo7:20211108114909p:plain
現在の社内システム一部
現在はコロナ対応に伴うリモートワーク環境構築の為に導入した物やオフィス リニューアル時に導入したシステムを合わせると上記の図のようになりました。

環境が大きく変わりましたが思いとしては道半ば。 まだまだ、導入しなければならない物が沢山あると感じていますが、今後も場当たり的に導入するのではなく 中期的に必要性や導入計画も立て予算についても経営層と事前に共有する事が必要と思いました。

例えば導入したい物が高額な場合に経営層も直々にOKを出す事は難しいですし、 導入したいシステムが一部だけ承認が降りたとしても会社全体でのシステム構成にバラツキが出てしまうのも 余計な投資を実行してしまう要因にも成りかねません。 モダンなシステム構成の実現、無駄な投資を防ぐ為にも中期計画が必要でした。

中期計画 策定のパートナー

私自身の中に今後、導入したいシステム構成はボンヤリとありましたが、果たして本当にその構成で良いのか?エニグモに取ってベストな構成なのか?と言う疑問がありました。 そこで中期計画を策定するにあたり外部の力を借りる事にしました。

f:id:enigmo7:20211108135212p:plain
クラウドネイティブさん
パートナーとしてクラウドネイティブさんのご協力をお願いしました。 お願いした理由としていくつかありますが、代表的な事としては下記の通りになります。

  • ベンダーフリー
    • ベンダーに属されていないのでフラットな立場で様々なサービスを提案・導入が出来る
    • ベンダーによっては導入提案出来る商材が決まっていたりする事があるのでフラットな立場で提案して頂ける部分に魅力を感じました。
  • 自立を考えてくれる
    • 支援をお願いすると基本、代行してやってくれるケースが多いですが基本、弊社にナレッジやノウハウを残して頂けるように支援してくれます。
    • また、問い合わせに関してはSlack出来る為、レスポンスが早くスピーディーに対応して頂けます。
  • 強力なスタッフ
    • 情シスSlack内やイベントでお見かけする強強な情シス経験者の方が参画しているので心強い。
    • 尊敬する方もいらっしゃったので一度、お仕事をご一緒したい思いもありました。

元々、IdP導入はクラウドネイティブさん経由で実施する予定でしたので、同時進行で進めていく事になりました。 やはり自分が考えている構成について壁打ち出来る相手が居ることは安心感に繋がりました。

コーポレートITのMVV

中期計画を策定にあたり、経営層との話し合いの場を設けて頂きました。 IT投資を実施する為に役員がコーポレートIT部門に対してどんな目的で、どのようなチームであって欲しいのかヒアリングをさせて頂き その内容をベースにMVV(ミッション・ビジョン・バリュー)を策定し、その内容にあった計画を作る事にしました。

ヒアリング当日は役員に対してコーポレートITに対して思っている事、実現して欲しい事を兎に角、何でも良いので言って欲しいとお願いし 様々なワードが出てきました。 そのワードを元に作成したMVVが以下の通りになります。

ミッション(使命、目的)

全てのStakeholderをHappyに

ビジョン(将来像)

社員と組織のValue実現をITで支えるチーム  

バリュー(スタイル)

「 Location Free 」 「 Always update」 「 Balancing productivity and security」

f:id:enigmo7:20211108160114p:plain
MVV

ミッションである「全てのStakeholderをHappyに」は代表である須田さんのお言葉でした。 ヒアリング当日はワードが出てこないのでは無いのかと懸念してましたが、予想とは裏腹に3人の役員が思いの丈をぶつけて頂きました。 中でも「従業員だけでなく、協力会社の方々、BUYMAユーザー、パーソナルショッパーなどエニグモに関わる全てのStakeholderがHappyになる環境であって欲しい」とお話して頂いた時はミッションはコレしかないと感じました。

f:id:enigmo7:20211108160736p:plain
ミッション

ビジョンである「社員と組織のValue実現をITで支えるチーム」はエニグモの企業理念にある3つの価値基準を大切する行動指針を後押し出来るチームである事を示しました。

セルフスターター

他人や環境に左右されず、自ら目標を見つけ引き金を引き、突き進める人

アウトパフォーマー

自分の強みを鍛え、常識、限界、期待値を超えていく人

チームビルダー

”日頃”のチーム作りと”実践時”のチームパフォーマンスに貢献できる人

f:id:enigmo7:20211108161752p:plain
ビジョン

最後にバリューについては3つの指針にしました。

Location Free

コロナ禍後は会社を身軽にする事に注視し、物は持たずPC端末とインターネット回線があれば世界中どこでも業務が出来る環境の実現を目指す事にしました。

Always update

次から次へと新サービス、新しいシステムが出てきます。既存の環境に満足せずに常にアップデートし続ける事を目標としました。

Balancing productivity and security

管理出来ないツールやサービスが増えると、そこがセキュリティホールになる危険性がありますが、無闇矢鱈に規制すると生産性が低下します。 矛盾した話になりますが、「生産性と安全性」を両立した構成を目指す事にしました。

f:id:enigmo7:20211108163734p:plain
バリュー

MVVについては無くても中期計画は策定出来ますが、私はあった方が良いと思っています。 経営層とコーポレートITの間でチームの方向性について同じマインドであった方がより良い組織になると感じるからです。

リスクと課題の洗い出し

エニグモにある想定されるリスクや課題の洗い出しに着手し懸念点については全てお話し必要な対応を可視化。 それに基づき必要なソリューションをマッピングしていきました。 弊社のセキュリティに関わる部分になるので、詳細については書くことが出来ませんが、箇条書きでも良いので懸念点をメモしておく事をオススメします。

ソリューションの選定に基づきロードマップへ反映しました。

f:id:enigmo7:20211109133233p:plain
ロードマップ

また、概算費用を算出する為、必要ライセンス数の洗い出し、定価ベースでの費用感を算出しました。 大凡の金額感だとしても、これだけの費用がかかるのかと思うと震えました。

未来へ

課題や懸念点、予算感を取りまとめてロードマップにし役員へ共有を行いました。 役員からは「概ね、agree」と言われて、同意して頂いたのでほっとしました。

今後についてはフェーズ毎に改めて詳細なシステム構成案、費用感、検証を実施し役員へ最終提案を行います。 より快適でセキュアな環境構築の為に日々、精進していきたいと思います。

明日の記事の担当は サーバーサイドエンジニアの竹本さんです。お楽しみに。


株式会社エニグモ 正社員の求人一覧

hrmos.co