データカタログの本格導入に向けたdbt-osmosisへの貢献について紹介します

Analytics Engineerの吉田(id:syou6162)です。BigQueryを中心に10X社内のデータ管理の仕事をしています。

最近、データカタログの本格導入の準備を進めていて、それに向けた補助ツールとしてdbt-osmosisもゴリゴリと使い倒すようになってきました。その中で「10Xでの運用を考えるとこういうケースで困るし、前職までの経験を踏まえると解決できると他社でも役に立ちそう」「この挙動は普通にバグっぽいな...」というものがあったので、立て続けにPull Requestを送りました。ありがたいことに全部マージしてもらえましたが、せっかくなのでデータカタログの導入に向けてdbt-osmosisを採用した背景やどういったPull Requestを送ったか紹介します。

データカタログ導入の必要性

つい先日もStailerが新規導入されたプレスリリースが出ました。「Stailerを導入していただいたらそれで終わり」ということは当然なく、導入後は

  • 初回購入者の獲得 (First Order UU)
  • 店舗 / エリア / アクセスの開設 (Accessibility)
  • キャパシティの最大化 (Capacity)
  • 品揃え / 価格の最適化 (Selection)

など様々な観点でデータを見ながら改善を進めていく必要があります。分析の対象も多様ですし、短期や中長期でも分析が必要なため、10XではアナリストだけでなくBizDevやPdMがSQLを書くことも多いです。アナリストであれば分析したいテーブルに不明点があっても元のSQLを読み解いて意味を理解することができますが、他職種の人にそれを求めるのは困難です。また、そもそもBigQuery内にテーブル / カラムが多数あるため、自分の分析に必要なテーブル / カラムがどれかを探すのが難しいというData Discoveryの観点で課題を感じている人が多い、ということも社内のアンケートで明らかになりました。

そこで、テーブルやカラムのdescriptionを充実させ、他職種の人でも自分が必要なデータを探したり、データの意味や定義をさっと分かるようにしてデータ分析を自走してもらえるように、データカタログの導入を進めています。導入にはDataplexを予定しており、検討した際の項目については以下のエントリを参照してください。

メタデータをいかに効率よく入力するか: dbt-osmosisの導入

データカタログを機能させるためには前提条件があり「(テーブルや)カラムのdescriptionがいかに充実しているか」が鍵となります。これが不足していると、検索にそもそも引っかからないですし、きちんとメンテナンスされていなければ古い定義のまま分析してしまい、誤った意思決定に繋がってしまうこともありえます。

「カラムのdescriptionが充実しているのがいかに大事か」は分析に関わる人であれば痛いほど理解できるかと思いますが、これをカバレッジ高く継続的に人手でメンテナンスし続けるのは非常に大変です。

10Xではdbtを導入していますが、dbtはエコシステムが非常に充実しており「最小限のカラムのdescriptionを埋めれば、それを参照しているカラムのdescriptionも自動的に埋めてくれる」dbt-osmosisという便利なOSSが存在します。

dbt-osmosis導入以前は体感だと1割もカラムのdescriptionが入力されておらず、データカタログが機能する状況ではありませんでした。しかし、導入後は10X社内でよく使われるデータセット内において、5割から8割程度のカラムのdescriptionが入力されている状況*1に改善され、自動で行なえるため運用コストもグンと抑えられます。dbt-osmosisの詳細については以下のエントリを参照してください。

dbt-osmosisの導入に伴ない、最小限のカラムのdescriptionを埋める箇所に関しては以下の方針で取り組みました。

  • 伝播元になるデータレイク側のカラムのdescriptionの入力
    • アプリケーションのコードを参照しながら、分析に頻出するテーブルのカラムについては気合いで埋める
    • より継続的なメンテナンスをしやすくするため、開発チームとデータコントラクトなどの枠組みでデータの仕様について握っていくことを今後進めていければと思っています
  • データマートに登場する独自のmetricsなどのカラムのdescriptionの入力
    • 伝播する必要のないデータマートだけで使うaggregateされた指標などを想定
    • データマートを作成することが多いAnalytics Engineerやアナリストで入力
    • なぜ入力する必要があるか、入力することでどういったメリットがあるかについて説明会を開催しました
    • メンテナンスが難しいSQLと向き合う機会が多かったり、データマートについて質問を受けるメンバーが多かったことから、入力のモチベーション部分についても納得感を持ってもらいやすい状況でした

取り込まれた修正

このように非常に便利なdbt-osmosisですが、10Xのdbtプロジェクトに導入する際に課題となった点がいくつかありました。修正自体は大したものではないですが、運用面ではクリティカルなものもあったため、これらを解決するために私が送ったPull Requestについて紹介します。

CamelCaseからsnake_caseにrenameした際にも伝播できるようにする

