メドピア開発者ブログ

集合知により医療を再発明しようと邁進しているヘルステックカンパニーのエンジニアブログです。読者に有用な情報発信ができるよう心がけたいので応援のほどよろしくお願いします。

Nuxt 3 への移行に Nuxt Bridge を使うのはいかが?

こんにちは!フロントエンドエンジニアの土屋 (@tutti2612) です。

いよいよ Nuxt 2 の EOL が迫ってきましたね。

nuxt.com

先日、弊社でもとあるプロダクトの Nuxt 3 への移行を完了させました。

メドピアでは既に複数のプロダクトで Nuxt 3 への移行を行ってきましたが、今回の移行では今までとは違ったアプローチを取りましたので、その詳細をお伝えしたいと思います。

これから Nuxt 3 への移行を考えている方にとって、少しでもお役に立てれば幸いです。

今回の移行の特徴

今回の移行の特徴として、以下の2点が挙げられます。

  1. Nuxt Bridge の使用
  2. 積極的な新機能開発を行いながらのビッグバンリリース

それぞれ解説していきます。

Nuxt Bridge の使用

今回の Nuxt 3 移行における一番の特徴は、Nuxt Bridge を使用したことです。

Nuxt Bridge とは、Nuxt 2 で Nuxt 3 の機能の一部が使えるようになるライブラリです。これを使うことで、Nuxt 3 への段階的な移行が可能になります。 nuxt.config.ts でフィーチャーフラグを切り替えることで、Nuxt Bridge が提供する機能を簡単に有効/無効化することができます。 これにより、移行作業中に必要な機能を段階的に有効化し、Nuxt 3 の機能を試しながら安定した環境を維持することができます。

nuxt.config.ts

Nuxt Bridge を使った移行手順については、Nuxt Bridge のコアコントリビュータである wattanx さんのスライドや、Nuxt 公式のマイグレーションガイドで詳しく紹介されています。これらのリソースを参考にすることで、スムーズな移行を実現することができます。

nuxt.com

積極的な新機能開発を行いながらのビッグバンリリース

もう一つの特徴として、今回の移行では積極的な新機能開発を行いながらのビッグバンリリースを実施しました。

どのくらいのビッグバンリリースかというと、このくらいの規模になります。

リポジトリのほぼ全てのファイルに変更を加えています。

なぜこのようなビッグバンリリースになったかというと、このプロダクトは自動テストをあまり書いておらず、動作確認は手動で行う必要があったためです。Nuxt Bridge を使用しても、Nuxt 3 の破壊的変更を適宜リリースするには手動での動作確認に多大な工数がかかると判断しました。移行の前に自動テストを拡充することも考えましたが、それもまた多大な工数が必要で、EOL までに移行を完了するスケジュールが立てられませんでした。

さらに、成長途中のプロダクトであるため、新機能開発を止めることができませんでした。新機能の動作確認にも多くの工数が必要だったため、Nuxt 3 移行の細かなリリースによる動作確認に十分な工数を割くことができませんでした。

これらの点を考慮し、ビッグバンリリースを選択しました。

具体的には、マイグレーションブランチを用意し、Nuxt 3 移行はそのブランチ上で行いました。新機能開発での変更箇所は適宜マイグレーションブランチにマージしていくことで、develop ブランチとの乖離を防ぎました。

成功の要因

積極的な新機能開発を行いながらのビッグバンリリースというリスクのある移行方法でしたが、無障害で移行を完了することができました。

成功の要因としては、以下の点が挙げられます。

  1. Nuxt Bridge の使用
  2. 週 1 回の定例ミーティング
  3. エンジニア以外にも協力してもらった手厚い手動テスト
  4. 巨人の肩に乗ることができた

これらもそれぞれ解説していきます。

Nuxt Bridge の使用

成功の要因の一つとして、今回の移行の特徴でもある Nuxt Bridge の使用が挙げられます。

ビッグバンリリースを行ったため、段階的に移行ができる Nuxt Bridge のメリットが無いのでは?と思われるかもしれませんが、実際にはそうではありません。Nuxt Bridge を使用して段階的に移行することで、Pull Request の粒度を細かくすることができました。これにより、コードレビューのしやすさが格段に向上しました。

粒度の細かいPRの例

また、各破壊的変更の動作確認を Nuxt 2 が動いている状態で行えることも大きなメリットです。Nuxt Bridge を使わない場合、すべての破壊的変更に対応してからでないと動作確認ができませんが、Nuxt Bridge を使用することで、各変更の影響を個別に確認しながら進めることができました。

このように、Nuxt Bridge を活用することで、段階的な移行が可能となり、結果として無障害での移行に大きく貢献しました。

週 1 回の定例ミーティング

移行作業はのべ 3 人のエンジニアで行いましたが、新機能開発と同時進行だったため、3 人が常に移行作業に専念できるわけではありませんでした。

しばらく移行作業から離れていたメンバーが状況を把握できるように、移行関係者で週1回の定例ミーティングを実施しました。このミーティングは「Nuxt 3 作戦会議」と題し、移行作業の進捗状況や課題を共有しました。タスクの管理には GitHub Projects を用い、進捗状況を可視化していました。

GitHub Projects のロードマップ

このミーティングのおかげで、各エンジニアのタスクの進捗と次のステップが明確になり、効率的な作業を促進しました。

エンジニア以外の協力を得た手厚い手動テスト

無障害での Nuxt 3 移行に成功した要因のひとつに、エンジニア以外の協力を得た手厚い手動テストの実施があります。

先に述べた通り、このプロダクトは自動テストの量が少なく、手動テストに頼らざるを得ませんでした。エンジニア視点のテストだけだと、抜け漏れが発生する可能性を拭いきれませんでした。そこで、PdM やカスタマーサクセスなど、エンジニア以外のメンバーにも手動テストに協力してもらいました。

これにより、複数の視点から手動テストを実施することができ、無障害での移行に大きく貢献したと考えています。

巨人の肩に乗ることができた

最後に、この移行を成功させた要因として欠かせなかったのは、社内に既に複数の Nuxt 3 移行を成功させていたエキスパートたちがいたことです。彼らの経験と知見が社内に蓄積されていたおかげで、スムーズな移行が可能となりました。

移行の注意点を事前に彼らから聞くことができ、さらに彼らが残してくれたドキュメントを参照することで、予想される落とし穴を回避することができました。

これらの貴重なドキュメントの一部は、弊社ブログや Speaker Deck で公開しています。

tech.medpeer.co.jp

tech.medpeer.co.jp

tech.medpeer.co.jp

それぞれ異なるアプローチを紹介しているため、これから Nuxt 3 移行を考えている方はぜひ一読することをおすすめします。あなたのプロダクトに最適な手法が見つかることでしょう。

