前回の続き。システムの一部をCloud RunからVPS化のために、
VPS上のログをGCPのCloud Loggingに送信したい。。
利用するプラグイン
利用するのはこのあたり。
アプリのログファイルをtailで読み込んで、
Cloud Logging(旧Stackdriver)に送信する。
ローカルでの環境
開発・確認用の環境は前回と同じ感じ。
myapp-io.conf
の[OUTPUT]
部分を設定していく。
とりあえず、転送する
まずは、とりあえず、転送するだけの設定。
追加した[OUTPUT]
以外は前回と同じ。
# myapp-io.conf [INPUT] name tail path ./logs/application.log read_from_head true multiline.parser myapp-multiline tag myapp.applog [FILTER] name parser match *.applog key_name log parser myapp-multiline-capture [OUTPUT] name stdout match * [OUTPUT] Name stackdriver Match * # myapp-parser.conf [MULTILINE_PARSER] name myapp-multiline type regex flush_timeout 1000 # rules | state name | regex pattern | next state # ------|---------------|-------------------------------------------- rule "start_state" "/^\[.+\] [a-zA-Z]+ .+/" "cont" rule "cont" "/^\s+.*/" "cont" [PARSER] name myapp-multiline-capture format regex regex /^\[(?<time>[^ ]+)\] (?<type>[a-zA-Z]+) +(?<message>.*)\n/m time_key time time_format %Y-%m-%dT%H:%M:%S.%L%z
google_service_credentials
を設定する必要があるけど、
デフォルトは環境変数(GOOGLE_APPLICATION_CREDENTIALS
)で設定できる。
GCPのコンソール上でサービスアカウントを作成し、
「ログ書き込み」権限を付与した上で鍵(.json
)をダウンロード。
あとは、環境変数にキーファイルのパスを指定すればOK
#!/bin/bash export GOOGLE_APPLICATION_CREDENTIALS="./credentials.json" fluent-bit -c myapp.conf
Cloud Logging上で確認すると、ログが転送されていることがわかる。
Cloud Loggingでのログの詳細はこんな感じ。
logName
には、Fluent側のTagが使われるっぽい。
{ "insertId": "c7yrtzfh5u8wj", "jsonPayload": { "message": "message info", "type": "INFO" }, "resource": { "type": "global", "labels": { "project_id": "myproject" } }, "timestamp": "2024-01-17T04:36:17.654Z", "logName": "projects/myproject/logs/myapp.applog", "receiveTimestamp": "2024-01-17T04:36:18.407382698Z" }
ログレベルを反映する
なにも指定していないので、ログレベル(severity
)がない状態。
severity_key
を使えばOK。
FILTERのPARSERで?<type>
と名前をつけているので、
[PARSER] name myapp-multiline-capture regex /^\[(?<time>[^ ]+)\] (?<type>[a-zA-Z]+) +(?<message>.*)\n/m # ...略
OUTPUTでそのキー名を指定するかたち。
[OUTPUT] Name stackdriver Match * severity_key type
設定した状態だとこんな感じ。
{ "insertId": "u7gxdeb6i2f", "jsonPayload": { "message": "message info" }, "resource": { "type": "global", "labels": { "project_id": "myproject" } }, "timestamp": "2024-01-17T06:54:36.083Z", "severity": "INFO", "logName": "projects/myproject/logs/myapp.applog", "receiveTimestamp": "2024-01-17T06:54:37.155753816Z" }
絞り込むための情報を追加する
Cloud Functionsでのログを見ると、こんな感じになっていて、
関数名などでも絞り込みできるようになっている。
{ "textPayload": "message cloud function log...", "insertId": "65a77280000b92741134b1ba", "resource": { "type": "cloud_function", "labels": { "function_name": "my_foo_function", "project_id": "myproject", "region": "asia-northeast1" } }, "timestamp": "2024-01-17T06:24:00.758388Z", "severity": "INFO", "labels": { "runtime_version": "nodejs20_20231231_20_10_0_RC00", "execution_id": "hv2mzdad42fl", "instance_id": "0087599d42325f0791879e25b0b66159bb57157855155a263ba635c671e1f8d42a60150e295dff896773521f08fa3a955ae28311f8733a1da8dea95f7bf859472008d2" }, "logName": "projects/myproject/logs/cloudfunctions.googleapis.com%2Fcloud-functions", "trace": "projects/myproject/traces/7abc1b0a9c4923b83d12c081cfa31d12", "receiveTimestamp": "2024-01-17T06:24:01.085097754Z" }
それぞれなにを設定すればよいかなどは、このあたりを参照。
- 構造化ロギング | Cloud Logging | Google Cloud
- LogEntry | Cloud Logging | Google Cloud
- MonitoredResource | Cloud Logging | Google Cloud
resource
はログエクスプローラで絞り込みするときに使うやつ。
設定の例
設定はこんな感じ。
[OUTPUT] Name stackdriver Match * severity_key type ### resource関連の設定 # resourceのtype resource generic_node # location/region location asia-northeast1 # 実行環境やclaster名などの識別子 namespace my_foo_func # namespace内ノードのID。IPやhost名など node_id my_vpn_host ### labelsの設定 # key=valueをカンマ区切りで指定 labels machine_name=my_vpn_host,app_version=1.0.0
設定した状態で実行するとこんな感じのログになる。
{ "insertId": "6xuk1uf767oyw", "jsonPayload": { "message": "message info" }, "resource": { "type": "generic_node", "labels": { "project_id": "myproject", "location": "asia-northeast1", "namespace": "my_foo_func", "node_id": "my_vpn_host" } }, "timestamp": "2024-01-17T07:20:58.129Z", "severity": "INFO", "labels": { "machine_name": "my_vpn_host", "app_version": "1.0.0" }, "logName": "projects/myproject/logs/myapp.applog", "receiveTimestamp": "2024-01-17T07:20:58.890547211Z" }
コンソールにも「汎用ノード」が増え、フィルタリングできる。
(未指定だったのは「グローバル」)
resource.labelsについて
resource.labels
で指定できるものは、
resource.type
ごとに決まっているので、
それ以外はlabels
に追加するといい感じ。
resource.type
は、k8sやgceなど指定できるけど、
global
、generic_node
、generic_task
を使いそう。
それぞれの詳細は、以下に書かれている。
- global | Monitored resource types
project_id
のみ
- generic_node | Monitored resource types
project_id
、location
、namespace
、node_id
- generic_task | Monitored resource types
project_id
、location
、namespace
、job
、task_id
ラベルでの変数の利用
各ラベルの値は、
severity(type)
のようにログ自体の値や、
環境変数の値を埋め組むことができる。
Fluent側のログがこんな感じの場合。
{ "keyA": "valA", "toplevel": { "keyB": "valB" } }
こんな感じで$<キー名>
を指定すると、
ログ内のデータを使ってくれる。
[OUTPUT] name stackdriver match * labels keyC=$keyA,keyD=$toplevel['keyB'],keyE=valC
細かい文法はこのあたり。
なので、アプリのバージョンなどで絞り込みたい場合には、
ログに含めておいて、labelsにわたす感じだとよい感じ。
以上!! やっとやりたいことができた気がするぞ。。(*´ω`*)