「データソースの都合で取り込まれたデータレイクのカラムがCamelCaseになっているが、データウェアハウスやデータマートの構築はsnake_caseで命名規則を統一している」というケースは多いと思います。dbt-osmosisはこれまでは依存関係にあるモデル内のカラムで完全一致*2した場合のみ、カラムのdescriptionに伝播していました。つまり、CamelCaseからsnake_caseへの変換が入ると、それ以降のレイヤーへのカラムのdescriptionが伝播できるカバレッジが途端に下がってしまう、という問題がありました。カラムのdescriptionはなるべくデータレイクに付与するのがメタデータ管理の基本と思ってこれまで生きているので、こういったケースでもカラムのdescriptionを伝播できるように修正しました。

ネストしたフィールドがある際に、ルートレベルのカラムの情報が欠損してしまう問題を修正

これはバグの修正ですね。dbtはBigQueryのstructやrecordのような構造があってもカラムのdescriptionを記述できますし、dbt-osmosisもそれらの構造を考慮した上でカラムのdescriptionを伝播してくれます。しかし、この伝播をする際にルートレベルのカラムの情報が吹き飛んでしまうというバグがあり、自分の事例でもせっかく付与したカラムのdescriptionがそれなりに存在したため、修正しました。

カラムのdescriptionがどこから伝播されたものか分かる情報を埋め込む

dbtはrefを使ってモデルを小さく構成した上でそれらに対してテストを書くことができますし、多段のレイヤリングになったとしてもデータリネージをきちんと管理できることが強みの一つです。しかし、そうした構成の中でdbt-osmosisを運用していると

  • このカラムのdescription、ちょっと意味が分かりにくいから修正したい
  • データレイク側で調べてみたけど、どうもこのdescriptionはデータレイクで付与されて伝播されたわけではなさそうだ
    • 中間レイヤーのどこかで付与されて伝播されてきたらしい
  • うーん、どこが大本か、データリネージとgit grepを駆使しながら探すかぁ...
    • 自分がやるなら「手間だな...」くらいで済むけど、アナリストなど他職種の人がやるのはハードルがぐっと上がってしまう...

ということで困ることが出てきました。「このカラムのdescriptionはどこから伝播されたか」という情報は実はログに出力されており、この情報をモデルのymlファイル内に埋め込むことで伝播元がどこかをさっと分かるようにするオプションを追加しました。

このオプションを使うと、meta.osmosis_progenitorに伝播元のモデルが記載されるため、どこを修正すればいいか分かりやすくなりました。

version: 2
models:
  - name: mart_order
    columns:
      - name: my_description
        description: "This is description"
        meta:
          osmosis_progenitor: source.my_project.my_dataset.order

こういったメタ的な情報を保存しておくのにmetaは便利なので、必要があれば要所要所で使っていきたいですね。

tagsやmetaの伝播をスキップするオプションを追加

dbt-osmosisはカラムのdescriptionだけでなく、実はカラムに付与されているtagsmetaの情報もディフォルトで伝播します。これは便利なのですが、先ほどのmeta.osmosis_progenitor自社独自の運用用のmetaのフィールドが存在する場合、無闇に伝播されると困ります。不要な場合はこれらの伝播をスキップできるオプションを追加しました。

まとめ

このエントリでは

  • パートナー数の拡大やグロースフェイズの最適化において、BizDevやPdMでも自走して分析できる環境が必要になっている
  • 自走できるようにデータカタログの導入を検討しているが、descriptionの入力のカバレッジの低さが課題
  • descriptionの入力をある程度自動で行なえるdbt-osmosisを導入したが、課題があったためPull Requestを送ってそれらを改善

について紹介しました。同じような課題は他社でもあると思いますし、そういった課題に対してdbt-osmosisを通じて多少は貢献できたかなと思います。

こういったメタデータ管理やデータカタログ、データ基盤の運用や改善に興味がある方はぜひお話しましょう。

*1:INFORMATION_SCHEMA.COLUMN_FIELD_PATHSビューを用いて集計しました

*2:正確に言うと、case-insensitiveでも一致するようになっており、これはSnowflakeで役に立つようです

開発チーム内における品質管理部のメンバーの動き方: お会計チームの例

こんにちは。 品質管理部のtarappoです。

早いもので2023年度も1Q(4月〜6月)が終わって上半期も後半戦です。 品質管理部は、次の記事に書いたとおり4月から組織体制を変えました。

上記の記事の執筆時点からさらに体制は変化しています。 ざっくりと執筆時点での体制を図にすると次のような感じです。

以前はチームへのアサインが固定化されてないメンバーもいましたが、今は各開発チームへのアサインは固定化されています。 上記のブログ記事や登壇含め、体制変化については伝えているものの、この体制になって各チームでどういったことを行なっているかについては話していません。

そこで、本記事ではこのチーム体制になってから各開発チームでの品管メンバーの動きについてフォーカスして話したいと思います。

その中で、まずは私が所属する「お会計チーム」についてフォーカスして話したいと思います。