こうすれば良かった

無事に Nuxt 3 への移行が成功しましたが、振り返ってみると「こうすれば良かった」と思う点もあります。

今回の移行では、Nuxt のバージョンが 2.14 の状態から Nuxt 3 に移行したのですが、少なくとも 2.17 にアップデートしてからビッグバンリリースを行うべきだったと感じています。

マイグレーションブランチに develop ブランチをマージした際、コンフリクトの解消に非常に苦労しました。Nuxt 2.17 にアップデートしていれば、Nuxt で使用している Vue のバージョンが 2.7 に上がり、CompositionAPI が Vue 本体から提供されるため、コンフリクトの発生数を減らせたと考えています。

おわりに

メドピアの Vue 3 / Nuxt 3 移行の集大成として臨んだこのプロジェクト。 なんとか EOL までに Nuxt 3 に移行することができたと思ったのも束の間、Nuxt 4 のリリースが間近に迫っています。

nuxt.com

Nuxt 4 への移行においても、今回の Nuxt 3 移行で得た知見は大いに役立つはずです。これまでの経験を活かし、スムーズな移行を目指していきましょう。


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら medpeer.co.jp

■エンジニア紹介ページはこちら engineer.medpeer.co.jp

■メドピア公式YouTube  www.youtube.com

■メドピア公式note
style.medpeer.co.jp

開発生産性の改善から1年経過したチームで考えていること

こんにちは。エンジニアの保立(@purunkaoru) です。

僕のチームでは、開発生産性の改善に取り組んでから1年経過しました。 開発生産性の改善系の記事やノウハウは世間によく出ていますが、1年経過した今、開発生産性に対してEMの立場で何を考えているかを言語化します。

チームメンバーの構成は、執筆時で以下の通りです。

  • フロントエンド: 5名
  • サーバーサイド: 9名
  • モバイルアプリ: 3名
  • EM(保立): 1名

弊社では、Findy Team+ を導入し、開発生産性を見えるようにしています。 まずはFindy Team+の画面を見ながら、改善結果を見ていきます。

  • 直近1年間

  • 直近2年間

直近2年で見ると、後半1年で生産性が改善されており、その改善が一定維持できていることがわかります。

ちなみに、このサイクルタイム分析について、数値的な目標を今まで一度も掲げてきませんでした。 どうしても指標に対する数値目標を掲げてしまうと、それに対するハックが進んでしまい、本質的な改善にならないと感じていたからです。チーム内では、開発に時間がかかる・レビューに時間がかかると誰かが感じた時に、Findy Team+の定量的な数値を見てチームに改善を促すコミュニケーションを取るケースが多かったです。

また、Four Keysの分析(Findy Team+でいうDevOps分析)は、botでリリースPRを作っているせいか、うまく集計できないので分析対象から外しています。 社内には、Four Keysの分析をOKRに組み込んでいるチームもあります。

それでは、ここから本題に入り、開発生産性の改善が進んでから1年経過して、何をチェックしているか記載していきます。

1. チーム別のアウトプット量の推移や負荷の確認

エンジニアチームとして、アウトプットの量の推移を確認することは不可欠です。アウトカムとしてのKPI(サブKPI)への貢献もチーム全体で把握していますが、開発に関わるアウトプット量の変化にも注目しています。

アウトプットの量は「1人あたりのプルリクエスト数」と「1プルリクエストあたりの平均変更行数」で測っています。以下の画像の棒グラフ(薄い色の方)で示されている「1人あたりのプルリクエスト数」は、昨年に比べて約20%増加していることが分かります。

一方で、「1プルリクエストあたりの平均変更行数」に関しては、別の画面で確認する必要がありますが、月ごとの推移を1画面で見る方法を見つけられなかったため、ここでは画像の提供は省略します。僕のチームの平均変更行数は、月ごとにばらつきはありますが、過去と比べて増加または減少した傾向は見られませんでした。

ここから読み取れることは2つあります。

1つ目は、チーム全体のアウトプット量が増加していること。これは、要件定義や設計のコミュニケーションが整備され、スムーズになったこと、またエンジニア自身の技術力やレビュー能力の向上が背景にあります。

2つ目は、12月にプルリクエスト数が急増しており、稼働時間が多い状況になったこと。主な要因は体制変更にありました。新しいチーム体制での見積もり精度が落ち、稼働が厳しくなってしまいました。11月末にはプルリクエスト数が増加する傾向にありましたが、対応が12月初旬まで遅れたことは、データチェックの不足や閾値設定の不備が原因です。以降、プルリクエストの数の増減にはこまめに目を光らせるようになりました。

このように、定量的なデータを活用して、チームの生産性と負荷のバランスを定量的な指標をもとに管理しています。

2. サイクルタイム分析による開発サイクルの確認

開発サイクルの改善を行ってから1年が経過し、サイクルは成熟しており、サイクルタイムの増減は限定的です。 サイクルタイムに大きな変動が生じる主な要因には、大規模な機能のリリース、メンバーの交代、チーム体制の変更、施策の追加や削除などがあります。これらの要因は、開発サイクルが改善されるか、逆に悪化するかを事前に予測できます。

たとえば、2024年4月から新しいメンバーが加わり、全エンジニアにメンターを配置する制度も導入しました。これにより、教育やMTGに費やす時間が増えました。このような新しい施策を実施したにもかかわらず、サイクルタイムや1人あたりのプルリクエスト数に変化が見られない場合、新たに増えた教育や会議の時間を考慮せずに見積もりを行い、チームメンバーが無理してタスクを完了させている可能性が考えられます。

そのため、新しい施策を導入する際には、いつごろから数値が改善するか、あるいは悪化するかを予測し、実際にその通りになっているかを後から確認するようにしています。

3. 十分な質のアウトプットが出せる量を超えてアウトプットをしていないかの確認

多くのサービスや機能を一人で担当することは効率が悪くなるとされています。エンジニアの世界でも、「チームトポロジー」などの書籍を通じて、シンプルで効率的な組織構造の重要性が説かれています。

同様に、一人が多数のプルリクエストやチケットを抱えると、対応を忘れてしまったり、ひとつひとつの作業に対する注意力が散漫になることがあります。チームによっては、レビュー待ち状態やテスト待ち状態のプルリクが放置されてしまう事象があると思います。

例えばメンバークラスのエンジニアが、タスク管理と開発の両方を行う役割に移行した場合を考えてみます。当然、タスク管理の責任が増えるため、割り当てられるチケット数やプルリクの数は自然と減少すべきです。しかし、変更前と同じ量を割り当ててしまうケースがよくあります。また、チームメンバーが増えた場合も、タスク管理の工数は増えますが、チームの増減を考慮せずにチケットを割り当てがちです。そのため、各人の役割に応じたタスク量を適切に考慮し、負荷を調整することが必要です。

