Holmes開発者ブログ

契約マネジメントシステム「ホームズクラウド」の開発者ブログです

gilotによるGitログ解析を、複数Gitリポジトリに対して試してみた

Holmesでエンジニアをしている山本です。

gilot (ジロー)の紹介記事を見て、複数チーム・複数Gitリポジトリで開発している弊社ではどのような結果が得られるかと思い、試してみました。

qiita.com

実行環境

名前 バージョン
OS Windows 10 Pro 64bit バージョン2004
Python 3.8.5
Git 2.28.0.windows.1
gilot 0.2.4

参考

Qiitaの記事gilotのGitHubリポジトリ、また以下の記事を参考にしました。

解析対象

解析対象とするリポジトリについて

現在、弊社では、複数のGitリポジトリに対して複数チームが開発を行っています。

今回は、Javaによるバックエンド、Vue.jsによるフロントエンドを対象とし、それぞれ名前を backend, frontend とします。対象とするブランチは、いずれもmasterです。

以下のディレクトリ構造にて、 root ディレクトリをカレントディレクトリとしてコマンドを実行していきます。

root/
  ├ backend/
  └ frontend/

hotspotやhotgraphで対象とするファイルパスについて

hotspotやhotgraphでは、ユニットテストなどのファイルを含めると結果が正しく取れないため、対象とするファイルパスを指定します。

backendは、プロジェクト管理ツールとしてGradleを使用したSpring Bootアプリケーションのため、解析時には --allow-files 'src/main/*' を指定します。