開発チームごとの動きとは?

最初に、なぜ特定のチームにフォーカスして話すのかという点について説明したいと思います。

各開発チームはそれぞれ特徴があります。

扱う範囲が広めのチームもあれば、特定領域に特化したチームもあります。 その中で、品管メンバーとしておこなっている内容についても違いがあります。

チーム体制になる前は品質管理部全体で動いていたので、次のような全体として1つのテストプロセスを決めていました*1

このプロセスがチーム体制になったことでどう変わったかというと。

基本的にこのプロセスは踏襲しますが、チームの特徴に応じてチーム単位で変化を加えたり、プロセス内の特定のアクションをより深化させたりと、各チームのメンバーに判断してもらっています。

こうした背景があり、特定のチームにフォーカスして話すのがよいというのがあります。

「お会計チーム」ではなにをおこなっているのか?

私が所属するチームは「お会計チーム」です。 チーム名の名前のとおり、お会計にまつわることを扱っています。

さらに本チームの特徴として、次のようなものがあります。

  • クライアントサイドよりサーバサイドを扱う機会が多い
  • 外部サービスを扱っている機能が他チームより多い

このお会計チームのメンバー(SWE、PdM、私)でチームができたときにキックオフをおこないました。

そのときにおこなったインセプションデッキで、「品質」という観点におけるトレードオフスライダーをおこなっています。 上図のようにこのチームでは扱う機能の関係上「品質」を重視するという話をチームのみんなでしています。

そのため「お会計チーム」では品質をより守っていくためのリリースプロセスとしています。 実際にリリースするまでの流れについて次に説明していきます。

リリースをするまでの流れ

リリースをするまでの流れをざっくりと図にすると次のようになっています。

簡略化のために、あえてこの図では除外していますが実装前には仕様策定のステップもあります。 図をもとにステップ、やること、担当者を表にすると次のとおりです。

ステップ やること 担当者
(1) 仕様に基づき実装 SWE
(2) 内容の理解 品管メンバー
(3) どう守るかを考える 品管メンバー
(4) 内容に対するフィードバック 品管メンバー
(5) フィードバック対応 SWE
(6) テスト実施 品管メンバー、SWE

基本的には(1)から順にすすみますが、(3)と(4)は同時に進めつつ(5)の結果をもとにさらに(3)をアップデートしたりします。 必ずしも前に進んで戻らないというわけではなく、戻ったりしながら前に進んでいきます。

上記については実装からのステップの話になっていますが、 品管メンバーもSpring Planningに参加しているので、本Sprintで何を実装予定なのか、そして今後の予定については把握しています。

なので、実装前の段階から品管メンバーも動けるとさらに良いのですが、現時点ではまだその状況にまでは達していません。 仕様を決める段階から関わることもありますが、それをおこなっているのは全体の一部となります。

上述した流れについて主にどのようなことをおこなっているかについて次に説明していきます。

(1)実装と(5)フィードバック対応

お会計チームでは実装時にプロダクトコードに対する「テストコード」とプロダクトコードへの「コードドキュメント」は基本的に必須となっています*2。 これが必須となっているのは「品質」に関係する対象機能に対する「認知コスト」をいかに下げていくかという点で重要なことでもあります。

コードドキュメントの対象読者は主にSWEならびに品管メンバーになります。

対象の機能に対して理解をする速度を上げるためにも「コードドキュメント」は重要です。 プロダクトコードにdartdocで記載されたコードドキュメントはWebから見ることができるようになっています。 また、文字だけでなく図(Mermaid記法)も貼ることでよりわかりやすくなっています。

テストコードにおいては、そもそもの課題として次がありました。

  • テストがなにをしているかが分かりづらい
  • テストとしてなにを守りたいかが分かりづらい
  • テストとして守るべき箇所が守れていない

テストコードを書くという文化はあり、コードカバレッジは高かったものの上記の課題がありました。 そこでお会計チームでは、今ある自動テストをがんばって活かすというよりも新たに作り直すぐらいの気概で進めていくことにしています。

そして、後述する私からのフィードバックに対して、内容をチェックした上で対応をしてもらっています。

(2)内容の理解

(1)の成果物を元に内容を確認した上で、対象に対する理解を深めます。 これによって次を理解していきます。

  • どのような機能なのか
  • なにができている必要があるのか

上記をおこなう上で見るべき成果物としては次のとおりです。 必須で見ているのは1、2、3で、4は必要に応じて見るものが変わっていきます。

  1. プロダクトコード*3
  2. テストコード
  3. コードドキュメント
  4. 関連ドキュメント(仕様書やDesignDocなどいろいろ)

理解を進めていく上で、上記の成果物を読んでいく中で分からないことがあれば適宜質問をしていきます。

