BigQuery にルーティングされたログを表示する

このドキュメントでは、Cloud Logging から BigQuery テーブルに転送したログエントリを見つける方法について説明します。Logging シンクは、ロギングデータを小さなバッチで BigQuery にストリーミングし、読み込みジョブを実行せずにデータをクエリできるようにします。クエリを作成して BigQuery テーブルの形式を理解できるように、このドキュメントではルーティングされたログの BigQuery スキーマについても説明します。

通常、ログエントリは 1 分以内に BigQuery に表示されます。ただし、新しいテーブルが作成されてから最初のログエントリが利用可能になるまでに数分かかることがあります。

始める前に

シンクのコンセプトについては、ルーティングとストレージ モデルの概要: シンクをご覧ください。

ログをルーティングする方法については、サポートされている宛先にログを転送するをご覧ください。

ルーティングされるログエントリ フィールドの命名法については、ルーティングされるログの BigQuery スキーマをご覧ください。

ログの表示

BigQuery にルーティングされたログを表示する方法は次のとおりです。

  1. Google Cloud コンソールのナビゲーション パネルで [BigQuery] を選択します。

    [BigQuery] に移動

  2. [エクスプローラ] パネルでプロジェクトを開いて、データセットを選択します。

    [詳細] タブにログエントリが表示されます。また、テーブルに対するクエリを行ってデータを返すこともできます。

サンプルクエリ

BigQuery クエリ シンタックスの詳細については、クエリ リファレンスをご覧ください。複数のテーブルをまたぐクエリが可能なテーブル ワイルドカード関数と、繰り返しフィールドのデータが表示できるようになるフラット化演算子は特に有用です。

Compute Engine クエリの例

次の BigQuery クエリは、複数の日付と複数のログタイプからログエントリを取得します。

  • このクエリは過去 3 日間の syslogapache-access のログを検索します。このクエリは 2020 年 2 月 23 日に作成されたので、2 月 21 日と 2 月 22 日に受け取ったすべてのログエントリと、2 月 23 日のクエリ発行時刻までに受け取ったログエントリを対象とします。

  • このクエリは、1 つの Compute Engine インスタンス 1554300700000000000 の結果を取得します。

SELECT
  timestamp AS Time,
  logName as Log,
  textPayload AS Message
FROM
  (TABLE_DATE_RANGE(my_bq_dataset.syslog_,
    DATE_ADD(CURRENT_TIMESTAMP(), -2, 'DAY'), CURRENT_TIMESTAMP())),
  (TABLE_DATE_RANGE(my_bq_dataset.apache_access_,
    DATE_ADD(CURRENT_TIMESTAMP(), -2, 'DAY'), CURRENT_TIMESTAMP()))
WHERE
  resource.type == 'gce_instance'
  AND resource.labels.instance_id == '1554300700000000000'
ORDER BY time;

出力行の例は次のようになります。

Row | Time                    | Log                                         | Message
--- | ----------------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------
 5  | 2020-02-21 03:40:14 UTC | projects/project-id/logs/syslog             | Feb 21 03:40:14 my-gce-instance collectd[24281]: uc_update: Value too old: name = 15543007601548826368/df-tmpfs/df_complex-used; value time = 1424490014.269; last cache update = 1424490014.269;
 6  | 2020-02-21 04:17:01 UTC | projects/project-id/logs/syslog             | Feb 21 04:17:01 my-gce-instance /USR/SBIN/CRON[8082]: (root) CMD ( cd / && run-parts --report /etc/cron.hourly)
 7  | 2020-02-21 04:49:58 UTC | projects/project-id/logs/apache-access      | 128.61.240.66 - - [21/Feb/2020:04:49:58 +0000] "GET / HTTP/1.0" 200 536 "-" "masscan/1.0 (https://github.com/robertdavidgraham/masscan)"
 8  | 2020-02-21 05:17:01 UTC | projects/project-id/logs/syslog             | Feb 21 05:17:01 my-gce-instance /USR/SBIN/CRON[9104]: (root) CMD ( cd / && run-parts --report /etc/cron.hourly)
 9  | 2020-02-21 05:30:50 UTC | projects/project-id/log/syslogapache-access | 92.254.50.61 - - [21/Feb/2020:05:30:50 +0000] "GET /tmUnblock.cgi HTTP/1.1" 400 541 "-" "-"