現在、負荷量は「1日あたりのプルリク数」×「コミットからマージまでの日数」という計算式で把握しています。単純な「1日あたりのプルリク数」や「チケット消化数」では、プルリクやチケットの内容による重さを正確に反映できません。そのため、軽いプルリクはコミットからマージまでの時間が短く、重いプルリクは時間がかかると見込んで、この計算式を採用しました。

この計算式で算出される負荷の量を、各メンバーが理想的に対応できる数値と比較し、適切かどうかをチェックしています。自分自身の場合、集中的にプレイヤーとして活動できる時期は「18」が上限ですが、10名程度を管理していた際は「6」が限界でした。ただし、個人の生活リズムやその他の業務負荷により、「コミットからマージまでの日数」は変わるため、他人と比べるよりも過去の自分自身と比較して閾値を設定しています。

上記の例だと、 「1日あたりのプルリク数」は、52PR / 20営業日 = 2.6PR/営業日 となります。 「コミットからマージまでの日数」は、(2.5時間 + 8.5時間) / 8時間 = 1.4時間弱となります。 (「8時間」は、1日あたりの稼働時間です) 負荷量(「1日あたりのプルリク数」 * 「コミットからマージまでの日数」)は、2.6 * 1.4 = 約3.6 となります。 安全ですね。

この指標は改善が必要かなと思いつつ、ひとりひとりの負荷をアクティビティベースに定量的に確認する術が無く、今はこの方法で管理しています。

4. 新しいメンバーが機能しているか・無理していないかの確認

オンボーディング施策の一環として、新たにチームに参画したメンバーが機能しているか・無理していないかも確認しています。これは、主に業務時間で見ていますが、徐々にやれることが増えているかという点で、プルリク数・プルリクに対するコメント数・レビュー数などでも確認しています。

特に多いのが、急激に頑張ろうとしてプルリク数とレビュー数が急激に伸びているケースです。このケースでは、1プルリクあたりに対するレビューコメント数も多くなる傾向があり、レビュワー・レビュイーともに疲弊するケースがあります。こういった場合は、目標を落として、その分ペアプロをしたり、レビューコメント数が少なくなるための施策を一緒に考えます。

5. サービスの障害に関する確認

最後に、Findy Team+から離れた場で開発生産性に関して確認している数値について説明します。

サービスの障害を未然に防ぐため、自動テストだけでなく、エンジニアによる手動テストやプロダクトマネージャー、QA、CS担当者の手動テストも行っています。これらのテストにかかる期間や発見されたバグの数を記録し、各々の閾値を設定しています。もちろん障害の発生件数も確認していますが、障害発生前の手戻りやバグ検出に伴う工数も管理し、減少させる努力を続けています。これらの数値は品質管理の文脈で語られることが多いですが、結合テストや受入テストの工程の工数が減ると開発生産性は上がるので、今回の記事にも取り入れました。

この取り組みは、今期から始めたばかりですが、既に一定の成果が見られ、良い施策であったと感じています。

まとめ

数値化による生産性の管理は、チームのパフォーマンスや成長を明確に追跡することができ、またチームの負荷も把握することができます。これにより、客観的なデータに基づいて意思決定や評価を行うことができます。一方で、一度数値化してしまうと、数値を良くすることに目を向けすぎて、本質的な改善にならないケースもあります。そのため、前提を疑いながらウォッチしていくことが大切だと考えています。

今回記載した開発生産性の改善から1年経過したチームで考えていること・見ていることについて、参考になれば嬉しいです。メドピアの開発者ブログでは、技術的なことやチームマネジメントなど、参考になりそうなことを発信しているので、是非ブックマークをしていただけると嬉しいです。


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら medpeer.co.jp

■エンジニア紹介ページはこちら engineer.medpeer.co.jp

■メドピア公式YouTube  www.youtube.com

■メドピア公式note
style.medpeer.co.jp

#RubyKaigi 2024 セッションレポート

サーバーサイドエンジニアの内藤(@naitoh) です。

RubyKaigi 2024に参加されていた皆さん、お疲れ様でした。 RubyKaigi のセッションの中で印象に残った発表をご紹介します。

RubyKaigi 2024 セッションレポート

タイムテーブル

タイムテーブルは以下から確認できます。

rubykaigi.org

Namespace, What and Why

今回のRubyKaigi で非常に気になっていたセッションの一つです。

  • アプリケーション、ライブラリをある空間の中でライブラリを読み込み、他の空間から隠す。
  • 空間の中で定義されたメソッドを別空間から呼び出すこと
  • 別空間から呼び出されたメソッドは、元の空間内で動作すること

という感じで複数のバージョンのライブラリに依存した場合のコンフリクト発生を解決するのが Namespace とのことで、内容が整理されておりわかりやすかったです。

Namespace "on read" ということで、 既存の gem をそのまま使いたい が特徴で、"on write" だと、Namespace を使うときに宣言して使うアプローチ(例: 別言語, python)になり、これだと既存の gem の対応が必要になるので、なるほどと思いました。

Namespace があると 1つの Ruby プロセス上で、複数のアプリケーションサーバーを動かすことが可能になり、コンテナレスで開発環境を構築するのが容易になりそうとのことで、柔軟性高いなーと感じました。

speakerdeck.com

It's about time to pack Ruby and Ruby scripts in one binary

実行ファイル一つで実行できるOne Binary 形式の話です。 Ruby の One Binary 用途として、Rubyプログラムを配布したいときが想定されており、 通常の Ruby スクリプトをそのまま配布した場合、配布先のユーザーの Ruby 環境が古いなど、期待しないバージョンの環境の場合だと動作しない問題を解決できるとの事。 既存の one binary ツールには下記の課題があるため、kompo gem を作ったとの事です。

  • Ruby 3.0 未満のサポート
  • Ruby にパッチが必要
  • Windows のみサポート
  • 一時ファイル書き込みがある

クロスコンパイル未対応の課題はありますが、native(C拡張 gem?) にも対応してるそうなので、使い勝手が良さそうですね。

speakerdeck.com

Ruby Committers and the World

毎年楽しみにしている、Ruby Committers and the World です。

今年は下記の内容が議論されていました。

  • #frozen_string_literal: true をデフォルトにする話
    • "" をバッファに使うケースは多いので、+"" にすれば良いのはわかるが手間が増える。
    • Quine で 1文字増えるのは、それだけで厳しい。
    • YJIT には効果ありそう
    • Ractor は Frozen したい
    • 型は他言語の静的方向の流れとは逆張りしたのに、#frozen_string_literal: true は他言語と同じ immutable の方向。