理解をするのは今回の機能に関するものを読めば分かるとは限りません。 変更点だけを見ても関連するものが分かれなければ、対象機能に対しての理解があまりできないこともあります。 そのため、関連する機能に対しても同様な成果物を確認することはよくあります。

しかし、初期の頃は認知コストの高さや自身のナレッジの薄さから時間がかかりやすい傾向がありました。 そのため、SWEに説明してもらったりシーケンス図などを用意してもらったりと、そういったこともおこないつつ理解を深めていきました。

理解が一定深まってきたら、「(3)どう守るか」を考えつつ「(4)内容のフィードバック」を併せておこないます。

(3)どう守るか考え(4)内容に対してフィードバックする

内容を理解した上で、「(3)どう守るか」を考えつつ「(4)内容に対してフィードバック」をおこないます。

常に新規機能ではなく、また新規に作ったものも既存の箇所で利用するといったケースもよくあります。 したがって影響範囲もチェックした上で、どの箇所をテストするべきかを考えていきます。

影響範囲も加味した上でどう守るか、そのためにはどのようなテストをするかというのを考えていきます。

  • 対応箇所:対象となる機能のどの箇所
  • 守る手段:自動テスト*4、手動テスト、それ以外

守る手段においては自動テストの活用は重要です。 その上で、自動テストだけでは守ることができない箇所に対して、手動テストがどの範囲で必要かどうかを判断していきます。

自動テストで守っていく範囲においては、現時点のテストコードで足りているかをチェックしフィードバックをしていきます。

レビュー観点

テストコードに対するレビュー観点の例としては次のようなものがあります。

  • テストコードが足りているか

対象のインターフェースのみを見た場合だとどうしても近視眼的になることがあります。 状態が重要となるケースにおいては、状態遷移テストも必要になるため、その点も加味します。 また、テストコードの見やすさと足りているかという観点からパラメタライズテストも積極的に活用しています。

  • テストコードを書きすぎていないか

お会計チームの場合、守りを強くしたいというのはありますが「なんでもかんでも」テストコードを用意するのが良いわけでもありません。 自動テストもメンテナンス対象なので、必要でないと感じるものがあれば作らないでもいいようには考えています。 とはいえ、現時点では守りを強固にしていることもあり一定多めになっているのも事実です。

  • テストコード内で確認しているものが妥当か

なにをチェックしているかどうかは重要で、確認すべきものを見ていないケースも過去にはありました。 逆に見なくてもいいものを見ているケースもあります。

  • テストケース名は分かりやすいか

なにがテストで担保されているか分かるためにもテストケース名は重要です。 単に「success」や「期待した結果になること」といった言葉があると、何をしたかったのかが分かりづらいです。

規約を作ったほうが良いよねということでSWE側で規約周りについていろいろと進めてくれています。 その話について次のブログ記事を書いてくれています。

(6)テスト実施

(3)でどう守るかを考えた内容を元にテストを実施していきます。

テスト実施が「自動テスト」のみで完結するケースもあります。 「手動テスト」が必要な場合は、内容を元に品管メンバーがおこなう場合もあればSWEがおこなう場合もあります。

テスト実施中に不具合が見つかれば対応をしていきますが、必要に応じてテストコードも追加していきます。 問題がなければ最終的にはリリースを実施します。

品管としてはリリースがされたこともチェックしています。 コードがmergeされてリリースされたのを見た上で、いつ時点までのコードを確認したかをメモしています。 これにより前回との差分をよりわかりやすくできるようにしています。

FY23 1Q(4月〜6月)の結果

上述したようなリリースプロセスで、FY23 1Q(4月〜6月)の3か月間における結果として次について説明をします。

  • 関わった案件数の推移
  • (現時点でのチームの)課題

関わった案件数の推移

この3か月間における関わった案件数の推移は次のとおりです。

  • 4月:8件
  • 5月:10件
  • 6月:19件

徐々にテスト資産*5も溜まってきており、1件あたりにかかるスピードは上がってきています。

一方、開発メンバーもリファクタリングや改善を進めた結果として開発速度は以前よりも早くなっており、まだまだ品管メンバー側の対応が少し遅れている状態といえます。

この状態を脱するためにも、ほぼ私1人のみだった品管側の体制を変化させてメンバーを増やしています。 他にも、今まで品管メンバーがおこなっていたことをいかに開発メンバーに委譲するかなどの検討も進めています。

定量的な数字は別の場所で話せればと思いますが、案件数の増加に伴ってテスト実施時に見つかる不具合が増えていたりユーザ影響がある障害が起きているわけではありません。

課題

すべてにおいて順調というわけではなく課題もいろいろとあります。 現時点における課題としては次のようなものがあります。

  • 扱う領域の中でまだテスト設計ができていない領域がある
    • 把握できてないためにそこへの影響範囲が読みづらく広く守ろうとしてしまう
    • 特にクライアントサイドに対しては弱い
  • 現時点で私が案件全体に関わっておりほかメンバーへの分散化ができていない
    • SETスキルを必要とする関係のためバス係数1の状態になっており、私がボトルネックとなるケースがある
    • 今より早い段階から関わるということがあまりできていない