frontendは、複数パッケージを packages/* 配下で管理しており、その中にStorybookやJestのテストファイルが含まれるため、解析時には --allow-files 'packages/*' --ignore-files '*/__tests__/*' '*.spec.ts' '*.stories.js' を指定します。

gilotによる解析

インストール

GitとPython3はインストール済みのため、 pip install gilot でインストールできました。

gilotのインストールに成功すると、バージョンが表示されます。実行環境にも記載しましたが、記事作成時点でのバージョンは0.2.4です。

Installing collected packages: gilot
Successfully installed gilot-0.2.4

また、 author コマンドによるグラフ描画に使用されるということで、IPAゴシックフォントをインストールしておきます。

IPAフォントのダウンロード

log

まずはログの取得を行います。 hotspothotgraph では --full オプションをつけて出力しておく必要があります。

後の解析コマンドにファイルを渡しやすいよう、出力ファイルにはプレフィックスとして log- を付与しておきます。また、frontendの開発が始まったのが2020年6月のため、 --since 2020-06-01 で開始日を指定します。

gilot log --full -b master -o log-backend.csv --since 2020-06-01 --full backend/
gilot log --full -b master -o log-frontend.csv --since 2020-06-01 --full frontend/

backendは約1,300行の出力に1分ほど、frontendは約2,100行の出力に2分ほどかかりました。

出力にはマージコミットも含まれますが、除外せずそのまま解析を行います。

plot

plot コマンドにて、グラフ生成を行います。

開発手法としてスクラムを採用しており、スプリント期間は各チーム1週間となっているため、解析時のタイムスロットを -t 1w で1週間とします。

backendとfrontend、両方合わせたものと個別で3種類出力してみます。

gilot plot -i log-*.csv -t 1w -o plot-all.png
gilot plot -i log-backend.csv -t 1w -o plot-backend.png
gilot plot -i log-frontend.csv -t 1w -o plot-frontend.png

それぞれの結果は、以下のようになりました。

f:id:h-yamamoto_holmescloud:20200904162547p:plain
plot-all

f:id:h-yamamoto_holmescloud:20200904162603p:plain
plot-backend

f:id:h-yamamoto_holmescloud:20200904162620p:plain
plot-frontend

frontendは6月から開発を開始したため、環境構築時のコミット行数が多く、かなり上振れしたグラフになっておりました。出力期間の変更が必要そうです。

アウトプットの落ち込みがある部分は、お盆休みの週となります。

hotspot

hotspot コマンドにて、変更頻度の高いファイルのランキングを出力します。ユニットテスト関連ファイルなどを除外するため、--allow-files および --ignore-files を指定しております。

gilot hotspot -i log-backend.csv \
  --allow-files 'src/main/*'
gilot hotspot -i log-frontend.csv \
  --allow-files 'packages/*' \
  --ignore-files '*/__tests__/*' '*.spec.ts' '*.stories.js'

# 出力結果
------------------------------------------------------------
    gilot hotspot ( https://github.com/hirokidaichi/gilot )
------------------------------------------------------------

 hotspot  commits  authors file_name
   19.57       57        5 src/main/java/<path_to_file>
   17.71       67        5 src/main/java/<path_to_file>

また、 --csv -o 出力先ファイルパスCSV出力が可能です。この場合、除外していないすべてのファイルについて、解析結果が出力されます。

gilot hotspot -i log-backend.csv --csv -o hotspot-backend.csv \
  --allow-files 'src/main/*'
gilot hotspot -i log-frontend.csv --csv -o hotspot-frontend.csv \
  --allow-files 'packages/*' \
  --ignore-files '*/__tests__/*' '*.spec.ts' '*.stories.js'

以下のようなCSVが出力されました。--csv を付与せず実行した場合より、項目が増えています。

file_name,hotspot,commits,authors,edit_rate,lines
src/main/java/<path_to_file>,19.56934308077001,57,5,0.7472647702407003,1828
src/main/java/<path_to_file>,17.703904086980828,67,5,0.6457142857142857,1050

hotgraph

hotgraph コマンドにて、同時に変更されやすいファイルのネットワーク図を出力します。こちらも hotspot と同様、ユニットテスト関連ファイルなどを除外するため、--allow-files および --ignore-files を指定しております。

また、Windows環境では --stop-retry を付与しないとエラーが発生するため、オプションを付与しております。

gilot hotgraph -i log-backend.csv --stop-retry -o hotgraph-backend.png \
  --allow-files 'src/main/*'
gilot hotgraph -i log-frontend.csv --stop-retry -o hotgraph-frontend.png \
  --allow-files 'packages/*' \
  --ignore-files '*/__tests__/*' '*.spec.ts' '*.stories.js'

それぞれの結果は、以下のようになりました。(ファイル名が含まれるため、ぼかしをかけています)

f:id:h-yamamoto_holmescloud:20200904172917p:plain
hotgraph-backend

f:id:h-yamamoto_holmescloud:20200904172938p:plain
hotgraph-frontend

同時に変更されやすいファイルが、同じ色の円で表示されます。

author

author コマンドにて、コミットした人ごとのコミット数や、割合を出力します。

デフォルトではトップ10人が出力され、それ以外の人は「Others」としてまとめられます。人数は -t 人数 で指定可能です。

-n 名前 で、出力画像右上にタイトルを追加できます。

plot と同様、backendとfrontend、両方合わせたものの3種類を出力してみます。

gilot author -i log-*.csv -o author-all.png -n all
gilot author -i log-backend.csv -o author-backend.png -n backend
gilot author -i log-frontend.csv -o author-frontend.png -n frontend

それぞれの結果は、以下のようになりました。(個人名が含まれるため、私とOthers以外はぼかしをかけています)

f:id:h-yamamoto_holmescloud:20200904175731p:plain
author-all

f:id:h-yamamoto_holmescloud:20200904175757p:plain
author-backend

f:id:h-yamamoto_holmescloud:20200904175831p:plain
author-frontend

info

info コマンドにて、各コマンドの解析元となる情報を、JSONで出力できます。

plot と同様、 -t オプションを指定できますが、gilot v0.2.4 では無視されてデフォルトの2週間で出力されるようです。

-o オプションは指定できないため、ファイル出力する場合はリダイレクトします。

gilot info -i log-*.csv -t 1w > info-all.json
gilot info -i log-backend.csv -t 1w > info-backend.json
gilot info -i log-frontend.csv -t 1w > info-frontend.json

以下のJSONが出力されます。タイムスロットが2週間になっています。

{
    "gini": 0.23784183100679956,
    "output": {
        "lines": 236045,
        "added": 62121,
        "refactor": 0.7368256052871274
    },
    "since": "2020-06-02T09:01:06.000000000",
    "until": "2020-09-03T17:01:01.000000000",
    "timeslot": "2 Weeks",
    // 以下省略

振り返り

それぞれの解析処理を実行してみました。いずれの解析も、 gilot log でログ出力しておけば後から実行できるため、CIと連携させて出力するのは難しくないと思います。

以下所感です。

plot

スポットで出力するだけでは、あまりメリットを感じませんでした。

1か月などの期間で定期的に出力し、大きな変化があれば原因を特定、必要があれば改善するなど、実際のプロダクト開発に利用することで意味が出てくるのではないかと思います。

(根本的なところを言うと、それぞれのグラフの意味をきちんと把握していないので、まずはそこから学習しないとです...)

hotspot, hotgraph

これらはファイル間の関連性、依存性を確認することができるので、スポットでも有用だと思います。

静的解析ツールなどによる複雑性の確認と組み合わせることで、リファクタリングの優先度が高いファイルの発見に使えそうだと思いました。

author

これはそのままコミット数になります。

見ていると面白いですが、同じチーム内でも各人のコミット粒度が同じとなることはなかなかないと思うので、単体では何かの指標として使いにくいかと思います。

info

それぞれの解析結果の元となる情報のため、より高度な利用方法になるかと思います。

ツールの習熟が進み、いずれかの指標を画像ではなくデータとして扱いたいときに、こうしたコマンドがあるのはありがたいと思います。

期間指定変更後の再plot

frontendから抽出する期間を2020/6/15以降に変更して plot してみたところ、コミット行数の上振れが解消されました。

backendも合わせて期間を変更してみます。

gilot log --full -b master -o log-backend.csv --since 2020-06-15 --full backend/
gilot log --full -b master -o log-frontend.csv --since 2020-06-15 --full frontend/

gilot plot -i log-*.csv -t 1w -o plot-all.png
gilot plot -i log-backend.csv -t 1w -o plot-backend.png
gilot plot -i log-frontend.csv -t 1w -o plot-frontend.png

結果は以下のようになりました。コミット行数の上振れがなくなり、グラフの上限値が適切な値になっています。

f:id:h-yamamoto_holmescloud:20200904215634p:plain
plot-all(期間変更後)

f:id:h-yamamoto_holmescloud:20200904215711p:plain
plot-backend(期間変更後)

f:id:h-yamamoto_holmescloud:20200904204505p:plain
plot-frontend(期間変更後)

最後に

Holmesではエンジニア・デザイナーを募集しております。ご興味がある方はこちらからご連絡ください。

lab.holmescloud.com

lab.holmescloud.com

課題解決のためにスキルマップ(星取表)を作成

はじめまして、Holmesでスクラムマスターの役割を担っているid:tomoya_misudaです。

今回は、スキルマップ(星取表)を実施したことをお伝えしたいと考えます。

組織が抱えていた課題

企業、組織としての成長過程で、組織を構成するメンバーには一定の流動性が伴います。
こうした中で、現時点で組織として足りないスキルが何か、について考えたことがきっかけでした。

  • チームで足りていない知識ってあるのか?
  • 自分たちに必要なスキルってなんだろう?
  • 他のメンバーのスキル、やりたいことはなんだろう?

問題を深く捉えるため、上記の問を自分自信に投げかけたことで、「メンバーのこと知らなかったな」という感想を持ちました。
特に、普段一緒に仕事をしているチーム以外のメンバーについては、わからないことだらけでした。

解決への模索

市谷さんカイゼンジャーニー、チームジャーニーを読むことで解決方法を探すことにしました。

www.amazon.co.jp

www.amazon.co.jp

チームジャーニーを読んでいる際、「チーム・ジャーニー 著者による本読みの会」に出席しました。市谷さんがスキルマップ(星取表)の良さを共有してくれました。私は「これだ」と感じました。 そこからは、本当に「スキルマップが自身のチームに必要か」を考察しました。

やると決めて、また自問自答

やると決めて、また自問自答で意味、実施方法、確認しました。

  • 「スキルマップをやる意味は?」
    → 課題のスキルの足りない箇所確認よりは、メンバーことを知ることで、コミュニケーションの向上とモチベーション維持が大切と設定しました。また、目標決めに役に立てばと考察しました。

  • 「スキルマップをやることの注意点はあるのか?」
    → メンバーには、素直に記載してもらうことを伝える必要がある。評価利用することもできるが、今回はメンバーの興味や自身が得意なことを見える化しようと決めました。

  • 「どんなスキルがあるだろうか?」
    → Holmesで利用しているスキルをメインで抽出して、Development、Operations、マネイジメント、プロダクトオーナー色々な観点からスキルを一覧化しました。

  • 「メンバー評価のスキル段階は?」
    → 各メンバーの評価軸を合わせることは、やらないことを決めました。結果、各自の自己評価で「◎:好き、◯:一人でできる、△:助けがあればできる、空欄:できない」回答してもらいました。ここは、メンバーに意見を求めて一番工夫しました。

スキルマップを作成

スキルマップを作成して、開発部のメンバーを招待して30分のタイムボックスで実施しました。アジェンダは下記の通りです。

  • やる目的
  • 記載方法
  • 全員で記載
  • まとめ

忙しい中、全員参加してくれました!

結果

メンバー間のコミュニケーションを手助けできました。「ここを得意としているんだ!」「憧れているメンバーのスキルはこんな感じなんだ!」色々な観点を生み出すことができました。また、採用へのスキル確認ができました。

まとめ

問題に対して解決方法は色々ある中で、今自身のチームに必要か?を自問自答することはとても大切で、私たちに合う形を考え実行しました。
スキルは、それぞれのチームで違うので合うかわかりませんが、スキルの項目を下記に記載します。
少しでもチームのコミュニケーションや目標共有の手助けができればと思います。

デザイン     
        UX設計
        UI設計
        User Story Map
        Mindmap
        ビジネスプロセスモデリング
        ワイヤフレーム
        画面設計
        アイコン作成
フロント        
        Storybook
        HTML
        CSS
        SASS
        Vue.js
        Nuxt.js
        Jest
        JavaScript
        JQuery
        Webpack
サーバー        
        Gradle
        Spring Boot
        Java
        Kotlin
        Python
        Groovy
        SQL
考え方       
        Atomic Design
        テスト駆動開発
        ドメイン駆動開発
        オブジェクト指向
        DB設計
        Git-flow
        スクラム
リリース        
    リリース手順検討作成  
        ECS リリース
        Elasticbeanstalk リリース
        Elasticseach リリース
        API Gateway
        RDS リリース
        コードリリース
テスト       
    テスト設計 
        サーバーサイドテスト設計
        フロントテスト設計
        負荷テスト
    テスト自動化  
        テストシナリオ作成
        python selenium
        selenium IDE
インフラ        
    AWS 構築、保守、設計    
        EC2 / ELB
        RDS for mysql
        ECS / ECR
        MQ
        Elasticbeanstalk
        Lambda
        Amazon Connect
        S3
        API Gateway
        Cloudfront
        Elasticsearch
        SES
        Route53
        Lightsail
    gitlab 運用保守 
        パイプライン作成
        unittest runner サーバーチューニング
        unittest Docker Image メンテナンス
    その他   
        apache / tomcat の middleware 構築、保守、設計
サポート・トラブルシュート     
    監視  
        Cloudwatch alarm / Lambda / SNS / Slack による監視構築
        ログ確認
        RDS SQLチューニング
プロダクト     
        仕様理解
        タスク出し
        デザインチェック
        コードレビュー
        バグ(障害)調査対応
その他       
        ファシリテーション
        1on1
        KPI
        PDCA
        セキュリティ
        ISMS

スキルマップを定期更新することで、コミュニケーション、メンバーの成長を実感できるチームを目指していきたいです。

おわりに

この記事で、チームのコミュニケーション、モチベーション維持に貢献できたらと考えます。 Holmesはエンジニア・デザイナーを募集しています 興味がある方はぜひこちらからご連絡ください!

lab.holmescloud.com

lab.holmescloud.com

REST APIのレスポンスステータスについて改めて考える

こんにちは。7月にHolmesにジョインした友野です。サーバーサイドエンジニアをしています。

今回はREST API実装時のHTTPレスポンスステータスについてです。
基本的なことですが、重要なことなので備忘録もかねて記事にしておきます。

余談ですが、Holmesでは秋口のUI/UXリニューアルに向けて開発を進めています。ゴールに向けて、複数のスクラムチームが並行して開発をしているため、各々のチームで経験に基づいた暗黙知による実装差分が稀に発生します。
都度共有もしていますが、エンジニアが増えてきた今だからこそ、「ちゃんと決めなきゃね」という話から今回の内容も改めてまとめておこうと思い立ちました。

利用するHTTPメソッド

GETPOSTPUTDELETE の4つです。リソースの更新はPUTで行い、PATCH は使いません。 べき等性を意識するという側面もありますが、なによりシンプルに実装を進めるためです。

レスポンスステータス

チームで話をするきっかけになったのが、このレスポンスステータスです。
正常時、GET200 OKPOST201 Createdを返すという認識は合っていたのですが、 PUTAPIを実装する際に、

  • 200 OKを返す
  • 204 No Contentを返す

の2つに意見が分かれました。 宗教戦争、とは言いませんが、様々なバックグラウンドを持つメンバーから成るチームだからこそあり得ることです。

定義がどうなっていたか、改めてRFCを確認してみます。

RFC7231 PUT *1

If the target resource does have a current representation and that representation is successfully modified in accordance with the state of the enclosed representation, then the origin server MUST send either a 200 (OK) or a 204 (No Content) response to indicate successful completion of the request.

リクエストが正常に完了したことを200 OK204 No Contentのいずれかで示さねばならないとあるのみでした。 これを踏まえて、開発チームではPUTで既存のリソースを更新する場合は、204 No Contentを返すと取り決めました。

200 OKではなく、204 No Contentを選択した理由は、特に返却する情報はないと考えたためです。 リソースが必要な場合は改めて取得し直すべき、と判断しました。
なお、リソースを作成する場合は明示的にPOSTを利用するので、PUTによるリソース新規作成はしません。

レスポンスヘッダー/レスポンスボディ

さて、そうするとレスポンスヘッダーとレスポンスボディについても明らかにしておいた方が良さそうです。 こちらもRFCを念のため確認した上で、特に意見も分かれなかったので以下としました。

RFC7231 POST
RFC7231 DELETE

  • 201 Createdを返却する場合
    • Locationヘッダーに作成したリソースのURIを合わせて返却する
    • レスポンスボディは不要
  • 204 No Contentを返却する場合
    • レスポンスボディは不要

まとめると、以下の通りです。

HTTPメソッド レスポンスステータス 備考
GET 200 OK 単一/複数リソース取得に利用する
POST 201 Created Location ヘッダーに作成したリソースのURIをセットする
レスポンスボディは不要
200 OK 複雑/組合せの条件などクエリパラメータではリクエスURIの文字数に懸念がある場合*2にリソース取得(検索)時にも POST を利用する
PUT 204 No Content 既存のリソースを更新する
レスポンスボディは不要
DELETE 204 No Content 既存のリソースを削除する
レスポンスボディは不要

Springによる実装イメージ

レスポンスボディを持たない実装イメージは以下の通りです。

  • 201 Created
@PostMapping("/api/tasks")
public ResponseEntity<Void> createTask(@RequestBody CreateTaskCommand command) {
    String taskId = createTaskService.handle(command);
    URI location = UriComponentsBuilder.fromUriString("http://example.com/api/tasks/" + taskId).build().toUri();
    return ResponseEntity.created(location).build();
}
  • 204 No Content
@DeleteMapping("/api/tasks/{taskId}")
public ResponseEntity<Void> deleteTask(@PathVariable("taskId") String taskId) {
    deleteTaskService.deleteWith(taskId);
    return ResponseEntity.noContent().build();
}

最後に

当たり前だと思っていたことが、わずかな思い違いが事故につながることも少なくありません。このような事故を未然に防ぐために、少しずつ明文化していきたいと思います。

Holmesでは現在エンジニアを募集しています。 興味がある方は是非こちらからご連絡ください!

lab.holmescloud.com

*1:当該RFCは執筆日現在で"PROPOSED STANDARD"ステータスです

*2:RFCでは最大文字数は定義されていないようですが、サーバーやブラウザの実装に依存するのを回避するためです

AWS App Mesh 導入のはまりどころとポイント

はじめに

弊社は、SPA化するためにフロントエンドとAPIを分離することにしました。それによってコンテナ間の通信状況とパフォーマンスをより簡単に把握したいニーズが生まれ、監視の高度化・インフラの安定化を目的として、AWS App Meshの導入を検討しました。
AWS App Meshとは、AWS上に存在するコンテナ間の通信を監視し、かつ制御できるサービスメッシュです。
aws.amazon.com 導入にあたって、はまったポイントとその解消方法を記載します。

構成

フロントエンドとAPIを分離した状態での検証をするために、以下の構成でApp Meshの設定を行いました。

  • 1層目 : Frontend Micro Service
  • 2層目 : Bff Micro Service (バックエンドAPI)
  • 3層目 : 各種 Micro Service 群

f:id:k-kitahara:20200805191413p:plain

はまったポイントその1. DBにつながらない

事象

APサーバにHTTPリクエストは到達したのですが、内部でエラーが発生してしまいました。
対象となるECSのコンテナにApp Meshの設定をしたことで、Envoyプロキシを全ての通信が通過するようになりました。 このEnvoyプロキシがTCP通信を全て遮断するため、APサーバからDBにつながらなくなってしまったようです。

解決方法

以下の手順で、Envoyに対してバイパスするポートを指定することで回避しました。

1. Amazon ECSのタスク定義から、「新しいリビジョンの作成」を選択。 f:id:k-kitahara:20200730183901j:plain 2. プロキシ設定から無視された出力ポートに、通信を許可したいポート番号を入力。 f:id:k-kitahara:20200730183910j:plain 3. 画面の一番下にある「作成」を選択。

タスク定義の無視された出力ポートに、2で入力したポート番号が表示されていればOKです。

はまったポイントその2. タイムアウトエラー

事象

ダウンロードやアップロードのような、比較的時間がかかる処理でタイムアウト(upstream timeout)が発生してしまいました。

解決方法

App Meshにデフォルトで設定されているタイムアウト時間は15秒だったため、以下の手順でタイムアウト時間を延長することで回避しました。

仮想ルータ側

  1. AWS App Meshの仮想ルータから、「編集」を選択。 f:id:k-kitahara:20200817172314j:plain
  2. Request timeoutIdle durationを任意の時間に設定。 f:id:k-kitahara:20200730193958j:plain
  3. 画面の一番下にある「保存」を選択。

仮想ノード側

  1. AWS App Meshの仮想ノードから、「編集」を選択。 f:id:k-kitahara:20200817172501j:plain
  2. Request timeoutIdle durationを任意の時間に設定。 f:id:k-kitahara:20200730195625j:plain
  3. 画面の一番下にある「保存」を選択。

仮想ノードと仮想ルータそれぞれの設定にあるRequest timeoutIdle durationの欄に、2で入力した値が表示されていればOKです。

最後に

どのエンドポイントに何秒かかったか、どのトラフィックが一番時間がかかっているかなどといった情報が表として出力されるので、非常にわかりやすくなりました!

クライアントが閲覧しているブラウザやデバイスの統計が出るので、ハイレベルな戦略を立てる場合の一つの材料にすることができます。
また、エンドポイントが呼ばれた回数が把握でき、どの機能がよく使われているのかがわかるようになるので、フィードバック開発の意思決定に役立てることもできます。


Holmesはエンジニア・デザイナーを募集しています
興味がある方はぜひこちらからご連絡ください! lab.holmescloud.com lab.holmescloud.com

Pixelaを使ってデプロイを可視化してみた #pixela

こんにちは、id:c-terashimaです

Pixela とはGitHubの草のように数値を可視化するツールです

pixe.la

弊社はGitLab CIを利用してmasterブランチにソースがマージされると自動的にステージング環境へデプロイが行われます
ちょっとしたことではありますが、ステージング環境へのデプロイを1日どのぐらい行っているのか Pixela を使って数えてみることにしました

手順

ユーザ登録

Pixelaにアカウントを作成します

$ echo `uuidgen`
$ dummy-uuid
$ curl -X POST https://pixe.la/v1/users -d '{"token":"dummy-uuid", "username":"holmes", "agreeTermsOfService":"yes", "notMinor":"yes"}'

Request Body

Key description
agreeTermsOfService 利用同意
notMinor 未成年確認

グラフ作成

デプロイ回数を描画するグラフを作成します

$ curl -X POST https://pixe.la/v1/users/holmes/graphs -H 'X-USER-TOKEN:dummy-uuid' -d '{"id":"staging","name":"deployCounter","unit":"deploy","type":"int","color":"shibafu"}'

Request Body

Key description
unit 単位
type 数量の種類(int or float)
color 芝生の種類 (shibafu (green), momiji (red), sora (blue), ichou (yellow), ajisai (purple) and kuro (black))

カウントアップ

以下のAPI呼び出しをCIに組み込むことで自動的にカウントアップが行われます

$ curl -X PUT https://pixe.la/v1/users/holmes/graphs/production/increment -H 'X-USER-TOKEN:dummy-uuid' -H 'Content-Length:0'

実際にできたやつ

f:id:c-terashima:20200720173604p:plain

あ、だれか土日にデプロイしてる!!
なんてことも可視化され、休日にもデプロイされていることがわかりましたw
今回はステージングのみですが、本番環境も可視化してセールスチームなどに共有してあげればいつリリースしたか振り返ることにも利用できそうですね

最後に

とっても容易に可視化することができました
芝生が見慣れているというのもあるかもですが視覚的に見やすくわかりやすいですね
デプロイだけではなく定量的に取得している数値などがあれば Pixela で可視化してみてはどうでしょうか?


Holmesはエンジニア・デザイナーを募集しています
興味がある方はぜひこちらからご連絡ください!

lab.holmescloud.com

lab.holmescloud.com

スクラムチームに新しい仲間が入るので、ドラッカー風エクササイズによるチーム期待値調整ワークをやってみた

こんにちは。Holmesでスクラムマスターをしている吾郷です。

今回はチームビルディングの一環として行ったドラッカー風エクササイズについて振り返っていきたいと思います。

前提・状況

現在弊社では、毎月会社に数名の新しい仲間が入ってくれています。嬉しいことに、半年一緒にやってきたスクラムチーム(開発メンバー4人)にも、7月から新しい仲間が1名加わってくれることになりました。既存のメンバーはすごく楽しみにしています。

また、タックマンモデルを参考として、チームの成長段階から考えてみましょう。

f:id:seiseiholmes:20200717112638j:plain
仕事ができる人は「正しい衝突」が超得意!から抜粋

半年ほど活動している自チームの段階は混乱期〜統一期といったところでしょうか。チームメンバーが変更になることで、再度形成期を過ごしながらチームを作り上げる必要があります。

目的

そこで、半年やってきたチームの練度をできるだけ保ちながら、チームにおける不安や緊張を緩和し、スムーズに新しい仲間の受け入れを行いたいです。 また、形成期を迎えるチームにおいてお互いのスキルや価値観、期待値を共有・すり合わせを行うことで、今後のチーム活動の基盤とし、成長への後押しとしたいです。

ドラッカー風エクササイズとは

ドラッカー風エクササイズは、アジャイルサムライで紹介されたチームにおける期待をすり合わせるための手法です 具体的には、以下の4つの質問に答えます。
①自分は何が得意なのか?
②自分はどうやって貢献するか?
③自分が大切に思う価値は?
④チームメンバが自分に期待していることは?

また、今回はカイゼン・ジャーニーを参考として5つ目の質問を追加することにしました。質問は以下です。
⑤その期待はあっているか?
カイゼン・ジャーニーで言及されていますが、最初の4つの質問は自分に視点を置いていましたが、5つ目の質問ではメンバーからの回答となります。メンバーからの回答はよりよいフィードバックとして、自信の期待値の調整ができます。

今回は期待値の共有にとどまらず、期待値のすり合わせまで行いたいと考え、質問を追加しました。注意としては、期待値の差異の受け取り方は人によってはマイナスにとらえてしまう場合もあるかと思います。今回は差異がわかることは良いことで、すり合わせのきっかけになることが大事である旨をワークの冒頭で丁寧に説明しました。

実施方法

今回は、リモートワーク状況ということで、オンラインホワイトボードのMiroを使用して行いました。 タイムボックスは一時間とします。

流れは下記です。

  1. チェックイン(実施日がたまたま7月7日でしたので七夕を題材にして行いました。)
  2. 4つの質問にそれぞれ回答2分ずつで回答を入力(質問×2分)
  3. 各メンバーに補足してもらいながら記入内容を共有(メンバー×2分)
  4. 各メンバーの記入内容について質問・深堀り(10分)
  5. 各メンバーの最後の質問に対して、自分の期待とあっているかどうか三段階で評価(3分)
  6. 評価結果についてすり合わせ(残り時間)

また、ワーキングアグリーメントとして以下を設定し最初に共有しました。

・メンバーを絶対に否定しない(否定はしないけど、意見はありです。)

実施結果

以下のような表が出来上がりました。

f:id:seiseiholmes:20200717122631p:plain
結果表
横列が質問、縦列をメンバーとしています。
また、期待の合致度を表す星のカラー定義は以下としています。

  • 青色・・・いい感じで合致している
  • 黃色・・・まあまあ合致している
  • 赤色・・・ちょっと違う

途中で出てきたコメントに関してはオレンジや濃い黄色、青色の付箋で追加しております。
また、画像を見ると気づくかもしれませんが、期待の合致度を表す星についてはメンバーによって青が多めの方、黄色が多めの方とそれぞれ違いが見えて面白かったです。

チームメンバーの感想(一部抜粋)

KEEP
・普通に楽しい会だった
・スプリントでの良い息抜きになった
・メンバー間のコミュニケーションが更に活発になった気がする
・新しく入ったメンバーが他メンバーを把握するのに良いと思いました
・自分自身の見直しが出来た

TRY
・POも声をかけるべき
・コンパクトバージョンでもいいのでQ毎にやってもよいと思いました
・発表者毎に質疑するともっと良さそう

このように嬉しい声がありました。また、カイゼン案などの意見もくれたので、参考にしながら次回以降のTRYとして実践していこうと思います。

発表者毎に質疑するともっと良さそう

こちらに関しては、各メンバーの記入内容についての時間をまとめて取ってしまったため、前の時間で最初の方に共有してくれた方の内容を思い出しにくく深堀りづらいという状況が生まれたためです。一人ひとりに焦点を当て、チームで共通認識を持てる方が良いと思いますので、要カイゼンとしました。

POも声をかけるべき

また、こちらに関してですが、スクラムを知っている方はご存知の通りスクラムチームは、PO・SM・開発チームで構成されています。しかし、最近スクラムイベントはまだしも、こういったチームビルディングイベントになるとPOの招待を忘れがちになる現状があります。非常に痛いです。POもよく嘆いております。そこで、チームメンバーとPOの架け橋となるべきSMが、POのことを忘れないようにPOの写真を机の横に置いておくTRYをやってみようかなと思った次第です。

更に、今回もう一つのポイントであった新しい仲間からの感想も抜粋させていただきます。

・メンバーの個性(落ち着きと秩序と盛り上げ)や、フロントとバックエンドのバランスがいいなと思いました。
・みんなが謙虚で、承認し合う雰囲気は素晴らしいです。
・自分が考える期待されていることと、メンバーから期待されていることが近しく、やりたいことが受け入れられており、チームで動く土台にりました。

ということで、なんかいい感じですねΣ(゚∀゚ノ)ノキャー 実施してよかったです!

感想

前提として、スクラムにおいてチームメンバーが変更されることはあまり良しとされておりません。しかし、新しい仲間が加わることによる新しい風(経験、知識、観点)はチームにとって新鮮さを保ち続けるいい要素になります。また、新しいチームを作り上げていくという課題を乗り越えることで一層チームとして成長できるのではないかと考えております。とはいえ、頻繁な変更(ここでいう頻繁の定義はチームや会社の状況によります)を行うことによるチームへの負荷というもの存在しますので、状況を判断してチームの変更可否を決めていくのがいいかと思います。

また、今回のワークで加筆すべき良かった点としては、メンバー同士の期待値のすり合わせができたというのはもちろんのこと、スクラムマスターとしてチームと接していた自分自身への期待値・評価のすり合わせも行うことができたということです。これまでは見えにくかったチームから自分への評価を聞けたことは、今後の活動を行う上でも大きな後押しとなると思います。

チームビルディングに迷っている方、スクラムマスターとしての成果に不安がある方は是非おすすめします!

最後に

Holmesはエンジニア・デザイナーを募集しています
興味がある方はぜひこちらからご連絡ください!

lab.holmescloud.com

lab.holmescloud.com

AWSでWebSocketのネットワーク構成を考えてみる

Holmesでエンジニアをしているid:w-miuchiです。

先日弊社のサービスでリアルタイム通知の構築がトピックに上がりました。
リアルタイム通知の手段としてWebSocketに着目し、そのネットワーク構成を考えてみました。

今回はその考えた中から構成案をいくつかピックアップして紹介します。

条件

考える上で、以下を条件としました。

  1. データベース(Amazon RDS)の更新をきっかけにし、エンドユーザーに通知を行う
  2. 負荷分散を可能とする
  3. 仮定としてWebSocketコネクション情報はAmazon ElastiCache for Redisを利用

想定されるトラフィック量の算出も必要とはなりますが、今回は現在のHolmesのサービスと同じ量と仮定します。

注意

本内容は構成案であり、検証や実装は行っておりません。
構成内容は弊社SREに確認済みです。

利用サービス

今回の条件で利用する(できる)サービスを洗い出したいと思います。

Routing Application DataStore Cache
ELB (ALB, CLB)
API Gateway
ECS
EC2
Lambda
RDS
DynamoDB
Redis (ElastiCache)

こちらを元に組み合わせて構成を考えます。

構成案

1. ALB + ECS + RDS + ElastiCache for Redis

f:id:w-miuchi:20200703173730p:plain
構成1

ALB(Application Load Balancer)を利用する方法です。

ALBはパスベースルーティングが可能なため、例えば/websocketというパスで切り分けることができます。
またサブドメイン(例:websocket.xxxxxx.com)で切り分けるのであればCLB(Classic Load Balancer)でも可能です。

上記ではECS(Amazon Elastic Container Service)ですが、EC2でも問題はありません。WebSocket専用のサーバーを用意するのも有効かと思います。

処理としてはサーバーでElastiCacheのRedisにconnectionを保存しハンドシェイクします。
サーバーはデータベースにポーリングし更新通知を受け取ります。
ElastiCacheのRedisに保管されたSocketのconnectionからエンドユーザーに通知します。

非常にシンプルな構成で、弊社サービスではすでにALBを利用しているため比較的に導入しやすいです。 正直なところ弊社サービスを考えるとこの構成がベストプラクティスと考えます(笑)

メリット

  • 現サービスと同じ構成のため導入しやすい
  • コスト計算が行いやすい

デメリット

  • ポーリングによってRDSの負荷がボトルネックになる可能性があり(Socketで利用するサーバ台数を制限するなど検証が必要)

2. ALB + Lambda + DynamoDB + ElastiCache for Redis

f:id:w-miuchi:20200703173734p:plain
構成2

構成1との違いは2点です。

1点目はALBのターゲット先をECSからAWS Lambdaにしています。
WebSocketの通知だけであれば処理は軽量でAWS Lambdaでも可能かと考えます。

2点目はデータベースの更新をAmazon DynamoDBにし、Lambdaでイベントを受け取っている点です。

Lambdaを利用するためサーバーの負荷分散を任せることが可能です。

メリット

  • Lambdaというマネージドサービスを利用するため負荷分散が容易

デメリット

  • DynamoDB, Lambdaのコスト計算が必要

3. API Gateway + Lambda + DynamoDB + ElastiCache for Redis

f:id:w-miuchi:20200703173738p:plain
構成3

構成2との違いはALBをAmazon API Gatewayに変えています。

ステートフルなフロントエンドとして、WebSocket API を作成できます。

API Gatewayペイロードサイズやリクエスト数等の制限をかけたいならこちらがおすすめです。
またWebsocketをServerlessのサービスとして独立させることが可能です。

メリット

  • Lambdaに加えAPI Gatewayというマネージドサービスを利用するため負荷分散が容易
  • API Gatewayの制限が活用できる

デメリット

  • API Gateway, Lambda, DynamoDBのコスト計算が必要

4. API Gateway + Lambda + RDS for PostgreSQL(RDS Proxy)

f:id:w-miuchi:20200703173741p:plain
構成4

こちらはAmazon RDSにPostgreSQLを利用した場合です。

PostgreSQLでは通知を受け取る機能(NOTIFY/LISTEN)があり、こちらを利用します。 接続にはAmazon RDS Proxyを利用します。
RDS ProxyはLambdaを同じVPC内に配置することでデータベースとの接続をプールすることが可能です。 Lambdaが起動するたびに発生していたデータベースとの接続を緩和します。

ただし、最大のネックがRDS Proxyがプレビューであること...と本記事を書いている時にRDS ProxyがGAになりました!

https://aws.amazon.com/jp/blogs/aws/amazon-rds-proxy-now-generally-available aws.amazon.com

GAになったばかりのためこちらはかなり検証が必要です。

メリット

  • マネージメントサービスにおける負荷分散が利用できる
  • RDBPostgreSQLの場合はそのまま使うことができる

デメリット

  • RDS ProxyがGAになったばかりで、コストもかかる

最後に

いかがだったでしょうか。

RDS Proxyを利用した構成はかなりチャレンジングですが、個人的興味で加えさせていただきました!
今後は実際に構築し検証も行ってみたいと考えています。 その結果はまた記したいと思います。

Websocketの導入検討をしている方の一助になりましたら幸いです。


Holmesはエンジニア・デザイナーを募集しています
興味がある方はぜひこちらからご連絡ください!

lab.holmescloud.com

lab.holmescloud.com