というような議論になっていました。 Ruby 3.4.0 preview1 はデフォルト有効になっているけど、引き続き議論中という流れでした。 個人的には性能UPに繋がりそうなのでデフォルト有効は賛成ですが、3.4 での変更ではなく 4.0 でのメジャーアップデート時の変更だとわかりやすくていいなと思いました。

  • Embed RBS

YARDにも型があるぞということで、整合性をとるために YARD → RBS 変換できるといいねという話がありました。

個人的には別ファイルだと型は書かないだろうなという感じですが、メソッドのすぐ上に書けるなら型を書くのもありかなという感じです。

  • GNU autotools を cmake に変更したい
  • (Python のように)GVL を取りたい
  • async/await の usability の話
    • async/await をいっぱい書くのは、書きにくいのでは
    • 最初から、対象のメソッドに async/await が必要ってわかっていて書けているのか?
    • 後から、必要になって async/await を書くのは bad 体験
  • Golang の defer が欲しい話
    • ネストを深くなるのを回避できる
    • いい文法があれば
    • ensure は最後に書くことになるのが問題 (リソースを使用した直後に書きたい)

などの議論がありました。 Ruby開発者の温度感がわかって楽しかったです。

YJIT Makes Rails 1.7x Faster

YJIT みなさん使ってますか?

YJIT Makes Rails 1.7x faster / RubyKaigi 2024 - Speaker Deck で 紹介されたように MedPeer でも YJIT を有効にして速くなっています。 感謝!

講演では Ruby 3.3 で高速化された YJIT の高速化された手法の紹介がありました。

  • Method Call Fallback の仕組みでJIT できない場合、Ruby インタプリタに処理を戻していたケースのいくつかで、JIT 可能になり高速化。
  • スタック変数をメモリ上で処理していたのをレジスタ上で処理するようになった。
  • Active Support の NilClass#blank? がインライン化され 1命令になるのは圧巻でした。

という感じで、素晴らしい改善ですね。 Ruby 3.4 でも改善が進んでいるみたいなので超期待です。

speakerdeck.com

Speeding up Instance Variables with Red-Black Trees

毎回、わかりやすく説明頂ける @tenderlove さんの講演です。 ObjectShape キャッシュミス時の検索に 赤黒木 を使うことで、計算量を O(n) から O(log(n)) に減らしたという内容でした。

ObjectShape の各オブジェクトもツリー構造に配置されるので、赤黒木のアルゴリズムが使えるんですね。 該当の PR は https://github.com/ruby/ruby/pull/8744 になると思います。

ただ、私は 赤黒ツリー を理解していなかったため内容にあまりついていけず、非常に残念な思いをしました。 観たいセッションの講演概要に知らないキーワードがある場合は、事前勉強が重要ですね!

コンピュータサイエンスの知識があると、最適なアルゴリズムを選択できるため知識は重要です。動画や資料が公開されたら再度確認したいです。

Lightning Talks

手前味噌ですが、LTで発表させて頂きました。 詳細は、下記を参照頂ければと思いますが、LT発表すると他の方のLT内容を聞けないのが残念ですよね。 こちらも動画が公開されたら確認したいです。

おわりに

3日間に渡るRubyKaigi 2024が終了しました。 非常に魅力的な公演が目白押しでしたが、3トラックなので観れるセッションが限られていたのが辛いところです。

次回のRubyKaigiは 2025年4月16日から4月18日、場所は愛媛県松山市です。

今年もAfter RubyKaigi を開催します!

昨年に続き今年もZOZOさん、FindyさんといっしょにAfter RubyKaigiを開催します!!!

medpeer.connpass.com

  • イベントタイトル: 『After RubyKaigi 2024〜メドピア、ZOZO、Findy〜』
  • 開催日時: 2024/05/28(火) 19:00 〜 21:30
  • 会場: ファインディ株式会社
    • 東京都品川区大崎1-2-2(アートヴィレッジ大崎セントラルタワー 5階)
    • ※ オンライン参加枠有り

メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら medpeer.co.jp

■エンジニア紹介ページはこちら engineer.medpeer.co.jp

■メドピア公式YouTube  www.youtube.com

■メドピア公式note
style.medpeer.co.jp

メドピアはRubyKaigi 2024にPlatinumスポンサーとして協賛します!

はいさい、メドピアの榎本です!

メドピアは2024年5月15日〜17日に沖縄・那覇文化芸術劇場なはーとで開催される RubyKaigi 2024 にPlatinumスポンサーとして協賛します!

今年もメドピアは会場でブースを出展します!

目次

ブース企画

今回メドピアブースでは大きく2つの企画をご用意しました。

  1. アンケートに答えてガチャガチャに挑戦!
  2. VPoTのXをフォローでデカバッグをプレゼント!

アンケートに答えてガチャガチャに挑戦!

簡単なアンケートに答えるだけでガチャガチャに挑戦でき、メドピアオリジナルのアクリルスタンドが獲得できます。

VPoTのXをフォローでデカバッグをプレゼント!

さらに、弊社のVPoT・ありひーこと平川 弘通のXアカウント(@arihh)をフォローで、メドピアオリジナルのデカバッグをプレゼントいたします。

ノベルティ紹介

アクリルスタンド

アンケートに答えて挑戦できるガチャガチャでは、アクリルスタンドが獲得できます。

オリジナルアクリルスタンド

メドピアのオリジナルキャラクター・メドベアがメッセージとともに登場します。RubyKaigi 限定のメドベアも登場するかも...?

ぜひ写真に収めてSNSに投稿してください!

デカバッグ

弊社のVPoT・ありひーのXアカウント(@arihh)をフォローすることで、昨年好評いただきましたメドピアオリジナルのデカバッグを獲得できます。

オリジナルデカバッグ(with 弊社VPoTのありひー)

荷物が嵩張っても大体のものが入る大きめサイズとなっておりますので、ぜひこちらもあわせてゲットしてください!

この場所でお待ちしています

メドピアは下記でブース出展しております。

RubyKaigi 2024 メドピアブース位置

ブース付近では、メドピアカラーの濃い緑色のTシャツを着たメンバーが立っておりますので、お気軽に声をお掛けください。

当日皆様にお会いできるのを楽しみにしております!

メドピアから内藤がLT登壇します

2日目の夕方(2024年5月16日 17:20-18:20)には弊社から内藤がLTに登壇いたします。

内藤から発表内容に関するコメントも下記のように頂いております。