上記はあくまでも、現時点での「お会計チーム」での課題といえます。

他の開発チームも含めて考えると、今回のお会計チームのようにSETスキルを活用したほうがより効果をうむ開発チームもあります。 しかし、現時点では品質管理部としてはまだそこにアプローチできていない現実があります。 それは上述したような特定の開発チームの課題というよりも品質管理部としての課題の1つとなっています。

おわりに

上述したように「お会計チーム」における品管の関わり方はSETスキルを必要とした形となっています。 そのスキルを活かすことでチームとして品質を強く守るということができるようになってきています。

より具体的な取り組みの詳細については、いろいろな形でアウトプットできればと思います。

また、今回話したチーム以外においても色々な取り組みをおこなっています。 今回の記事に限らずいろいろなチームの動き方を紹介できればと思います。

本記事で話したような「SETスキルって?」というのがあるかと思います。 各社が現時点でSETにもとめるスキルはいろいろなものがあると思いますし、我々が「今」求めているSETスキルというのもあります。

そこで、1Qの終わりにおこなった品質管理部のオフサイトでメンバーと「今、10XのSETとして求めることは」ということについて話し合いました。 その内容については、近いうちに公開する予定ですので楽しみにしていただければと思います。

それまでに話を聞いてみたいという方は次から是非カジュアル面談を応募してもらえると嬉しいです。

*1:わかりやすさを考慮した上で多少簡略化して書いています

*2:必須としていますが、当然必要でないところまでやる必要はありません

*3:新たにライブラリを使っている場合は状況に応じてライブラリのテストコードもチェックします

*4:ここでいう自動テストは一般的に言われるユニットテストやE2Eテストなどで、その中から有効なものを考えます

*5:ここでいうテスト資産は既存機能に対するテスト設計書など対象機能に対するナレッジの集まりやテストを実施する上でのアセットです

データ基盤の管理に役立つ監視用のSQLを紹介します

Analytics Engineerの吉田(id:syou6162)です。BigQueryを中心に10X社内のデータ関連の管理をしています。10Xに入社してそろそろ一年になろうかとしていますが、データ基盤を適切に管理 / 運用するためにSQLによる監視を少しずつ取り入れています。この記事では、具体的にどのようなSQLを書いて監視しているのか紹介したいと思います。

なお、SQLを使ったデータ基盤の監視自体については私の前職のTech Blogで詳細に書いていますので、そちらを参照してください。

本エントリはこれをベースに「dbtをフルに活用している10Xの環境向けに入れた監視」や「BigQueryの最近のアップデートに伴ない新しく入れた監視」にフォーカスを絞って紹介しようと思います。

dbtの運用に関連する監視

更新されていないテーブルを検知する

10Xではdbtを積極的に活用しています。dbtではテーブルなどのリソース作成や更新をSQLを使ってコード管理できますが、SQLを削除した場合でもBigQuery上のテーブルを削除してくれるわけではありません。SQL削除後に忘れずにテーブル側も削除しないと、ずっとテーブルが残ってしまうことになります。これは以下の2点からも課題になります。

  • ストレージコスト
    • SQLを削除する場合、ほとんどはその後はそのテーブルを見ないことを意味します
    • 誰からも見られないテーブルをそのままにしておくのはストレージコストの観点で無駄です
  • データセキュリティ
    • 参照されることがほぼないとは言え、不必要なテーブルが残ったままになっているのはデータセキュリティの観点からもよくありません
    • 定期的に不要なテーブルを棚卸しする必要がありますし、削除すべき対象の一覧は機械的にさっと出せるようにしたいです

削除すべきテーブルが出てきた場合、以下のSQLで監視して速やかに棚卸しをするようにしています。これはINFORMATION_SCHEMA.TABLE_STORAGEビューを使うと簡単に分かります。

SELECT
  COUNT(DISTINCT table_name) AS not_updated_tables_count
FROM
  `my-project`.`region-us`.INFORMATION_SCHEMA.TABLE_STORAGE
WHERE
  # プロジェクト全体での適用は難しい場合が多いので、データセットを限定しながら少しずつ管理対象を拡大していくのがオススメ
  table_schema IN ("my_dataset_1", "my_dataset_2", "my_dataset_3")
  AND DATE_DIFF(CURRENT_DATE("Asia/Tokyo"), DATE(storage_last_modified_time, "Asia/Tokyo"), DAY) >= 7

なお、データがテーブルに最後に書き込まれた時刻を取りたい場合はstorage_last_modified_timeを使うのがよいとna0さんに教えていただいたものを採用してます。アドバイス、ありがとうございました。

ストレージが巨大になり過ぎているテーブルを検知する