App Engine のクエリの例

次の BigQuery クエリは、過去 1 か月の失敗した App Engine リクエストを取得します。

SELECT
  timestamp AS Time,
  protoPayload.host AS Host,
  protoPayload.status AS Status,
  protoPayload.resource AS Path
FROM
  (TABLE_DATE_RANGE(my_bq_dataset.appengine_googleapis_com_request_log_,
    DATE_ADD(CURRENT_TIMESTAMP(), -1, 'MONTH'), CURRENT_TIMESTAMP()))
WHERE
  protoPayload.status != 200
ORDER BY time

結果の例は次のようになります。

Row | Time                    | Host                                  | Status | Path
--- | ----------------------- | ------------------------------------- | ------ | ------
 6  | 2020-02-12 19:35:02 UTC | default.my-gcp-project-id.appspot.com |    404 | /foo?thud=3
 7  | 2020-02-12 19:35:21 UTC | default.my-gcp-project-id.appspot.com |    404 | /foo
 8  | 2020-02-16 20:17:19 UTC | my-gcp-project-id.appspot.com         |    404 | /favicon.ico
 9  | 2020-02-16 20:17:34 UTC | my-gcp-project-id.appspot.com         |    404 | /foo?thud=%22what???%22

ルーティングされたログの BigQuery スキーマ

ルーティングされたログに対する BigQuery テーブル スキーマは、LogEntry タイプの構造とログのペイロードの内容に基づいています。また、Cloud Logging では、監査ログと特定の構造化ペイロード フィールドの BigQuery スキーマ フィールド名を短縮するルールも適用されます。 テーブル スキーマを表示するには、BigQuery インターフェース でルーティングされたログエントリのテーブルを選択します。

フィールド命名規則

BigQuery にログを送信するときに、ログエントリ フィールドに適用される命名規則がいくつかあります。

  • ログエントリ フィールドの名前は 128 文字以下にする必要があります。

  • ログエントリのフィールド名は、英数字のみにする必要があります。サポートされていない文字はフィールド名から削除され、アンダースコアに置き換えられます。たとえば、jsonPayload.foo%%jsonPayload.foo__ に変換されます。

    ログエントリのフィールド名は、変換後も英数字で始める必要があります。先頭のアンダースコアはすべて削除されます。

  • LogEntry 型の一部であるログエントリ フィールドの場合、対応する BigQuery フィールド名はログエントリ フィールドとまったく同じです。

  • ユーザー指定のログエントリ フィールドの場合、対応する BigQuery フィールド名は小文字に正規化されますが、それ以外は名前は保持されます。

  • 構造化ペイロードのフィールドの場合、@type 指定子が存在しない限り、対応する BigQuery フィールド名は小文字に正規化されますが、それ以外は名前は保持されます。

    @type 指定子が存在する構造化ペイロードについては、このページの @type を含むペイロード フィールドをご覧ください。

次の例は、これらの命名規則がどのように適用されるかを示しています。

ログエントリ フィールド LogEntry 型マッピング BigQuery フィールド名
insertId insertId insertId
textPayload textPayload textPayload
httpRequest.status httpRequest.status httpRequest.status
httpRequest.requestMethod.GET httpRequest.requestMethod.[ABC] httpRequest.requestMethod.get
resource.labels.moduleid resource.labels.[ABC] resource.labels.moduleid
jsonPayload.MESSAGE jsonPayload.[ABC] jsonPayload.message
jsonPayload.myField.mySubfield jsonPayload.[ABC].[XYZ] jsonPayload.myfield.mysubfield