REXMLは Ruby で実装された XML パーサーで、Ruby の標準添付ライブラリ(Bundled Gem)です。 Pure Ruby なのでインストールが容易ですが、処理速度が遅いという課題があります。 このREXMLのパース処理をStringScannerで書き換えて高速化した話をします。

今年もAfterイベントを開催します!

昨年に続き今年もZOZOさん、FindyさんといっしょにAfterイベントを開催します!!!

findy.connpass.com

  • イベントタイトル: 『After RubyKaigi 2024〜メドピア、ZOZO、Findy〜』
  • 開催日時: 2024/05/28(火) 19:00 〜 21:30
  • 会場: ファインディ株式会社
    • 東京都品川区大崎1-2-2(アートヴィレッジ大崎セントラルタワー 5階)
    • ※ オンライン参加枠有り

ぜひ奮ってご参加ください!


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら medpeer.co.jp

■エンジニア紹介ページはこちら engineer.medpeer.co.jp

■メドピア公式YouTube  www.youtube.com

■メドピア公式note
style.medpeer.co.jp

監視にかかるコストを見直し半額にした話

SRE の田中 @kenzo0107 です。

メドピアグループでは主に AWS をプラットフォームとし、監視は Datadog で実施しています。

監視対象や課金対象のサービスの増加で徐々にコストが増加していたので、 利用状況を分析し、削減できる項目を調査しまとめました。

Datadog 子組織・サービス毎の利用料金の確認の仕方

親組織にある Usage & Cost > Individual Organizations *1 の Cost タブで各 org 毎の利用料金を確認できます。*2

事前に利用する量をコミット

www.datadoghq.com

事前に利用する量をコミットすることで 2~3割程、コスト削減できます。

ANNUALLY (年間でコミットを決定) の方がコスト削減率は高いですが、 MONTH-TO-MONTH (月毎にコミットを決定) を採用しています。

月毎に監視対象リソースの増減が頻繁にある為です。*3

Datadog APM のサンプルレートを下げる

Datadog APM の Ingested Span*4量は課金対象です。

docs.datadoghq.com

上記参考に Ingestion Control *5で Monthly Usage で使用量を確認し、 100% を超える分を冗長なデータとして取り込まない様にすることでコスト削減します。

サンプルレートを下げるコンテナの設定例

  • DD_APM_MAX_TPS = 1 とすることで 10 分の 1 で全体の 10% を取り込むように抑える
  • DD_APM_ENABLE_RARE_SAMPLER = true とし、稀に発生するサンプルを取りこぼさない様にする

Fargate タスク定義 JSON では以下の様になります。

{
    "name": "datadog",
    "image": "datadog/agent:latest",
    ...
    "environment": [
        {
            "name": "DD_APM_ENABLED",
            "value": "true"
        },
        {
            "name": "DD_APM_MAX_TPS",
            "value": "1"
        },
        {
            "name": "DD_APM_ENABLE_RARE_SAMPLER",
            "value": "true"
        }
    ],
    ...
}

Datadog APM EC2 vs Fargate

  • EC2 1 ホスト: 31 ドル / 月
  • Fargate 1 タスク: 2 ドル/月

既知の方は多いかと思いますが、念の為。
Fargate で Datadog APM を有効化した方が格段に安いです。

利用しない監視対象リソースのメトリクスを収集しない

  • 利用していないリージョンのメトリクス取得を無効化*6
  • 利用していない AWS サービスのメトリクス取得を無効化*7
  • EC2 のタグフィルターで datadog:true のタグを所持する EC2 のみ監視対象とする*8

Terraform で実装すると以下の通りです。

locals {
  enable_integration_list = [
    "application_elb",
    "elb",
  ]
}

resource "datadog_integration_aws" "this" {
  ...

  # 監視を有効化したいサービスのみ有効化する
  account_specific_namespace_rules = { for c in data.datadog_integration_aws_namespace_rules.rules.namespace_rules : c => contains(local.enable_integration_list, c) }

  # 除外リージョン
  excluded_regions = [
    "af-south-1",
    "ap-east-1",
    "ap-northeast-2",
    "ap-northeast-3",
    "ap-south-1",
    "ap-south-2",
    "ap-southeast-1",
    "ap-southeast-2",
    "ap-southeast-3",
    "ap-southeast-4",
    "ca-central-1",
    "ca-west-1",
    "eu-central-1",
    "eu-central-2",
    "eu-north-1",
    "eu-south-1",
    "eu-south-2",
    "eu-west-1",
    "eu-west-2",
    "eu-west-3",
    "il-central-1",
    "me-central-1",
    "me-south-1",
    "sa-east-1",
    "us-east-1",
    "us-east-2",
    "us-west-1",
    "us-west-2",
  ]

  # NOTE: メトリクスを収集する EC2 タグのフィルター設定
  #       datadog-agent インストール済みの EC2 のみ監視する為、以下タグをフィルターとする
  # see: https://registry.terraform.io/providers/DataDog/datadog/latest/docs/resources/integration_aws#optional
  filter_tags = ["datadog:true"]
}

data "datadog_integration_aws_namespace_rules" "rules" {}

上記対応により、 Datadog AWS Integration による AWS GetMetricData API の発行数が下がり、大幅にコスト削減できました。

AWS CloudWatch メトリクスで監視できるリソースは CloudWatch Alarm で監視

こちらも AWS GetMetricData API 発行コストを削減できます。

アラートの遅延*9を回避でき、副次的な効果がありました。

CloudWatch Alarm のリソースを監視する Terraform Module を作成し、監視の移行コストを下げました。

EC2 監視を Datadog Agent から CloudWatch Agent へ移行

Datadog の EC2 監視に掛かる Datadog Infrastructure Host のコストを削減したい意図です。

Datadog で監視していたメトリクスを CloudWatch Agent で取得し CloudWatch メトリクスに保存*10し、 CloudWatch Alarm でアラート発行する様にします。

CloudWatchAgent の設定ファイル例

{
    "agent": {
        "metrics_collection_interval": 60,
        "run_as_user": "root"
    },
    "metrics": {
        "aggregation_dimensions": [
            [
                "InstanceId"
            ]
        ],
        "append_dimensions": {
            "AutoScalingGroupName": "${aws:AutoScalingGroupName}",
            "ImageId": "${aws:ImageId}",
            "InstanceId": "${aws:InstanceId}",
            "InstanceType": "${aws:InstanceType}"
        },
        "metrics_collected": {
            "collectd": {
                "metrics_aggregation_interval": 60
            },
            "disk": {
                "measurement": [
                    "used_percent",
                    "inodes_free",
                    "inodes_total"
                ],
                "metrics_collection_interval": 60,
                "resources": ["*"]
            },
            "mem": {
                "measurement": ["mem_used_percent"],
                "metrics_collection_interval": 60
            },
            "statsd": {
                "metrics_aggregation_interval": 60,
                "metrics_collection_interval": 60,
                "service_address": ":8125"
            },
            "procstat": [
                {
                    "exe": "nginx",
                    "measurement": ["pid_count"],
                    "metrics_aggregation_interval": 60
                },
                {
                    "exe": "unicorn",
                    "measurement": ["pid_count"],
                    "metrics_aggregation_interval": 60
                }
            ]
        }
    }
}

