Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GAEログのコスト削減

 GAEログのコスト削減

GO TechTalk #30 クラウドコスト削減 祭り で発表した資料です。

■ YouTube
https://www.youtube.com/live/O_b_wTPloiM

■ connpass
https://jtx.connpass.com/event/341113/

GO Inc. dev

February 05, 2025
Tweet

More Decks by GO Inc. dev

Other Decks in Programming

Transcript

  1. © GO Inc. 2 自己紹介 GO株式会社 バックエンド開発部 / 山野 祐 不動産業界向けの基幹システムやポータルサイト内サービスの

    翻訳、ブログ、広告配信システムの開発に従事したのち、2023 年11月よりGO株式会社にてバックエンドの開発・運用を担当 趣味はツーリング、旅行、ジム、辛いもの食べること
  2. © GO Inc. 3 GOのシステム全体構成と発表箇所 バックエンド 分析環境 バックエンド (App Engine)

    次世代 バックエンド (Kubernetes) キュー (Pub/Sub) 分析ログ データ 基盤 (BigQuery) RDB (Cloud SQL) フロントエンド 次世代 サーバログ基盤 (Loki) サーバログ基盤 (Cloud Logging) S3 キュー (Pub/Sub) 車載位置ログ サーバ ログ サーバ ログ ユーザー アプリ ドライバーア プリ 発表箇所
  3. © GO Inc. • Cloud Loggingとは ◦ ストレージ、検索、分析、モニタリングをサポートするリアルタイムのログ管理システ ム ◦

    Google Cloudリソースからログデータを自動的に収集 ◦ GAEのログ種類 ▪ リクエストログ • アプリに送信されたリクエストのログ • デフォルトではApp Engine は、アプリが受信した HTTP リクエストごとにロ グエントリを自動的に出力 ▪ アプリログ • サポートされているフレームワークまたはファイルに書き込んだログエントリ に基づいてApp Engineアプリが出力するログエントリ ▪ システムログ • アプリに関する情報が格納されるプラットフォームで生成されたログ Cloud Logging の概要 6 Cloud Logging概要
  4. © GO Inc. • Cloud LoggingはGoogle Cloudのコストの中でもTOP3でコスト削減が必要 ◦ 不要なログの削除をすることでコスト削減できないか検討 ◦

    ログ内の項目削除をすることでコスト削減できないか検討 • ロギングの検索を容易にするため、構造化ロギングにしコスト増し 7 なぜCloud Loggingのコスト削減?
  5. © GO Inc. • 調査 ◦ リクエストボディとレスポンスボディが大きいログを目視で確認 ◦ リクエスト数の多いログを調査するため、 Loggingから転送されたBigQueryでログを集計して確認

    • 削除したもの ◦ 調査で不要と判断され、かつリクエストボディとレスポンスボディが大きいログ ◦ 調査で不要と判断され、かつリクエスト数が多い apiのログ ◦ すべての項目がマスクされているログ ▪ (例 削減1:不要なログ削除 {"adress":"*****", "kana_name":"*****", "mail":"*****", … 8
  6. © GO Inc. • ログ内で値の重複項目削除 ◦ pathとurlが同じ値のためurlだけ残し た 削減2:不要な項目の削除 9

    insertId: ”1234abcd5678xxxx” jsonPayload: { message: ”samplelog” request: { method: “POST” url: “/v1/export/log” userAgent: “iPhone12.8” } timestamp: “2025-01-10T00:00:00.00000000Z” } insertId: ”1234abcd5678xxxx” jsonPayload: { message: ”samplelog” request: { method: “POST” path: “/v1/export/log” url: “/v1/export/log” userAgent: “iPhone12.8” } timestamp: “2025-01-10T00:00:00.00000000Z” }
  7. © GO Inc. • 他のログで内容が被っている項目 ◦ リクエストログとアプリログの user agentが重複している ▪

    リクエストログにだけ user agentを残した 削減2:不要な項目の削除 10 リクエストログ method: “POST” requestId: ”1234abcd5678xxxx” resource: “/v1/export/log” responseSize: “100” spanId: “123abc” startTime: “2025-01-10T00:00:00.00000000Z” status: 200 traceId: “1a2b3c4e” urlMapEntry: “auto” userAgent: “iPhone12.8” versionId: “testservice” アプリログ insertId: ”1234abcd5678xxxx” jsonPayload: { message: ”samplelog” request: { method: “POST” url: “/v1/export/log” userAgent: “iPhone12.8” } timestamp: “2025-01-10T00:00:00.00000000Z” }
  8. © GO Inc. 11 結果:Cloud Logginのコスト約40%カット • 結果 ◦ サービスの成長とともに右肩上がりに増

    えていたログコストを9個の不要ログを削 除しピーク時の約40%削減 • 所感 ◦ GCPコストの中でTOP3の割合を Loggingがしめていて、もっと早くにやる べきだったが、コストの意識が回らなく対 応できいていなかった ◦ コストの意識が薄かったが以前より意識 するようになり、週一の部の定例でコスト の増減を確認するパートができ、部として 意識付けできるようになった ピーク時の約40%減
  9. © GO Inc. • Cloud Loggingだけでなく、GAEもコストが高いという課題があった • Cloud ProfilerでCPU使用率を確認した所、正規表現でログのマスク化をしている処理が重かった ※個人情報をログに出さないためマスク化は必須

    ◦ 置換対象のワード辞書のワードとjsonのフィールド名が一致した場合、jsonの値を正規表現 で*****等に置換しマスク化している処理が高負荷であった 13 課題 { "id":12345," "kana_name":"テストタロー", "adress":"東京都港区", "is_newsmail_accepted":false } { "id":12345, "kana_name":"*****", "adress":"*****", "is_newsmail_accepted":false } マスク化の例 処理前 処理後
  10. © GO Inc. 14 改善前のコード(golang) var result = b //jsonのbyte

    for _, word := range genMaskWord(b, dictionary) { // JSONのキー文字列ごとにループ if !ok { // 値にjson文字列が入る場合、エスケープされている文字が存在する可能性がある(「\”」など) // "..."の間に許す文字:エスケープされている文字 = \\.」、または「"」と「\」以外の文字 rep = regexp.MustCompile(`"` + maskWord + `": ?"(?:[^"\\]|\\.)*?"`) maskingJSONRegexpCache.Write(maskWord, rep) } // 置き換え if rep.Match(s) { maskedWord := fmt.Sprintf("\"%s\":\"*****\"", maskWord) result = rep.ReplaceAll(s, []byte(maskedWord)) } } ※イメージのため実際の処理とは異なります ここがプロファイラ 上、CPU時間の多くを 占めていた マスク処理
  11. © GO Inc. 15 改善後のコード(golang) for // 構造体フィールドのループ tag :=

    typ.Field(i).Tag.Get("mask") if field.Kind() == reflect.Struct || (field.Kind() == reflect.Ptr & // Recursively mask nested structs if field.Kind() == reflect.Ptr { field = field.Elem() } if tag == "true" { switch field.Kind() { case reflect.String: field.SetString("xxxxx")// 置き換え type User struct { ID int`json:"id"` KanaName string `json:"kana_name" mask:"true"` DeviceType int `json:"device_type" mask:"true"` IsNewsmailAccepted bool `json:"is_newsmail_accepted"` } GO言語の記法である tagを利用。 独自のtag「mask」の 導入 • 構造体に独自のタグ付け(mask:”true”) • 構造体の値を型によって*****だったり数値の0に置換しマスク化 構造体定義 マスク処理 ここで、構造体のtag を参照
  12. © GO Inc. 18 まとめ • Cloud Loggingのコスト削減 ◦ 不要ログの削除と不要項目の削除をして約40%削減

    • ログを出力するGAEのコスト削減 ◦ マスク化処理の変更によりコスト削減を今後期待