イベントやログなどのテーブルを参照する場合、テーブルサイズが非常に大きいこともあり

  • 新規でテーブルを参照する場合は全期間を対象にする
  • テーブルがすでに存在するのであれば、参照する期間を直近のみにする

という処理をしたいことがよくあるかと思います。dbtではadapter.get_relationを使うことで、テーブルに限らずリソースがすでに存在するかを判断することができます。よって、こういったSQLがよく登場します。

{%- set already_exists = adapter.get_relation(this.database, this.schema, this.identifier) is not none -%}

select
  ...
from
  {{ source('my_dataset', 'my_events') }}
where
  {%- if already_exists %}
  _TABLE_SUFFIX > format_date('%Y%m%d', date_sub(current_date(), interval 3 day))
  {%- endif %}

これは便利ではあるのですが、上記のSQL内で使われているjinjaのマクロは変数が未定義であっても、そのまま動作してしまいます。変数が未定義の場合だと

  • 毎日巨大なテーブルが参照され
  • その結果の巨大なテーブルがincrementalなテーブルとして積み重なり
  • 最終的には数百TBある巨大なテーブルが出現してしまう

ということがありました。恐しいですね...。

こういった巨大なテーブルができてしまった場合でも早期に気付けるように、INFORMATION_SCHEMA.TABLE_STORAGEビューを使って監視するようにしています。

SELECT
  table_schema AS dataset_name,
  table_name,
  SUM(active_logical_bytes / POW(1024, 4)) AS active_logical_tera_bytes,
FROM
  `region-us`.INFORMATION_SCHEMA.TABLE_STORAGE_BY_PROJECT
GROUP BY
  dataset_name, table_name
HAVING
  active_logical_tera_bytes >= 100 # ここは適当に変えて使ってください

この監視による通知がきた場合、対象のテーブルの作成ロジックを調査したり、git blameして作成者にロジックを修正依頼する、ということを行なっています。

BigQueryの新プラン導入に伴なう監視

ここ最近でBigQueryではBigQuery Editionsの登場やPhysical storage課金のGAなど大きめの変更が複数ありました。BigQueryのコストは10Xでも大きなものとなっているため、BigQuery EditionsやPhysical storage課金の導入を進めています。導入に際し、新規に監視したほうがよい項目があったので、それらを紹介したいと思います。

BigQuery Editions導入に伴なうスロット利用量に対する監視

10Xでは長らくBigQueryはオンデマンドを利用していました。しかし、2023/07/05以降、オンデマンドは課金単価が約25%値上げということもあり、BigQuery Editions導入を検討しました。BigQuery Editions導入によりコストが増加 / 減少するかは実際に動かすクエリのワークロードによって異なりますが、検証の結果、10XのワークロードにおいてはBigQuery Editionsを導入したほうがコストが下げられると判断したため、BigQuery Editionsをコストの大部分を占めるプロジェクトで導入しました。

オンデマンド利用時はデータのスキャン量に比例した課金体系でしたが、BigQuery Editionsでは処理に使ったスロット時間に比例した課金体系へと変化します。データのスキャン量はBigQueryのWebコンソールで実行前に表示されますが、現在のところスロット時間は実行前にはまだ表示されません。また、実行後でも奥まったところに表示されるため、ユーザーがスロット時間を気にしにくい形になっています。そのため、スロット量の監視を導入することにしました。

一つ目は短期間でスロットを大量に消費しているパターンの監視です。一時間毎にINFORMATION_SCHEMA.JOBS_TIMELINE_BY_ORGANIZATIONビューを叩くことで、バースト的に大量のスロットを消費しているユーザーがいないか監視しています。

WITH
  slot_in_second AS (
  SELECT
    period_start,
    user_email,
    CEIL(SUM(period_slot_ms) / 1000 / 100 ) * 100 AS total_slot_sec,
  FROM
    `region-us`.INFORMATION_SCHEMA.JOBS_TIMELINE_BY_ORGANIZATION
  WHERE
    job_creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), interval 60 minute)
    AND reservation_id IS NOT NULL # BigQuery Editionsを有効にしているものが対象
    AND user_email NOT LIKE "%iam.gserviceaccount.com"
  GROUP BY
    period_start,
    user_email
)
SELECT
  user_email,
  DATE_TRUNC(period_start, HOUR) AS period_start,
  ROUND(SUM(total_slot_sec) / 60 / 60, 2) AS total_slot_hour,
FROM
  slot_in_second
GROUP BY
  period_start,
  user_email
HAVING
  total_slot_hour >= 1000 # この閾値は適当に変更してください

バーストはしていないものの、長時間に渡って実行されておりその結果スロットの消費量も多くなっているパターンもありました。このパターンについては、別にSQLでのそのパターンも検知できるようにしています。

SELECT
  job_id,
  TIMESTAMP_DIFF(CURRENT_TIMESTAMP(), MAX(start_time), MINUTE) AS running_minutes,