以下カスタムメトリクスとして CloudWatch メトリクスに保存します。

  • ディスク使用率
  • ディスク i-node フリー
  • ディスク i-node トータル
  • メモリ使用率
  • procstat でプロセス監視

CPU 使用率はデフォルトで取得できるので設定していません。 inodes_free, inodes_total からディスク i-node 使用率を計算しています。

docs.aws.amazon.com

CloudWatch Agent に移行できないパターン

Datadog APM を利用している EC2 ホストは Datadog Agent を起動させておく必要があり、 CloudWatch Agent への移行ができません。*11

Datadog APM を有効化している EC2 ホストは CloudWatch Agent へ移行せず、移行できるものだけ移行することとしました。
監視設定が Datadog と AWS とハイブリッドになりますが、コスト削減メリットが大きく、移行を進めました。

通知内容自体も Datadog と CloudWatch Alarm で若干異なりますが、欲しい情報は取れていたので特段問題ありませんでした。*12

上記対応により、逐次 Datadog Infrastructure Host を削減できました。

過去 6 ヶ月の Datadog Infrastructure Host 利用量

Datadog に残したもの

代用できるサードパーティや自作する見通しが直ちに立たなかった為、元々使用していたものを利用することとしました。

まとめ

以下の対応により監視にかかるコストが年間 1 千万円ほど削減できました。

  • 事前に利用料をコミット
  • Datadog APM サンプルレートの適正化
  • 利用しない監視対象リソースのメトリクスを収集しない
  • AWS CloudWatch メトリクスで監視できるリソースは CloudWatch Alarm で監視
  • EC2 監視を Datadog Agent から CloudWatch Agent へ移行

全体的に監視を AWS に寄せたことが大きなコスト減の要因ですが、用法用量を適切に管理すること、サービスの知見を得ることで未然に意図しないコスト増を防ぐ必要があると改めて学びがありました。
怠惰に利用しない様、心に刻みます。

以上
参考になれば幸いです。


是非読者になってください


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら medpeer.co.jp

■エンジニア紹介ページはこちら engineer.medpeer.co.jp

■メドピア公式YouTube  www.youtube.com

■メドピア公式note
style.medpeer.co.jp

*1:Datadog ログイン後、親組織で admin 権限を持つアカウントのみアクセス可能です。

*2:プロジェクト毎の利用料金をわかりやすくすべく、 子組織に分けています。 メドピアグループでは terraform で Datadog リソースを管理しておりますが、terraform provider も子組織もサポートしています

*3:キャンペーンが多い月はサーバ数が増加したり、サービスがクローズした場合の影響度を下げる等、フレキシブルに変更可能にしたい意図です。毎月更新している訳ではなく、必要が生じた際に担当のカスタマーサポートに連絡し、変更いただいています。

*4:Ingested Span は、スタック内の個々のサービスに対する個別のリクエストです。Datadog に取り込まれたスパンのギガバイトの総数に基づき月末に課金されます。

Ingested Span = 上記図に見られる APM で取得 (Ingested) した各ブロック (Span)

参考: https://docs.datadoghq.com/ja/account_management/billing/apm_distributed_tracing/

*5:Datadog にログイン後に閲覧可能なリンクです。

*6:基本 ap-northeast-1, us-east-1 を利用しており、それ以外を除外しました。

Datadog AWS Integration の設定

*7:Datadog で利用したいメトリクス以外は無効化しました。

*8:タグフィルターを設定しないとデフォルトで全ての EC2 が監視対象となり、意図しないコスト増が発生します。

*9:docs.datadoghq.com

*10:CloudWatch のカスタムメトリクスを使用しましたが、いずれも無料枠で収まる量となりました。

*11:Datadog Agent, CloudWatch Agent 双方を起動させることは可能ですが、重複させる必要性はなく、Datadog Infrastructure Host の料金を下げる意図に反するので移行しませんでした。

*12:CloudWatch Alarm から Chatbot へポストし、 Slack 通知させています。

初めてのMariaDBバージョンアップのメンテナンスで大変だったこと、工夫したこと

はじめに

 2023年4月に新卒で入社したバックエンドエンジニアの冨家です。現在は、全国の医師が経験やナレッジを 「集合知」として共有し合う医師専用コミュニティサイト「MedPeer」の開発を行っています。
 「MedPeer」ではAmazon RDSのMariaDBを一部使用しています。最近まで10.6.11バージョンを使用しており2024年3月にRDS 標準サポート終了を迎えるので、私が主にバージョンアップ作業を担当することになりました。しかし、私自身初めてのデータベースバージョンアップ作業だったため、どのような点に気をつけるべきかわからず対応に苦労しました。
 そこで今回は、次回バージョンアップする方の参考になるように、実際に行ってみて大変だったことや工夫したところ、次回改善したほうが良いことなどを紹介していきます。

MariaDBバージョンアップに関連する「MedPeer」のAWS構成図

メンテナンス日時の選定の仕方

 まず大変だったことが、メンテナンスの日時を選定することでした。メンテナンスモードに切り替えると全てのユーザーがサービスを使用できなくなります。日時によっては大きな機会損失を出す可能性があるので、実施する日時を見極めることがとても重要でした。
 最終的には、2024年2月26日の23:00から24:00の間にメンテナンスモードに切り替えました。メンテナンスする日時は7つの条件から選定しました。

リスト1 メンテナンス日時を選定したときの7つの条件

1.1. バージョンアップのプロジェクト開始日から1ヶ月以上後であること
1.2. サポート期間が終了する1ヶ月以上前であること
1.3. メンテナンス当日と翌日が休日・祝日ではないこと
1.4. バッチ処理が少ない時間帯であること
1.5. ユーザーのアクセスが低い時間帯であること
1.6. メンテナンス実施日から翌日まで重要な処理がないこと
1.7. ステージング環境で実際にかかったメンテナンス作業時間以上を本番のメンテナンス時間として確保できること

1.1. バージョンアップのプロジェクト開始日から1ヶ月以上後であること

 データベースをバージョンアップするためには他チームとの日程調整やユーザーにメンテナンスを実施する告知が必要です。そのため、余裕を持って行えるようにプロジェクト開始から1ヶ月以上後にしました。

