このドキュメントでは、構造化ロギングのコンセプトと、ログエントリのペイロード フィールドに構造を追加する方法について説明します。ログペイロードが JSON オブジェクトとしてフォーマットされ、そのオブジェクトが jsonPayload
フィールドに保存されている場合、ログエントリは構造化ログと呼ばれます。これらのログでは、特定の JSON パスを検索するクエリを作成し、ログ ペイロード内の特定のフィールドをインデックスに登録できます。一方、ログ ペイロードが文字列としてフォーマットされ、textPayload
フィールドに格納されている場合、ログエントリは非構造化になります。
テキスト フィールドを検索することはできますが、そのコンテンツをインデックスに登録することはできません。
構造化ログエントリを作成するには、次のいずれかを行います。
entries.write
API メソッドを呼び出し、完全なフォーマットのLogEntry
を指定します。- 構造化ログを書き込める Cloud Logging クライアント ライブラリを使用します。
gcloud logging write
コマンドを使用します。- BindPlane サービスを使用します。
エージェントを使用してログを書き込みます:
一部の Google Cloud サービスには、
stdout
またはstderr
に書き込まれたデータを Cloud Logging にログとして送信する統合 Logging エージェントが含まれています。このアプローチは、Google Kubernetes Engine、App Engine フレキシブル環境、Cloud Run 関数などの Google Cloud サービスで使用できます。Compute Engine 仮想マシン(VM)の場合は、Ops エージェントまたは従来の Logging エージェントをインストールして構成し、インストールしたエージェントを使用して Cloud Logging にログを送信できます。
これらのアプローチの詳細については、以降のセクションをご覧ください。
クライアント ライブラリまたは API を使用してログを書き込む
ログデータを書き込むには、Cloud Logging API を呼び出す Cloud Logging クライアント ライブラリを使用するか、Cloud Logging API を直接呼び出します。クライアント ライブラリでは、一部の情報を自動的に取得し、フィールドに適切に入力するためのインターフェースを提供することで、特別な JSON フィールドを簡単に入力できます。ただし、ペイロードの構造を完全に制御するには、Cloud Logging API を直接呼び出して、完全な LogEntry
構造を Cloud Logging API に渡します。
詳細については、entries.write
リファレンスをご覧ください。
コード例については、構造化ログの書き込みをご覧ください。
gcloud CLI を使用してログを書き込む
ログデータを書き込むには、gcloud CLI を使用します。このインターフェースは、非構造化ログと構造化ログをサポートしています。構造化ログを書き込むには、シリアル化された JSON オブジェクトをコマンドに指定します。
クイックスタートについては、Google Cloud CLI を使用したログエントリの書き込みとクエリをご覧ください。
コード例については、gcloud logging write
リファレンスをご覧ください。
BindPlane を使用してログを書き込む
BindPlane サービスを使用して、Logging にログを送信できます。これらのログの場合、ペイロードは JSON 形式で、ソースシステムに従って構造化されます。BindPlane を使用して取り込まれたログの検索と表示の詳細については、BindPlane のクイックスタート ガイドをご覧ください。
エージェントを使用してログを書き込む
Compute Engine インスタンスからログを取得するには、Ops エージェントまたは以前の Cloud Logging エージェントを使用します。どちらのエージェントもサードパーティ アプリケーションから指標を収集でき、どちらも構造化ロギングをサポートします。
Ops エージェントは、Compute Engine インスタンスからテレメトリーを収集する推奨エージェントです。このエージェントは、ロギングと指標を単一のエージェントに統合します。また、YAML ベースの構成を提供し、高スループット ロギングを行います。
構造化ロギングをサポートするように Ops エージェントを構成する方法、または構造化ログの形式をカスタマイズする方法については、Ops エージェントの構成をご覧ください。
以前の Cloud Logging エージェントはログを収集します。このエージェントは、他の形式のテレメトリーは収集しません。
このセクションの残りの部分は、以前の Logging エージェントに固有のものです。
Logging エージェント: 特別な JSON フィールド
JSON オブジェクトのフィールドには、以前の Logging エージェントによって特別なものと認識され、LogEntry
構造に取り出されるものがあります。これらの特別な JSON フィールドは、次に挙げる LogEntry
のフィールドを設定するために使用されます。
severity
spanId
- ユーザー定義の
labels
httpRequest
JSON はテキスト行よりも厳密で汎用性が高いため、JSON オブジェクトは、複数行メッセージの記述や、メタデータの追加に使用できます。
簡略化された形式を使用してアプリケーションの構造化ログエントリを作成するには、JSON の各フィールドと値を列挙した次の表をご覧ください。
JSON ログフィールド | LogEntry フィールド |
Cloud Logging エージェントの機能 | 値の例 |
---|---|---|---|
severity
|
severity
|
Logging エージェントは、Logging API によって認識される LogSeverity 文字列のリストを含む、さまざまな共通の重大度文字列の照合を試みます。 | "severity":"ERROR"
|
message
|
textPayload (または jsonPayload の一部)
|
ログ エクスプローラのログエントリに表示されるメッセージ。 | "message":"There was an error in the application." 注: Logging エージェントが他の特殊フィールドを移動した後に唯一残ったフィールドであり、かつ detect_json が有効でない場合、message は textPayload として保存されます。これに該当しない場合、message は jsonPayload に残ります。detect_json は、Google Kubernetes Engine などのマネージド ロギング環境には適用されません。ログエントリに例外スタック トレースが含まれている場合、例外スタック トレースをこの message JSON ログフィールドに設定する必要があります。設定すると、例外スタック トレースが解析され Error Reporting に保存されるようになります。 |
log (以前の Google Kubernetes Engine のみ) |
textPayload
|
以前の Google Kubernetes Engine にのみ適用されます。特殊フィールドを移動した後に log フィールドだけが残った場合、そのフィールドは textPayload として保存されます。 |
|
httpRequest
|
httpRequest
|
LogEntry HttpRequest フィールド形式の構造化レコード。 |
"httpRequest":{"requestMethod":"GET"}
|
時間関連フィールド | timestamp
|
詳細については、時間関連フィールドをご覧ください。 | "time":"2020-10-12T07:20:50.52Z"
|
logging.googleapis.com/insertId
|
insertId
|
詳細については、LogEntry ページの insertId をご覧ください。 |
"logging.googleapis.com/insertId":"42"
|
logging.googleapis.com/labels
|
labels
|
このフィールドの値は、構造化レコードであることが必要です。詳細については、LogEntry ページの labels をご覧ください。 |
"logging.googleapis.com/labels":
{"user_label_1":"value_1","user_label_2":"value_2"}
|
logging.googleapis.com/operation
|
operation
|
このフィールドの値は、関連するログエントリをグループ化するためにログ エクスプローラによっても使用されます。詳細については、LogEntry ページの operation をご覧ください。 |
"logging.googleapis.com/operation":
{"id":"get_data","producer":"github.com/MyProject/MyApplication",
"first":"true"}
|
logging.googleapis.com/sourceLocation
|
sourceLocation
|
ログエントリに関連するソースコードの位置情報(存在する場合)。詳細については、LogEntry ページの LogEntrySourceLocation をご覧ください。 |
"logging.googleapis.com/sourceLocation":
{"file":"get_data.py","line":"142","function":"getData"}
|
logging.googleapis.com/spanId
|
spanId
|
ログエントリに関連付けられているトレース内のスパン ID。詳細については、LogEntry ページの spanId をご覧ください。 |
"logging.googleapis.com/spanId":"000000000000004a"
|
logging.googleapis.com/trace
|
trace
|
ログエントリに関連するリソースの名前(存在する場合)。詳細については、LogEntry ページの trace をご覧ください。 |
"logging.googleapis.com/trace":"projects/my-projectid/traces/0679686673a" 注: stdout や stderr に書き込まない場合、このフィールドの値は、projects/[PROJECT-ID]/traces/[TRACE-ID] 形式にする必要があります。これにより、ログ エクスプローラとトレース ビューアで、ログエントリをグループ化してトレースと一緒に表示できます。autoformat_stackdriver_trace が true で、[V] が ResourceTrace の traceId の形式と一致する場合、LogEntry の trace フィールドの値は projects/[PROJECT-ID]/traces/[V] になっています。 |
logging.googleapis.com/trace_sampled
|
traceSampled
|
このフィールドの値は true または false のいずれかにする必要があります。詳細については、LogEntry ページの traceSampled をご覧ください。 |
"logging.googleapis.com/trace_sampled": false
|
簡略化された形式でログエントリを作成するには、上記のフィールドを使用してエントリの JSON 表現を作成します。すべてのフィールドは省略可能です。
簡略化された JSON ログエントリの例を、次に示します。
{ "severity":"ERROR", "message":"There was an error in the application.", "httpRequest":{ "requestMethod":"GET" }, "times":"2020-10-12T07:20:50.52Z", "logging.googleapis.com/insertId":"42", "logging.googleapis.com/labels":{ "user_label_1":"value_1", "user_label_2":"value_2" }, "logging.googleapis.com/operation":{ "id":"get_data", "producer":"github.com/MyProject/MyApplication", "first":"true" }, "logging.googleapis.com/sourceLocation":{ "file":"get_data.py", "line":"142", "function":"getData" }, "logging.googleapis.com/spanId":"000000000000004a", "logging.googleapis.com/trace":"projects/my-projectid/traces/06796866738c859f2f19b7cfb3214824", "logging.googleapis.com/trace_sampled":false }
結果のログエントリの例を、次に示します。
{ "insertId": "42", "jsonPayload": { "message": "There was an error in the application", "times": "2020-10-12T07:20:50.52Z" }, "httpRequest": { "requestMethod": "GET" }, "resource": { "type": "k8s_container", "labels": { "container_name": "hello-app", "pod_name": "helloworld-gke-6cfd6f4599-9wff8", "project_id": "stackdriver-sandbox-92334288", "namespace_name": "default", "location": "us-west4", "cluster_name": "helloworld-gke" } }, "timestamp": "2020-11-07T15:57:35.945508391Z", "severity": "ERROR", "labels": { "user_label_2": "value_2", "user_label_1": "value_1" }, "logName": "projects/stackdriver-sandbox-92334288/logs/stdout", "operation": { "id": "get_data", "producer": "github.com/MyProject/MyApplication", "first": true }, "trace": "projects/my-projectid/traces/06796866738c859f2f19b7cfb3214824", "sourceLocation": { "file": "get_data.py", "line": "142", "function": "getData" }, "receiveTimestamp": "2020-11-07T15:57:42.411414059Z", "spanId": "000000000000004a" }
Logging エージェント: 構成
以前の Logging エージェント google-fluentd
は、Fluentd ログデータ コレクタの Cloud Logging 専用パッケージです。Logging エージェントにはデフォルトの Fluentd 構成があります。Logging エージェントは、Fluentd 入力プラグインを使用して外部ソース(ディスク上のファイルなど)からイベントログを pull するか、受信ログレコードを解析します。
Fluentd にはサポートされるパーサーのリストがあります。これらのパーサーはログを抽出し、構造化ペイロード(JSON)に変換します。
ログソースに format [PARSER_NAME]
を構成することで、Fluentd が提供する組み込みのパーサーを構築できます。以前の Logging エージェントの構成については、Logging エージェントを構成するをご覧ください。
次のコードサンプルは、Fluentd の構成、入力されるログレコード、出力される構造化ペイロード(Cloud Logging のログエントリの一部)を示しています。
Fluentd の構成:
<source> @type tail format syslog # This uses a predefined log format regex named # `syslog`. See details at https://docs.fluentd.org/parser/syslog. path /var/log/syslog pos_file /var/lib/google-fluentd/pos/syslog.pos read_from_head true tag syslog </source>
ログレコード(入力):
<6>Feb 28 12:00:00 192.168.0.1 fluentd[11111]: [error] Syslog test
構造化ペイロード(出力):
jsonPayload: { "pri": "6", "host": "192.168.0.1", "ident": "fluentd", "pid": "11111", "message": "[error] Syslog test" }
syslog
パーサーの仕組みの詳細については、詳細な Fluentd のドキュメントをご覧ください。
Logging エージェント: デフォルトで有効になっている標準パーサー
次の表に、構造化ロギングを有効にした場合にエージェントに含まれる標準パーサーを示します。
パーサー名 | 構成ファイル |
---|---|
syslog |
/etc/google-fluentd/config.d/syslog.conf |
nginx |
/etc/google-fluentd/config.d/nginx.conf |
apache2 |
/etc/google-fluentd/config.d/apache.conf |
apache_error |
/etc/google-fluentd/config.d/apache.conf |
以前の Logging エージェントのインストール時に構造化ロギングを有効にする方法については、インストール セクションをご覧ください。
Logging エージェント: インストール
構造化ロギングを有効にするには、以前の Logging エージェントをインストールまたは再インストールするときに、以前の Logging エージェントのデフォルト構成を変更する必要があります。構造化ロギングを有効にすると、以前にリストされた構成ファイルが置き換えられますが、エージェント自体のオペレーションは変更されません。
構造化ロギングを有効にすると、構造化ログを有効にする前と異なる形式にログエントリが変換されます。ログが Logging の外部の宛先に転送されている場合は、この変更が後処理のアプリケーションに影響を及ぼす可能性があります。たとえば、ログを BigQuery に転送する場合、BigQuery は変更を行った時刻以降の当日の残りの期間について、新しいログエントリを誤ったスキーマを有するものとして拒否します。
以前の Logging エージェントをインストールして構造化ロギングを有効にする手順については、Logging エージェントのインストールをご覧ください。
以前の Logging エージェントの構成ファイル(/etc/google-fluentd/config.d/
)に、デフォルトで有効になっている標準パーサーが追加されています。
Logging エージェント: Apache アクセスログの形式の構成
以前の Logging エージェントでは、Apache アクセスログのデータはデフォルトで jsonPayload
フィールドに保存されます。例:
{
"logName": ...,
"resource": ...,
"httpRequest": ...,
"jsonPayload": {
"user" : "some-user",
"method" : "GET",
"code" : 200,
"size" : 777,
"host" : "192.168.0.1",
"path" : "/some-path",
"referer": "some-referer",
"agent" : "Opera/12.0"
},
...
}
また、特定のフィールドを httpRequest
フィールドに抽出するように以前の Logging エージェントを構成することもできます。例:
{
"logName": ...,
"resource": ...,
"httpRequest": {
"requestMethod": "GET",
"requestUrl": "/some-path",
"requestSize": "777",
"status": "200",
"userAgent": "Opera/12.0",
"serverIp": "192.168.0.1",
"referrer":"some-referrer",
},
"jsonPayload": {
"user":"some-user"
},
...
}
前のサンプルで示されたように httpRequest
フィールドを構成すると、トレースが支援されます。Google Cloud コンソールでは、特定の HTTP リクエストのすべてのログが親子階層で表示されます。
この抽出を構成するには、/etc/google-fluentd/config.d/apache.conf
の末尾に、次の内容を追加します。
<filter apache-access>
@type record_transformer
enable_ruby true
<record>
httpRequest ${ {"requestMethod" => record['method'], "requestUrl" => record['path'], "requestSize" => record['size'], "status" => record['code'], "userAgent" => record['agent'], "serverIp" => record['host'],
"referer" => record['referer']} }
</record>
remove_keys method, path, size, code, agent, host, referer
</filter>
ログエントリの構成方法については、ログレコードの変更をご覧ください。
Logging エージェント: nginx アクセスログの形式の構成
以前の Logging エージェントでは、nginx アクセスログのデータはデフォルトで jsonPayload
フィールドに保存されます。例:
{
"logName": ...,
"resource": ...,
"httpRequest": ...,
"jsonPayload": {
"remote":"127.0.0.1",
"host":"192.168.0.1",
"user":"some-user",
"method":"GET",
"path":"/some-path",
"code":"200",
"size":"777",
"referrer":"some-referrer",
"agent":"Opera/12.0",
"http_x_forwarded_for":"192.168.3.3"
},
...
}
また、特定のフィールドを httpRequest
フィールドに抽出するように以前の Logging エージェントを構成することもできます。例:
{
"logName": ...,
"resource": ...,
"httpRequest": {
"requestMethod": "GET",
"requestUrl": "/some-path",
"requestSize": "777",
"status": "200",
"userAgent": "Opera/12.0",
"remoteIp": "127.0.0.1",
"serverIp": "192.168.0.1",
"referrer":"some-referrer",
},
"jsonPayload": {
"user":"some-user",
"http_x_forwarded_for":"192.168.3.3"
},
...
}
前のサンプルで示されたように httpRequest
フィールドを構成すると、トレースが支援されます。Google Cloud コンソールでは、特定の HTTP リクエストのすべてのログが親子階層で表示されます。
この抽出を構成するには、/etc/google-fluentd/config.d/nginx.conf
の末尾に、次の内容を追加します。
<filter nginx-access>
@type record_transformer
enable_ruby true
<record>
httpRequest ${ {"requestMethod" => record['method'], "requestUrl" => record['path'], "requestSize" => record['size'], "status" => record['code'], "userAgent" => record['agent'], "remoteIp" => record['remote'], "serverIp" => record['host'], "referer" => record['referer']} }
</record>
remove_keys method, path, size, code, agent, remote, host, referer
</filter>
ログエントリの構成方法については、ログレコードの変更をご覧ください。
独自のパーサーを作成する
使用するログが標準パーサーでサポートされていない場合は、独自のパーサーを作成できます。パーサーは、ログレコードの照合とラベルの適用に使用される正規表現から構成されます。
次のサンプルコードは、ログレコードのログ行、ログ行の形式を表す正規表現を含む構成、保存されているログエントリを示しています。
ログレコードのログ行:
REPAIR CAR $500
ログ行の形式を表す正規表現を含む構成:
$ sudo vim /etc/google-fluentd/config.d/test-structured-log.conf $ cat /etc/google-fluentd/config.d/test-structured-log.conf <source> @type tail # Format indicates the log should be translated from text to # structured (JSON) with three fields, "action", "thing" and "cost", # using the following regex: format /(?<action>\w+) (?<thing>\w+) \$(?<cost>\d+)/ # The path of the log file. path /tmp/test-structured-log.log # The path of the position file that records where in the log file # we have processed already. This is useful when the agent # restarts. pos_file /var/lib/google-fluentd/pos/test-structured-log.pos read_from_head true # The log tag for this log input. tag structured-log </source>
結果のログエントリ:
{ insertId: "eps2n7g1hq99qp" jsonPayload: { "action": "REPAIR" "thing": "CAR" "cost": "500" } labels: { compute.googleapis.com/resource_name: "add-structured-log-resource" } logName: "projects/my-sample-project-12345/logs/structured-log" receiveTimestamp: "2023-03-21T01:47:11.475065313Z" resource: { labels: { instance_id: "3914079432219560274" project_id: "my-sample-project-12345" zone: "us-central1-c" } type: "gce_instance" } timestamp: "2023-03-21T01:47:05.051902169Z" }
問題のトラブルシューティング
以前の Logging エージェントのインストールや操作に関する一般的な問題のトラブルシューティングについては、エージェントのトラブルシューティングをご覧ください。
次のステップ
ログエントリをクエリして表示するには、ログ エクスプローラを使用してログを表示するをご覧ください。
Google Cloud CLI を使用してログエントリを読み取る方法については、ログエントリを読み取るをご覧ください。
Logging API を使用してログエントリを読み取る場合は、
entries.list
メソッドをご覧ください。