@type でのペイロード フィールド

このセクションでは、ログエントリのペイロードに指定子 @type が含まれている特別な BigQuery スキーマ フィールド名について説明します。これには、BigQuery にルーティングされる監査ログエントリも含まれます。

ログエントリのペイロードには構造化データを含めることができます。すべての構造化フィールドには、オプションの型指定子を次の形式で含めることができます。

@type: type.googleapis.com/[TYPE]

命名規則は、監査ログエントリの protoPayload フィールドが BigQuery スキーマ フィールド protopayload_auditlog にマッピングされる理由を説明しています。

@type の命名規則

型指定子を含む構造化フィールドには、フィールド名に [TYPE] が付いた BigQuery フィールド名が指定されます。[TYPE] の値は、任意の文字列にできます。

@type の命名規則は、jsonPayload または protoPayload の最上位にのみ適用されます。ネストされたフィールドは無視されます。最上位の構造化ペイロード フィールドを処理する場合、Logging によって接頭辞 type.googleapis.com が削除されます。

たとえば、次の表は、最上位の構造化ペイロード フィールドの BigQuery フィールド名へのマッピングを示しています。

ペイロード ペイロード @type ペイロード フィールド BigQuery フィールド名
jsonPayload (なし) statusCode jsonPayload.statusCode
jsonPayload type.googleapis.com/abc.Xyz statusCode jsonpayload_abc_xyz.statuscode
protoPayload (なし) statusCode protoPayload.statuscode
protoPayload type.googleapis.com/abc.Xyz statusCode protopayload_abc_xyz.statuscode

型指定子を含むフィールドでは、上記のルールにいくつかの例外が適用されます。

  • App Engine のリクエストログでは、ペイロードに型指定子が含まれる場合でも、BigQuery にルーティングされたログのペイロード名は protoPayload になります。

  • Cloud Logging では、監査ログの BigQuery スキーマ フィールド名を短縮するための特別なルールが適用されます。これについては、このページの監査ログのフィールド セクションで説明します。

この例は、構造化ペイロード フィールドが BigQuery に受信されたときに、どのような名前になり、どのように使用されるかを示しています。

ログエントリのペイロードが次のように構成されているとします。

jsonPayload: {
  @type: "type.googleapis.com/google.cloud.v1.CustomType"
    name_a: {
      sub_a: "A value"
    }
    name_b: {
      sub_b: 22
    }
  }

BigQuery フィールドへのマッピングは次のとおりです。

  • 最上位の構造化フィールド jsonPayload には、@type 指定子が含まれています。 BigQuery 名は jsonpayload_v1_customtype です。

  • ネストされたフィールドは、標準の BigQuery 命名規則として扱われます。ネストされたフィールドには、型指定子ルールが適用されないためです。

つまり、ログエントリのペイロードに対して次の BigQuery 名が定義されます。

  jsonpayload_v1_customtype
  jsonpayload_v1_customtype._type
  jsonpayload_v1_customtype.name_b
  jsonpayload_v1_customtype.name_b.sub_b
  jsonpayload_v1_customtype.name_a
  jsonpayload_v1_customtype.name_a.sub_a

監査ログのフィールド

BigQuery にルーティングされた監査ログを扱わない場合は、このセクションをスキップできます。

監査ログのペイロード フィールドである protoPayload.requestprotoPayload.responseprotoPayload.metadata には、@type 型指定子が付与されていますが、JSON データとして扱われます。つまり、それらの BigQuery スキーマ名は、フィールド名に Json が追加され、JSON 形式の文字列データを含む形式になります。

次の表に、これら 2 つの監査ログのペイロード フィールド名を示します。

ログエントリ フィールド BigQuery フィールド名
protoPayload protopayload_auditlog
protopayload.metadata protopayload_auditlog.metadataJson
protoPayload.serviceData protopayload_auditlog.servicedata_v1_bigquery
例: protopayload_auditlog.servicedata_v1_bigquery.tableInsertRequest
protoPayload.request protopayload_auditlog.requestJson
protoPayload.response protopayload_auditlog.responseJson