1.2. サポート期間が終了する1ヶ月以上前であること

 もしサポート期間終了直前でバージョンアップを試みて失敗した場合、再チャレンジする時間がありません。そこで、余裕を持って再チャレンジできるようにサポート終了日から1ヶ月以上余裕を持たせるようにしました。

1.3. メンテナンス当日と翌日が休日・祝日ではないこと

 メンテナンス当日や翌日は想定外のことが起きやすく障害が発生しやすいです。もし休日に障害が発生した場合対応が遅れやすくなるので、当日と翌日が休日・祝日ではない日程にしました。

1.4. バッチ処理が少ない時間帯であること

 バッチ処理が多いと考慮することが多くなり、想定外のことが発生しやすくなります。
 現在の 「MedPeer」では、22時から24時の間で1時間あたり3件程度バッチ処理が起動します。しかし、24時以降は1時間あたり数十件のバッチ処理が起動するように設定されているので、日程が変わる前にメンテナンスをすることにしました。

1.5. ユーザーのアクセスが低い時間帯であること 

 もしユーザーがメンテナンス中でアプリを使えなかった場合、サービスに対して不満を感じて、問い合わせ数の増加やアクティブユーザー率の低下に繋がります。そのため、トラフィックが少ない時間帯にメンテナンスを実施して、ユーザーへの影響を最小限にすることが大切です。
 調査した結果、 「MedPeer」では比較的月曜夜のトラフィックが少なめで、22時と23時では数万のアクセス数差があることが判明したので、選定しました。

1.6. メンテナンス実施日から翌日まで重要な処理がないこと

 深夜にアップデートした場合、利用者が増える翌朝に問題が発覚することが多いです。そのためメンテナンス日から翌日の夕方まで、ユーザー影響の大きなイベントが開催されないように他チームと調整を行いました。開催日時が定まっている「Web講演会」機能を筆頭に、特定日時での処理が必要な機能がメンテナンス前後で実行されないように周知・調整を徹底しました。

1.7. ステージング環境で実際にかかったメンテナンス作業時間以上を本番のメンテナンス時間として確保できること

 本番環境のインスタンスはステージング環境と比較してデータ量が多く、より時間がかかる可能性があります。
 ステージング環境でメンテナンス時間を計測してみた結果、メンテナンスモードに切り替えてから通常モードに戻すまで1時間かかりました。そのため、1時間以上切り替えられる日時を選定しました。

実際に選定した日時にバージョンアップした結果

 大きな問題は発生しませんでした。しかし、「メンテナンス中でアクセスできずデイリーボーナスポイントやログインボーナスポイントが獲得できなかった」という問い合わせが1件入ったので、次メンテナンスする方は、メンテナンス中に締切があるイベントやキャンペーンがある時間帯をできる限り避けるように選定できると良さそうです。

バージョンアップ作業の手順

 次に大変だったことは、バージョンアップの手順を作成することでした。もしプライマリーインスタンスで大きな障害が発生してしまうと、長時間サービスが止まってしまい大きな損失を出してしまいます。そのため、「どうすればプライマリーインスタンスで障害を起こさないようにできるのか」、「もし障害が発生した場合どのようにすれば最小限に抑えることができるのか」という視点を持ってバージョンアップの手順を考える必要がありました。
 リスト2 は、MariaDBをバージョンアップしたときの手順を表しています。手順のポイントは7つあります。

リスト2 MariaDBバージョンアップ手順

2.1 事前準備
2.1.1. バージョンアップに失敗した場合の復旧手順を確認しておく
2.2 メンテナンス作業
2.2.1. 社内に向けて作業開始連絡
2.2.2. リードレプリカのバージョンアップ
  • 対象インスタンスのリードレプリカのバージョンアップ
  • 追加されたデータがDBに反映できていることを確認
2.2.3. サービスメンテナンス開始
  • アプリケーションをメンテナンスモードに切り替え
  • 外部のユーザーがアクセスできないことを確認
2.2.4. プライマリーインスタンスのバージョンアップ
  • 対象のプライマリーインスタンスのスナップショットの取得および結果確認
  • プライマリーインスタンスをバージョンアップ
2.2.5. バージョンアップ後の確認
  • バージョンアップ後にデーターベースの読み書きができることを確認
  • プライマリーインスタンスのバージョンアップ後にRedashからリードレプリカのデータを取得できるかを確認
  • コンテナログ、監視ツールのアラート確認
2.2.6. サービスメンテナンス終了
  • アプリケーションのメンテナンスモードを解除
  • 外部のユーザーがアクセスできることを確認
2.2.7. 社内に向けて作業終了連絡
2.3 メンテナンス後の残作業
2.3.1. 不要になったコードの削除
2.3.2. 1週間程度バージョンアップ後のメトリクス(CPU使用率など)に異常がないか確認

Point1. バージョンアップに失敗した場合の復旧手順を確認しておく

 もしバージョンアップに失敗した場合、慌てず迅速に対処できるように事前に確認するようにしました。

Point2.リードレプリカをバージョンアップしてからプライマリーインスタンスをバージョンアップする

 リードレプリカでバージョンアップして問題が起きないことを確認することで、プライマリーインスタンスの障害発生率を低くするように工夫しました。

Point3. バージョンアップ後にデーターベースの読み書きができることを確認する

 閲覧ログを登録しているテーブルがあるため、そのページを表示し閲覧ログが書き込まえることを確認しました。

Point4. プライマリーインスタンスのバージョンアップ後にRedashからリードレプリカのデータが取得できるかを確認する

 プライマリーインスタンスをバージョンアップするとリードレプリカも置き換わります。プライマリーインスタンスのバージョンアップ後にリードレプリカが正常に動作しているか確認するため、Redashからリードレプリカのデータが取得できることを確認しました。

Point5. コンテナログ、監視ツールのアラート確認する

 バージョンアップ中やバージョンアップ後でアプリケーションにエラーが起きていないことを確認するために行いました。もしメンテナンス関連で問題がないエラー通知が来ていた場合(DBのコネクションエラー等)、その通知がメンテナンス作業のものであることを表明して、バージョンアップに携わっていない人にも問題がないことを伝えるようにしました。

Point6. 1週間程度バージョンアップ後のメトリクス(CPU使用率など)に異常がないか確認する

 バージョンアップ直後は想定外のことでメトリクスが変化しやすく、パフォーマンス悪化に繋がりやすいです。そのため、1週間程度異常がないか確認するようにしました。

2/26から3/4までのMariaDB CPU使用率の推移

Point7. 各手順でかかった時間を計測しておく

 各手順でかかった時間がわかると「次回バージョンアップ作業する時にスケジュールを立てやすくする」、「時間がかかった作業を分析して、次回以降の作業時間を短縮できる」などのメリットがあるので、計測するようにしました。

