Slide 1

Slide 1 text

© GO Inc. GAEログのコスト削減 2025.01.28 バックエンド開発部 / 山野 祐 GO株式会社

Slide 2

Slide 2 text

© GO Inc. 2 自己紹介 GO株式会社 バックエンド開発部 / 山野 祐 不動産業界向けの基幹システムやポータルサイト内サービスの 翻訳、ブログ、広告配信システムの開発に従事したのち、2023 年11月よりGO株式会社にてバックエンドの開発・運用を担当 趣味はツーリング、旅行、ジム、辛いもの食べること

Slide 3

Slide 3 text

© GO Inc. 3 GOのシステム全体構成と発表箇所 バックエンド 分析環境 バックエンド (App Engine) 次世代 バックエンド (Kubernetes) キュー (Pub/Sub) 分析ログ データ 基盤 (BigQuery) RDB (Cloud SQL) フロントエンド 次世代 サーバログ基盤 (Loki) サーバログ基盤 (Cloud Logging) S3 キュー (Pub/Sub) 車載位置ログ サーバ ログ サーバ ログ ユーザー アプリ ドライバーア プリ 発表箇所

Slide 4

Slide 4 text

Index © GO Inc. 4 1. Cloud Loggingのコスト削減 2. ログを出力するGAEのコスト削減 3. まとめ

Slide 5

Slide 5 text

© GO Inc. 5 Cloud Loggingのコス ト削減 01

Slide 6

Slide 6 text

© GO Inc. ● Cloud Loggingとは ○ ストレージ、検索、分析、モニタリングをサポートするリアルタイムのログ管理システ ム ○ Google Cloudリソースからログデータを自動的に収集 ○ GAEのログ種類 ■ リクエストログ ● アプリに送信されたリクエストのログ ● デフォルトではApp Engine は、アプリが受信した HTTP リクエストごとにロ グエントリを自動的に出力 ■ アプリログ ● サポートされているフレームワークまたはファイルに書き込んだログエントリ に基づいてApp Engineアプリが出力するログエントリ ■ システムログ ● アプリに関する情報が格納されるプラットフォームで生成されたログ Cloud Logging の概要 6 Cloud Logging概要

Slide 7

Slide 7 text

© GO Inc. ● Cloud LoggingはGoogle Cloudのコストの中でもTOP3でコスト削減が必要 ○ 不要なログの削除をすることでコスト削減できないか検討 ○ ログ内の項目削除をすることでコスト削減できないか検討 ● ロギングの検索を容易にするため、構造化ロギングにしコスト増し 7 なぜCloud Loggingのコスト削減?

Slide 8

Slide 8 text

© GO Inc. ● 調査 ○ リクエストボディとレスポンスボディが大きいログを目視で確認 ○ リクエスト数の多いログを調査するため、 Loggingから転送されたBigQueryでログを集計して確認 ● 削除したもの ○ 調査で不要と判断され、かつリクエストボディとレスポンスボディが大きいログ ○ 調査で不要と判断され、かつリクエスト数が多い apiのログ ○ すべての項目がマスクされているログ ■ (例 削減1:不要なログ削除 {"adress":"*****", "kana_name":"*****", "mail":"*****", … 8

Slide 9

Slide 9 text

© 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” }

Slide 10

Slide 10 text

© 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” }

Slide 11

Slide 11 text

© GO Inc. 11 結果:Cloud Logginのコスト約40%カット ● 結果 ○ サービスの成長とともに右肩上がりに増 えていたログコストを9個の不要ログを削 除しピーク時の約40%削減 ● 所感 ○ GCPコストの中でTOP3の割合を Loggingがしめていて、もっと早くにやる べきだったが、コストの意識が回らなく対 応できいていなかった ○ コストの意識が薄かったが以前より意識 するようになり、週一の部の定例でコスト の増減を確認するパートができ、部として 意識付けできるようになった ピーク時の約40%減

Slide 12

Slide 12 text

© GO Inc. 12 ログを出力するGAEの コスト削減 02

Slide 13

Slide 13 text

© 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 } マスク化の例 処理前 処理後

Slide 14

Slide 14 text

© 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時間の多くを 占めていた マスク処理

Slide 15

Slide 15 text

© 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 を参照

Slide 16

Slide 16 text

© GO Inc. ● 文字列長に比例しないためGAEのCPUが下がりインスタンス料金の削減につながる予定 16 結果

Slide 17

Slide 17 text

© GO Inc. 17 まとめ 03

Slide 18

Slide 18 text

© GO Inc. 18 まとめ ● Cloud Loggingのコスト削減 ○ 不要ログの削除と不要項目の削除をして約40%削減 ● ログを出力するGAEのコスト削減 ○ マスク化処理の変更によりコスト削減を今後期待

Slide 19

Slide 19 text

文章・画像等の内容の無断転載及び複製等の行為はご遠慮ください。 © GO Inc.