Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Reasonable logging in BtoB Application
Search
hoshino tsuyoshi
October 10, 2024
Technology
5
100
Reasonable logging in BtoB Application
テーマ: 変更履歴を適切に保持したい
rails ruby
hoshino tsuyoshi
October 10, 2024
Tweet
Share
More Decks by hoshino tsuyoshi
See All by hoshino tsuyoshi
GitHub Actionsで `shell` に `ruby {0}` と書ける話
hoshinotsuyoshi
2
160
RDSのパスワードローテーションについて考えてみた話
hoshinotsuyoshi
1
110
「技術的負債」について私から言えること私から言えないこと
hoshinotsuyoshi
2
1.1k
spreeのrails updateの戦いの歴史と github上のPR作成時の工夫
hoshinotsuyoshi
0
990
Ruby is fun but difficult
hoshinotsuyoshi
0
380
バッチ処理でhakoを使う話
hoshinotsuyoshi
0
9.6k
docker swarm 触ってみた #dockerlt
hoshinotsuyoshi
0
1.1k
貧者のためのCoreOS(Jenkinsを例に)
hoshinotsuyoshi
1
1.6k
個人で使ってみた Docker と CoreOSとか
hoshinotsuyoshi
7
3.6k
Other Decks in Technology
See All in Technology
なぜ私はいま、ここにいるのか? #もがく中堅デザイナー #プロダクトデザイナー
bengo4com
0
460
生成AI時代の開発組織・技術・プロセス 〜 ログラスの挑戦と考察 〜
itohiro73
1
220
低レイヤを知りたいPHPerのためのCコンパイラ作成入門 完全版 / Building a C Compiler for PHPers Who Want to Dive into Low-Level Programming - Expanded
tomzoh
4
3.2k
第9回情シス転職ミートアップ_テックタッチ株式会社
forester3003
0
240
A2Aのクライアントを自作する
rynsuke
1
170
BigQuery Remote FunctionでLooker Studioをインタラクティブ化
cuebic9bic
3
310
CI/CD/IaC 久々に0から環境を作ったらこうなりました
kaz29
1
170
Amazon Bedrockで実現する 新たな学習体験
kzkmaeda
2
570
Amazon S3標準/ S3 Tables/S3 Express One Zoneを使ったログ分析
shigeruoda
4
530
Postman AI エージェントビルダー最新情報
nagix
0
110
Microsoft Build 2025 技術/製品動向 for Microsoft Startup Tech Community
torumakabe
2
280
生成AIで小説を書くためにプロンプトの制約や原則について学ぶ / prompt-engineering-for-ai-fiction
nwiizo
4
2k
Featured
See All Featured
What’s in a name? Adding method to the madness
productmarketing
PRO
23
3.5k
Automating Front-end Workflow
addyosmani
1370
200k
Building Flexible Design Systems
yeseniaperezcruz
328
39k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.4k
Embracing the Ebb and Flow
colly
86
4.7k
Become a Pro
speakerdeck
PRO
28
5.4k
Agile that works and the tools we love
rasmusluckow
329
21k
A better future with KSS
kneath
239
17k
Faster Mobile Websites
deanohume
307
31k
It's Worth the Effort
3n
185
28k
Fireside Chat
paigeccino
37
3.5k
Art, The Web, and Tiny UX
lynnandtonic
299
21k
Transcript
Roppongi.rb #23 "Proposals on Rails 2024" Reasonable logging in BtoB
Application ROUTE06, Inc. GitHub:@hoshinotsuyoshi 1
Me GitHub:@hoshinotsuyoshi • X:@hoppiestar • • SWE in ROUTE06 •
EDI platform 2023- • NO-CODE platform for building business apps 2024- • Yes, API backend is made with Ruby on Rails • public repo?(TBD) • 2
Outline EDI Platform • テーマ : 変更履歴を適切に保持したい • PaperTrail gemの手法とイベントソーシングについて説明
• 「誰が変更したか」を記録する工夫 • その他の工夫 • まとめ • 3
4
商取引におけるさまざまな事柄 (注文、商品、見積、出荷、承認、 etc.) を扱う。 EDI platform BtoB Applicatoin • many
resource classes • • buying, ordering, shipping ... • many stakeholders • • buyer, supplier, trader ... • ... • 5
テーマ : 変更履歴を適切に保持したい 6
商取引におけるさまざまな事柄について、 「誰が、いつ、どのように変更を加えたか」 を保持したい 目的 ... (今回は分析用途の目的は薄い ) テーマ : 変更履歴を適切に保持したい
システム不具合や障害発生時の調査・分析 • SOC監査対応 • リソースの変更履歴を表示するビューの追加実装 • 7
変更履歴 -> アプリケーションのログに頼る ?? 「アプリケーションのログにモデルの変更を記録する」という手もあるかもしれな いが ... • このログには他の情報も記録しているため、それらが混ざった状態で一定期間保持 する必要がある
• CloudWatchLogsのデータ保持のための料金もかかる • (or Logを分ける ?) • 8
paper_trail gemは、 Railsアプリケーションでモデルの変更履歴を追跡・管理する ための仕組みを提供する。 各モデルの変更を追跡し、 versions テーブルに履歴として保存する。 以下のコマンドを実行し、 versions テーブルを準備する
bundle exec rails generate paper_trail:install [--with-changes] [--uuid] bundle exec rails db:migrate 手法 : paper_trail gem 9
class Article < ApplicationRecord has_paper_trail end 手法 : paper_trail gem
1. バージョンの作成について モデルにバージョン管理を追加 : モデルに has_paper_trail を追加するだけで、そ のモデルの Create/Update/Destroy操作が自動的に追跡される。 • versions テーブルに履歴を保存 : 各変更は versions テーブルに保存され、バージ ョンごとの変更内容が記録される。 • 10
2. バージョンの保持内容について versions テーブルには、以下の情報が含まれる : | id | item_type |
item_id | event | object | ... |-----|-----------|---------|--------|------------------------------------------------------------------------------------| | 1 | Article | 1 | create | null | | 2 | Article | 1 | update | {"title": "First Post", "content": "Hello World!", "author": "Alice"} | | 3 | Article | 1 | update | {"title": "First Post - Revised", "content": "Final revision.", "author": "Alice"} | 手法 : paper_trail gem item_type: 追跡対象モデルのクラス名 (polymorphic) • item_id: 追跡対象モデルの ID(polymorphic) • event: 作成、更新、削除のイベント名 • object: 変更前のオブジェクトの状態を JSON形式 (または YAML)で保存 • object_changes: 各カラムがどのように変わったかを記録 • 11
イベントソーシングは、システム内で発生したすべてのイベントを保存し、そのイベ ントからデータの現在の状態を導き出す手法。 eventが主役となり、データの変化を イベントとして記録する。 1. eventsテーブルでのデータ管理 | aggregate_id | seq
| event_type | event_data |... |--------------|-----|-----------------|----------------------------------------| | Article:1 | 1 | ArticleCreated | {"title": "First Post", "author": "A"} | | Article:1 | 2 | ArticleUpdated | {"content": "New content"} | 参考 : イベントソーシング イベントを events テーブルに記録。 • 各イベントが「いつ、何を変更したか、何が起きたか」という情報を持つ。 • 12
2. Single Source of Truth 3. Projectionで状態を復元 参考 : イベントソーシング
イベントがデータの唯一の信頼できる情報源( Single Source of Truth) 。 • 過去の状態は、イベントの履歴を projection(投影)して再構築することで確認可 能。 • events テーブルのデータを集計・投影することで、アプリケーションで使用する 現在の状態を表現。 • この手法により、過去の任意の時点のデータ状態を再現することが可能。 • 13
イベントソーシング ActiveRecordのコールバックでバージョンを作成する手法 ざっくりまとめると イベントが主役 • gem例 : rails_event_store • リソースが主役
• gem例 : paper_trail • gem例 : audited • 14
1. ActiveRecordとのスムーズな統合 モデルの変更があれば自動的にバージョンが作成され、余分な設定や複雑なロジ ックを書く必要がない。 2. コールバックを活用した直感的な動作 ActiveRecordのコールバックを活用し、 save や update
メソッドの操作時に履 歴が自動で保存される。 Rails標準のメソッドを使うだけで、 paper_trail が自 動的に動作するため、開発中にイベント処理やトランザクションの管理をあまり 気にせずに済む。 paper_trail を採用したモチベーション 15
「誰が変更したか」を記録する工夫 16
「誰が変更したか」を記録する工夫 whodunnit (who done it・誰がやったか ?) の活用 • IPアドレス? •
できれば DBに保存したくない ... • アプリケーションのログに吐く ? • 17
平たく言えば、ユーザー IDを version テーブルの whodunnit カラムとして追加す る。コントローラに設定が必要。 class GraphqlController <
ApplicationController # ... before_action :set_paper_trail_whodunnit # ... whodunnit の活用 次のように書くと、コントローラーで current_user が定義されている場合、 current_user.id が whodunnit 列に保存される (という規約 )。 • current_user は devise gemを使っていてユーザークラスが User の場合に利用 されるメソッド。 • 18
devise を使っていない場合は current_user を定義したりすれば OK。 def current_user # 別途rack middlewareでセットしたユーザーを取得
request.env["xxx.tenant_user"] || raise end whodunnit の活用 19
IPアドレス IPアドレス ? 調査ケースによっては、あると便利な場合がある • 機微情報という見方もできる。できればあまり直接 DBに保存したくない ? • アプリケーションのログに吐く
? • --> AWSのログに頼るのはどうか • 20
--> この IDを追加で versionsテーブルに記録すれば OKでは? IPアドレス 今回の AWSの構成の事情 CloudFrontが ALBや
Railsアプリケーションの前段に配置されている • S3にログを吐く設定にしているので、ソース IPアドレスとリクエストを識別でき る ID( X-AMZ-CF-ID )が残っている • 21
paper_trail の 機能を使う。 例えばコントローラーに以下のように書けば、 x_amz_cf_id を versionsテーブルに記 録できる。 def info_for_paper_trail
{ # CloudFront. "x_amz_cf_id" => request.headers["HTTP_X_AMZ_CF_ID"], } end これで versionsテーブル -> X-AMZ-CF-ID -> S3のログから IPアドレスをたどることが できるようになった ! IPアドレス 22
さらに追加で Amazon X-Rayとアプリケーションログとの紐付け用に情報を足す例 def info_for_paper_trail { # CloudFront. "x_amz_cf_id" =>
request.headers["HTTP_X_AMZ_CF_ID"], # 追加: アプリケーションログと紐づけられるRequestID "request_id" => request.request_id, # 追加: Amazon X-Ray. ALBのログと紐づけられるID. "x_amzn_trace_id" => request.headers["HTTP_X_AMZN_TRACE_ID"], } end 参考 23
これで ...リーズナブルに対応できたのでは ? (分析対応ではなく )障害調査・侵害疑惑調査・監査対応などを目的と想定する場合 はこれで十分 • アプリケーションログ (ECS/CloudWatchLogsを利用 )も肥大化しないしリーズナブル
• CloudFrontのログは S3に置かれるので、 Amazon Athenaによる検索が可能 • 積極的に活用はしていないが、仕組み自体は準備済みであり、 CloudWatchで検索 をかけるよりも金銭コストが低いと思われる • 24
ここまでで 変更履歴が記録できるようになった 何を • いつ • 誰が • AWSのログと組み合わせることで「誰がどこから」もトレース可能に •
25
その他の工夫 26
保存時に必ずコールバックを発火するようにしたい コールバックが発火しないと versionが保存されないので ... update_column(s) , update_all , insert ,
... • -> rubocopの設定で禁止 • Rails/SkipsModelValidations • 27
1つのテーブルが極端にレコード数が増えるのを防ぐため、 クラスごとに versionsテーブルを分割。 # バージョンテーブルの抽象クラス class TenantRecordVersion < TenantRecord self.abstract_class
= true class << self def inherited(subclass) super # ...snip... # PostgresのRLSのための設定をここに書く(今回は説明省略) # ...snip... subclass.include ::PaperTrail::VersionConcern versions テーブルが肥大化することを抑止 28
このように使う : # ActiveRecordのクラス class Image < TenantRecord has_paper_trail versions:
{ class_name: "ImageVersion" } # ...snip... # Imageクラス用のバージョンテーブル class ImageVersion < TenantRecordVersion end versions テーブルが肥大化することを抑止 29
まとめ 30
変更履歴の保持手法について、 paper_trail gemを中心に説明しました。 この手法により、 BtoBアプリケーションにおけるログの管理がより効果的に行える ようになったと考えています。 まとめ 簡便さを重視し、 Railsエンジニアのマインドセットに適した履歴管理を実現 •
ActiveRecordとのスムーズな統合やコールバックを活用することで、エンジニアの 負担を軽減 • whodunnit や CloudFrontログの活用により、誰がどこから変更したかの追跡が可 能に。直感的かつリーズナブルな履歴管理が実現 • 31
「うちはこんな設計にしてる」 「こうしたほうがいいぞ !」みたいな話も聞きたいです ! 質問があれば、いつでもどうぞ! みなさんはどうやっていますか? 32
東京でお会いしましょう ! 👋 さいごに宣伝 33