serviceData 命名規則は、BigQuery によって生成され、Cloud Logging から BigQuery にルーティングされる監査ログに固有です。これらの監査ログエントリには、次のような @type 指定子がある serviceData フィールドが含まれています。type.googleapis.com/google.cloud.bigquery.logging.v1.auditdata

BigQuery によって生成された監査ログエントリには、次の名前のフィールドがあります。

protoPayload.serviceData.tableInsertRequest

このログエントリが BigQuery にルーティングされた場合、tableInsertRequest フィールドはどのように参照されますか。名前を短縮する前は、BigQuery の対応するフィールド名は次のようになります。

protopayload_google_cloud_audit_auditlog.servicedata_google_cloud_bigquery_logging_v1_auditdata.tableInsertRequest

名前の短縮後、同じフィールドが BigQuery テーブルでは次のように参照されます。

protopayload_auditlog.servicedata_v1_bigquery.tableInsertRequest

テーブルの構成

このセクションでは、BigQuery にルーティングされるログのパーティション分割テーブルの概要について説明します。

BigQuery データセットにログをルーティングすると、Logging はログエントリを保持するテーブルを作成します。宛先 BigQuery テーブルのスキーマは、BigQuery で最初に受信するログエントリによって決定されます。BigQuery は、最初のログエントリのフィールドとそのタイプに基づいた列を持つテーブルを作成します。後続のログエントリがスキーマの不一致を引き起こす可能性があります。不一致が発生するタイミングとその処理方法については、スキーマの不一致をご覧ください。

Logging がエクスポートするデータを整理する 2 つのテーブルタイプ(日付別シャーディング テーブルパーティション分割テーブル)があります。どちらのテーブルタイプも、ログエントリの timestamp フィールドに基づいてログデータを分割します。ただし、テーブルタイプ間には次の 2 つの主な違いがあります。

  • パフォーマンス: パーティション分割テーブルは、大きいテーブルを小さいパーティションに分割するため、クエリのパフォーマンスを向上させ、クエリの読み込みバイト数を減らすことで BigQuery の費用をより効率的に管理できます。

  • テーブルの命名法: テーブルタイプでは、次のセクションで説明するように、異なる命名規則が使用されます。

テーブルの構成

ログエントリは、エントリのログ名とタイムスタンプに基づく組織と BigQuery テーブルにシャーディングされます。

テーブル名には、ログエントリの UTC タイムスタンプ(ISO 8601 の基本形式である YYYYMMDD を使用)のカレンダー日付が末尾に付加されます。

次の表は、ログ名とサンプルのタイムスタンプを BigQuery のテーブル名にマップする例を示しています。

ログ名 ログエントリ timestamp1 BigQuery テーブル名
(日付別)
BigQuery テーブル名
(パーティション分割)
syslog 2017-05-23T18:19:22.135Z syslog_20170523 syslog
apache-access 2017-01-01T00:00:00.000Z apache_access_20170101 apache_access
compute.googleapis.com/activity_log 2017-12-31T23:59:59.999Z compute_googleapis_com_activity_log_20171231 compute_googleapis_com_activity_log

1 ログエントリのタイムスタンプは UTC(協定世界時)で表されます。

パーティション分割テーブルの作成

シンクを作成して BigQuery にログをルーティングする場合は、日付別シャーディング テーブルまたはパーティション分割テーブルを使用できます。デフォルトの選択は、日付別シャーディング テーブルです。

シンクの作成方法については、次のリソースをご覧ください。

スキーマの不一致

宛先 BigQuery テーブルのスキーマは、BigQuery で最初に受信するログエントリによって決定されます。BigQuery は、最初のログエントリのフィールドとそのタイプに基づいた列を持つテーブルを作成します。