FROM
  `region-us`.INFORMATION_SCHEMA.JOBS_BY_ORGANIZATION
WHERE
  creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 60 minute)
  AND reservation_id IS NOT NULL -- BigQuery Editionsを有効にしているものが対象
  AND user_email NOT LIKE "%iam.gserviceaccount.com"
  AND state = "RUNNING"
GROUP BY
  job_id
HAVING
  running_minutes > 30 # この閾値は適当に変更してください

Physical storage課金の対象になっていないデータセットを洗い出す

BigQueryのPhysical storage課金は対象になるデータセットによって圧縮率が異なりますが、10X社内では6~8倍の圧縮率であることが多く、ストレージコストも非常に下げられる試算があったので、導入を進めています。

既存のデータセットについては一度Physical storageを有効にしてしまえばOKですが、問題は新規で作成されるデータセットです。プロジェクト内で新規に作成されるデータセットのdefaultをPhysical storageに設定することができないため、新規に作成されたデータセットはLogical storageの設定になってしまうことは注意が必要です。

そこで、INFORMATION_SCHEMA.SCHEMATA_OPTIONSビューとINFORMATION_SCHEMA.TABLE_STORAGEビューを使ってPhysical storageが有効になっていないデータセットの一覧を洗い出すようにしています。

WITH storage_billing_model_physical AS (
  SELECT
    catalog_name AS project_id,
    schema_name AS dataset_id
  FROM
    `my-project`.INFORMATION_SCHEMA.SCHEMATA_OPTIONS
  WHERE
    option_name = "storage_billing_model"
    AND option_value = "PHYSICAL"
)
SELECT
  project_id,
  table_schema AS dataset_name,
FROM
  `my-project`.`region-us`.INFORMATION_SCHEMA.TABLE_STORAGE
WHERE
  # まだstorage_billing_modelがphysicalになっていないデータセットのみ対象とする
  project_id || "." || table_schema NOT IN (SELECT project_id || "." || dataset_id FROM storage_billing_model_physical)
GROUP BY
  project_id,
  dataset_name

この一覧を元に、定期的にPhysical storageを有効にするバッチを運用しており、ストレージコストの削減に繋げています。

まとめ

10X社内でのdbtやBigQueryの運用で行なっている監視の工夫について紹介しました。データの活用者が適切に利用できるようにガードレールを引きながら、コストやセキュリティの面でも今後も継続的に改善していこうと思います。

データ基盤の運用や改善に興味がある方はぜひお話しましょう。

プロダクトのイシューリスト(課題一覧)を作りました

こんにちは。10Xのソフトウエアエンジニア(SWE)の石田です。

10Xでは採用に応募してくださる候補者様にむけて、プロダクトのStailerにおいて解決しなければいけないイシューリスト(課題一覧)を作りました。

イシューリスト

各課題をクリックすると各課題の詳細が確認できます。

イシュー

作った理由の1つは、候補者様に対して会社に応募してくださるときに、どんな中長期的な課題があって、どのような貢献ができるか具体的にイメージしてもらいたいからです。会社やプロダクトの情報はプレゼンテーションなどの資料で公開されていますが部署単位で実際にどのような課題があるかは表現できていませんでした。課題をあきらかにすることにより採用の初期の段階でよく質問のある「プロダクトの課題は何ですか?」に答える事ができ、より深い議論ができます。どのような課題が候補者様が興味があるかによって入社した後のアサインも話す事ができます。このように実際に働いたときの解像度を高め10Xに入社を決めてくれる助けになればいいなと思っています。

もう1つの理由は、10Xのメンバがいまプロダクトの課題はなにかを広く理解できることです。他のチームの課題がわかればカジュアル面談などで候補者様の質問に網羅的に答える事ができます。また、メンバのチームの課題を言語化することにより課題を深く理解しチーム外に説明ができます。そうするとチーム外のメンバが課題に対して理解でき、アイデアがあれば話す事ができ、課題をより解決しやすくなると思っています。

このように候補者様・10Xのメンバが両者ともイシューリスト(課題一覧)を認識することにより採用の助けになり、ひいては課題を解決できればなと思っています。

イシューリストの項目に興味をもっていただいた方はぜひカジュアル面談で詳しくお話しましょう!

ソフトウェアエンジニア(Product Security Ops)を募集します

こんにちは、Software Engineerの@sota1235です。最近の趣味はギター練習です。

今回は私が所属するセキュリティチームで新たにソフトウェアエンジニアを募集し始めた話をします。

採用目的が全開みたいなタイトルになっていますが、伝えたいことは「セキュリティエンジニアだけでなくソフトウェアエンジニアをセキュリティチームで募集するに至った」背景です。

10Xのセキュリティチームが組成されてから1年半でどのような変化があり、どんな課題を解決するためにこの意思決定に至ったのか。なぜソフトウェアエンジニアが必要なのか。