実際に手順通りバージョンアップした結果

 問題なくバージョンアップすることができました。バージョンアップによる障害が発生せず、予定よりも10分早くメンテナンスを終えてスムーズに行うことができました。

作業が終了したときの社内連絡

最後に

 以上、MariaDBをバージョンアップさせる上で大変だったことや工夫したこと、次回改善した方が良いことなどについて、紹介しました。
 実際にバージョンアップ作業を進めていくと、他社ではどのように行っているのか何度も気になりました。もし親切な方がいらっしゃいましたら貴社の事例を記事にしていただけると大変参考になります。
 また、今回のバージョンアップ方法で改善案がありましたら、コメントいただけると嬉しいです。


是非読者になってください


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら medpeer.co.jp

■エンジニア紹介ページはこちら engineer.medpeer.co.jp

■メドピア公式YouTube  www.youtube.com

■メドピア公式note
style.medpeer.co.jp

社内版 ChatGPT を構築し、社内の ChatGPT 利用を促進した話

SRE の田中 @kenzo0107 です。

社内版 ChatGPT を構築し、社内の ChatGPT 利用を促進した話です。

社内版 ChatGPT が必要だった理由

以下要望を実現する為です。

  • 秘匿情報をクローズドな環境で OpenAI にポストしたい
  • 社員誰もが最新のモデルやバージョンで高精度、且つ、パフォーマンスの高い ChatGPT を利用したい

構成 - Web 版 社内 ChatGPT

  • Web サービスは AWS に配置
  • ALB を会社毎に分けて Google 認証する *1
  • ECS から Azure API Management 経由で Azure OpenAI Service に問い合わせ
    • API Management は Azure OpenAI Service の監査ログを取得する為に配置している *2
  • Azure 側ではネットワークセキュリティグループで AWS NAT Gateway の EIP を許可し、リクエスト制限する

AWS にサーバを立てている理由

Azure で完結した方が、よりクローズドでセキュアです。

弊社では AWS はセキュリティガードレールが整備されていますが
Azure は未完です。

その為、Azure 側は必要最低限の利用リソースのみにし
AWS 側で基本 Web サービスを配信する構成としました。

chatbot の選定

既に世の中には多くの OSS がありますが、 中でもコンテナに対応しており、スター数が多く、開発が活発だった mckaywrigley/chatbot-ui *3 を採用しました。

chatbot-ui v2 がリリースされていますが、 v1 を利用しています。*4

chatbot-ui v2 採用を見送った理由

  • supabase との連携を前提としている
    • AWS 上にクローズドな環境を構築するようなアーキテクチャを採用できない
  • 利用者が各自 Azure OpenAI Service デプロイ ID を設定・管理する必要がある

上記理由から採用を見送りました。

chatbot-ui v1 の問題点

v1 は各自設定不要で即利用できるメリットがあるものの、以下デメリットがありました。

  • API バージョンを 2023-03-15-preview からアップグレードするとエラーになる
  • Azure OpenAI Service からのレスポンスが途切れる
    • fetch メソッドで API エンドポイントからレスポンスを取得していたことが影響していた

上記はいずれも openai ライブラリを利用することで解決できました。*5

Slack から問い合わせたい!

社内リリースをし Google Analytics で利用者の増加を眺めながら一呼吸したのも束の間、 すぐさま以下の意見をいただきました。

  • VPN に繋いで Web ブラウザ開くのが手間
  • Slack からサクッと問い合わせたい

早速実現に向け動きました。

構成 - Slack 版 社内 ChatGPT

  • Slack Event Subscription を設定し、 Bot へのメンション・Direct Message をトリガーに Lambda を起動し Azure OpenAI Service へ問い合わせる
  • 弊社グループ会社毎の各 Slack Workspace で Slack App を作成*6
  • Slack 毎の Signing Secret や Bot User OAuth Token は Lambda 内で処理分け *7
  • VPC モードの Lambda から Azure OpenAI Service に問い合わせる
    • 出口 IP を NAT Gateway EIP に固定する為

Slack 参加メンバーはグループ会社のメールアカウントを所持しており、Google 認証はしない方針としました。

使用例1: チャンネル上から Slack App にメンションする

Slack Bot をチャンネルに招待し、 Bot へのメンションをトリガーに Azure OpenAI Service に問い合わせます。

スレッド中の Bot へのメンションは Azure OpenAI Service との会話に引き継がれます。*8

使用例2: Slack App に直接 Direct Message を送信する

チャンネル上でメンションする場合と異なり、スレッド上の全てが Azure OpenAI Service との会話となります。

利用上の注意点を社内通知

  • 秘匿情報を扱う際は Slack でなく Web 版を利用していただく
    • Slack はサードパーティであり、秘匿情報を第三者が取得できてしまう可能性がある為
  • Slack 検索時の @office-ai のノイズ除外したい時は -from:@office-ai して、というノウハウの通達*9

総評

Slack 版は、他の方が Azure OpenAI Service にどのように問い合わせることで回答を引き出すかのノウハウを知る機会を作ることができたと思います。

開発に際して、
Azure 関連のセキュリティや OSS の改修等、諸問題に対して、
Azure OpenAI Service を利用することで解決できました。

弊社では GitHub Copilot *10 を採用し生産性を向上していたりと AI による社内全体の業務促進する為に AI を利用するという好循環ができているように改めて感じました。

以上
参考になれば幸いです。


是非読者になってください


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら medpeer.co.jp

■エンジニア紹介ページはこちら engineer.medpeer.co.jp

■メドピア公式YouTube  www.youtube.com

■メドピア公式note
style.medpeer.co.jp

*1:ALB のリスナールールのデフォルトアクションでのみ Google 認証の指定が可能です。メドピア株式会社メンバーが持つ @medpeer.co.jp のメールアカウントとフィッツプラス株式会社メンバーが持つ @fitsplus.co.jp で Google Workspace が異なる為、 Google Workspace 毎に ALB を用意することとしました。

*2:Azure OpenAI Service 単独では Azure OpenAI Service へのリクエスト・レスポンスのログは取得できない仕様でした。 learn.microsoft.com

*3:Next.js ベースで作成されています

*4:legacy ブランチが v1 相当です

*5:v2 の参照実装で事なきを得ました。

*6:workspace を跨いだ Slack Bot が作れませんでした

*7:Event Subscription で指定したエンドポイントに "?workspace=medpeer" を追加することで判定しました。

*8:Bot にメンションしていないメッセージは Slack Event Subscription をトリガーできない為

*9:用途があるかと思ったので

*10:Copilot Business を導入しています