スキーマの不一致が発生するのは、ログエントリが宛先テーブルに書き込まれ、次のいずれかのエラーが発生した場合です。

  • 後のログエントリで、テーブル内の既存のフィールドのフィールド タイプが変更されます。

    たとえば、最初のログエントリの jsonPayload.user_id フィールドが string の場合、そのログエントリは、そのフィールドの文字列型を持つテーブルを生成します。後になって jsonPayload.user_idarray としてロギングを開始した場合、スキーマの不一致が発生します。

  • 新しいログエントリに、現在のスキーマにないフィールドが含まれ、そのフィールドを宛先テーブルに挿入すると、BigQuery の列の上限を超えることになります。

    列制限を超えない限り、宛先テーブルは新しいフィールドを受け入れることができます。

BigQuery はスキーマの不一致を識別すると、対応するデータセット内にテーブルを作成し、エラー情報を保存します。テーブルの種類によってテーブル名が決まります。日付別テーブルの場合、命名形式は export_errors_YYYYMMDD です。パーティション分割テーブルの場合、命名形式は export_errors です。詳しくは、テーブルの構成をご覧ください。

ログエントリをルーティングする場合、Logging はメッセージをバッチとして BigQuery に送信します。BigQuery は次のルールを使用して、メッセージの現在のバッチのログエントリが書き込まれるテーブルを決定します。

  • フィールド タイプが変更されると、スキーマの不一致の原因となったログエントリのみがエラーテーブルに書き込まれます。スキーマの不一致を引き起こさないメッセージの現在のバッチ内のログエントリは、元の宛先テーブルに書き込まれます。

  • 列の上限を超えると、現在のメッセージのバッチ内のすべてのログエントリがエラーテーブルに書き込まれます。

エラーテーブルのスキーマ

エラーテーブルには、LogEntry のデータと不一致に関する情報が含まれています。

  • logEntry: 完全なログエントリが含まれます。ただし、ログエントリは JSON から文字列に変換されます。
  • schemaErrorDetail: BigQuery から返される完全なエラー メッセージが含まれます。
  • sink: ログシンクの完全なリソースパスが含まれます。
  • logName: LogEntry から抽出されます。
  • timestamp: LogEntry から抽出されます。
  • receiveTimestamp: LogEntry から抽出されます。
  • severity: LogEntry から抽出されます。
  • insertId: LogEntry から抽出されます。
  • trace: LogEntry から抽出されます。
  • resourceType: LogEntry から抽出されます。

Logging は、次の方法でルーティング シンクを含む Google Cloud プロジェクトにスキーマの不一致を通知します。

  • プロジェクト オーナーにメールを送信します。詳細には、Google Cloud のプロジェクト ID、シンク名、宛先が含まれます。
  • Google Cloud Console の [アクティビティ] ページにエラー Stackdriver Config error が表示されます。詳細には、シンク名と宛先、エラーの原因となったログエントリの例へのリンクが含まれます。

今後のフィールド タイプの不一致を防ぐ

後のログエントリのフィールド タイプの不一致を修正するには、現在のスキーマに一致するようにフィールド タイプを修正します。

たとえば、Google Cloud サービスによって自動的に生成されるログのフィールド タイプを変更できないときは、フィールド タイプを変更できません。フィールド タイプを変更できない場合のスキーマの不一致を防ぐため、テーブルの名前を変更するか、シンクのパラメータを変更して、Logging で別のデータセットのテーブルを再作成します。手順については、シンクを管理するをご覧ください。

トラブルシューティング

シンクの宛先にログがないように見える場合や、シンクがログを正しくルーティングしていないと思われる場合は、ログのルーティングのトラブルシューティングをご覧ください。

料金

Cloud Logging では、サポートされている宛先にログが転送されることはありませんが、転送先での請求が適用されることがあります。宛先の費用については、BigQuery の料金をご覧ください。

Cloud Logging から Virtual Private Cloud フローログを送信して除外した場合は、宛先料金に加え VPC フローログの生成料金が適用されます。