スタートアップにおいてプロダクトのセキュリティ品質を担保するための体制をどう組み立てていくかの一例として参考になれば幸いです。

目次

  • 目次
  • ソフトウェアエンジニア(Product Security Ops)とは
  • なぜソフトウェアエンジニアの募集をするのか
    • 1. 現在のセキュリティチームを構成するメンバーがソフトウェアエンジニアであること
    • 2. 直近で見えているセキュリティ領域の課題の大半はソフトウェアエンジニアの力で解決できること
  • どんな機会があるのか
    • プロダクトセキュリティ面での品質強化の初期フェーズに携われる
    • 未経験でもプロダクトセキュリティの領域にチャレンジができる
  • 最後に
続きを読む

デザイナーの採用面接ワークショップを社内でやってみた

デザイナーのJです。(このプロダクトブログ書くのは初!)

先日からプロダクト本部とエンジニアリング本部合同で社内の知見活性化を目的に「Product Friday」というLT大会が開催されるようになりました。👏👏

今回はそこでデザイン部から発表した内容をプロダクトブログでご紹介させていただきます。

発表内容はずばり「UIとUXの話をしよう」ということで、実際の10Xデザイン部の採用面接の中で使われているFigJamを使って行いました。

今後の採用面接ではこのお題は変更するのですが、似たようなことはやっていくと思います。 もしこれからデザイナーの募集に応募してみようと思った方は参考にしてみてください。

採用面接でワークショップやることになった背景

2023年1月から10Xに入社したのですが、前職の採用フローでも同じようなことをやっていて、ちょうどミドルからシニアにかけてのデザイナー面接において一定効果を感じられていたので10Xでも導入してみました。

ポートフォリオだけでは図りきれない普段の候補者の思考やどんなところから目をつけるかなどに気づけることができ、今いるデザイナーとのバランスや、イシューへ取り組む際のスタンスなどを感じとることができています。

では、実際のファイルはどんなものか

簡易的な背景とユーザー情報

まずは、背景やユーザー情報を簡単にまとめた情報を読んで頂いています。

ワークショップの前提やユーザー像などの情報
ワークショップの前提やユーザー像などの情報

続いてユーザーフロー

一連のユーザーフローを画面スクショで配置しています。

アプリの画面一覧が並んでいる様子
アプリの画面一覧

ちなみに画面内はあえて大きく気付けるポイントを残していたり、意図的に違和感あるUIを設けてたりもします。

候補者の方には、このFigJamのURLをお渡しして、気づいた点をどんどん口頭で指摘してもらいます。 10Xメンバーはその指摘をFigJamのコメント機能を使って該当箇所に記入し、気になったところを適時深掘りしながら候補者の方と会話していきます。

FigJamのタイマー

FigJamにはタイマー機能があるので、お互い夢中になりすぎて「時間大幅に過ぎてる!!」みたいなこともないのがいいですね!

Product Fridayでの模様

今回は時間も限られているので、20数人みんなで一斉にコメントしていってもらいました。

みんなが一斉にコメントする模様のスクリーンショット
みんなが一斉にコメントする模様

気になる箇所を指摘してる模様
ログイン導線の課題コメントを読んでいる

登録フローでの必須がわかりにくいというコメントを話してる模様
登録フローでの必須がわかりにくいというコメント

デザイナーだけでなくエンジニア視点、PdM視点、さらにユーザー視点で「ここはわかりにくい」や「ここはこうしたほうがいいのでは」と盛り上がりました。

余談ですが、Product FridayではFigJamのBGM機能をONにして、文字通りFridayを駆け抜けるようにノリノリでやったのが面白かったです。 ※普段の採用面接ではBGMは流してません。

それぞれの会社なりの採用の形があるはず

10Xのデザイナー採用においてはこういった取り組みをしていますが、エンジニア採用では技術課題がある会社もありますし、他社含めいろいろな取り組みをされていると思うので、もし自社ではこんなことやってるなどあれば、アンサーブログを勝手にお待ちしてます! そして、もしよかったらデザイナー採用に関するイベント一緒にやりましょう!

最後に、こんなデザイナー面接を受けてみたいと感じた方、ぜひご応募お待ちしております!

デザイナー / 株式会社10X

Null Safetyへの移行対応からDart 3の世界へ

はじめに

こんにちは。お会計チームの yamakazu (@yamarkz) です。

Dartで導入準備が進められていたNull Safetyと呼ばれる言語機能への対応が、先日ようやくStailerでも完了しました。

プログラミング言語としてNull Safetyへの移行 (機能導入) は頻繁に起こるものではなく、珍しい話題です。なので、せっかく対応をしてきたのなら、その記録として何を考え、何を行いNull Safetyに対応していったのか、Stailerを題材に紹介しようと思います。

ニッチな話題ですが、読み物として楽しんでいただければ。

続きを読む