やわらかテック

興味のあること。業務を通して得られた発見。個人的に試してみたことをアウトプットしています🍵

GoogleCloudStorageでファイル検索を簡単にする命名方法

あらすじ

とあるAPIからのレスポンスの内容が、どうやら仕様書で共有されていたモノと中身が異なっているということで、どういうレスポンスが返ってきているのかを確認してほしいと言われました。とはいえ、本番環境では1時間に約10万回ものリクエストを送っているため、単純にログにデータを出力すると、えらいことになります。

そのため、受け取ったレスポンス(json)を.json形式のファイルを作成して、GoogleCloudStorageにアップロードすることにしました。ただログを集約したいだけだったので、特に階層は作らず、バケットの直下にファイルをアップロードさせるようにしています。

ファイル名は重複がなく、いつ、どこで受け取ったレスポンスなのかが分かるように以下のように命名をしています。

uuid + timestamp + リクエストしたユーザー名 + 種別(絞り込みのための値) + .json

例:
5300f326-9fcd-d392-798b-5b7a253983ff_2021-10-08-21-45-00_ayatsuzi_student.json

ログをアップロードするところまでは良かったんですが、この後に問題に直面しました。

検索が出来ない

いざ、アップロードされたログを絞り込んで一覧を取得して、問題になっていそうなログを確認しようと思った頃に問題が発生しました。 開発はRubyOnRailsを用いて進めています。GoogleCloudStorageAPIを使用するために、Googleより公開されているRuby用のライブラリを使用する必要があります。他言語でも同様の手順を踏む必要があるでしょう。

github.com

公式にサンプルがあるので、真似て書いてみました。どうやらprefixという引数(Rubyだとdefaultがnil)を渡してあげることで、一覧表示するファイルを絞り込むことが出来るようです。コードサンプルの方にはprefixワイルドカードを使って、*.jsonだけを絞り込むという感じのサンプルは載っていないのですが、gsutilの方にはワイルドカードを使ったサンプルが載っていたので、「これ使ってユーザーを絞り込むか」と思い立ちます。

cloud.google.com

以下のコードを書いてみて、試してみましたが空配列が返ってきます。書き方が違うのかな?と思い正規表現を渡したり....いろいろ試してみましたが、やはり空配列が返ってきます。

# NG
bucket.files prefix: 'ayatsuzi'
bucket.files prefix: /ayatsuzi/
bucket.files prefix: './*_ayatsuzi'

途方に暮れていたところで、ポカしていることに気付きました。Googleのコードサンプルにこんな記述があります。

# prefix      = "Filter results to files whose names begin with this prefix"

ref: オブジェクトのリスト  |  Cloud Storage  |  Google Cloud

文字通り、prefixから始まるファイルの一覧が取得出来るようです。加えて、上記には説明がありませんが、ワイルドカードを用いた絞り込みは少なくともRuby製のライブラリには提供されていませんでした。(Python, Goでも出来ないっぽい??)

結果的に、ファイルの一覧を全件取得して、条件式を書いて絞り込みをしようかと思いましたが、どうやら取得可能なファイル数orファイルサイズに上限があるようで、全てのファイル一覧を取得することは出来ませんでした。

結果的にgsutilを用いてファイル一覧を絞り込むという形に落ち着きました。(最初からそうしろ)

gsutil ls gs:://project-hogehoge/**_ayatsuzi

命名のススメ

prefixが接頭辞にしか用いることが出来ないため、絞り込みを強力にすることが出来る順に命名するのが良いかと考えます。今回の場合だと、リクエストしたユーザー名を用いることでデータ数をかなり絞り込むことが出来ます。その次は種別、その次は...と順に情報を与えていきます。
先ほど、uuidを重複回避のために先頭に持ってきたのは明らかな失敗でした...。

リクエストしたユーザー名 + 種別(絞り込みのための値) + timestamp + uuid + .json

例:
ayatsuzi_student_2021-10-08-21-45-00_5300f326-9fcd-d392-798b-5b7a253983ff.json

副作用としては、一覧に表示されるデータの順番が意図したものではなくなる可能性がありますので、要注意です。 (とはいえ、データ数が多いとそんなに気になりませんし、普通にソートも出来ます)

階層を用いてファイルを管理する場合(例: /2020-02-08/ayatsuzi/student/***.json)にはprefixを用いて簡単に検索することが出来ます。データを直下に集約しなければ、遭遇しない問題なので、Googleの意図としては「素直に階層作ってくれよな」というところでしょう。

参考文献