ログストリーミング: Datadog

Fastly のリアルタイムログストリーミング機能を、Datadog が読める形式でログを送信するように設定することができます。Datadog はクラウドベースの監視及び分析ソリューションで、スタック内のアプリケーション内部を確認して結果を集計できます。

Fastly ではサードパーティのサービスに関する設定等のサポートは行っておりません。詳細は Fastly's Terms of Service をご参照ください。

前提条件

Fastly サービスのログエンドポイントとして Datadog を追加する前に、以下が必要です。

  • Datadog アカウントの登録 Datadog サイトでアカウントを作成できます。制限付きの無料プラン、またはアップグレードしてより多くの機能を利用することができます。Datadog のセットアップを登録する場所 (米国 (US)、欧州連合 (EU)、または日本) によって、Fastly でログエンドポイントを設定する際に使用するコマンドが影響されます。

  • Datadog の設定ページから Datadog API キーを 取得 Datadog インターフェイスで Integrations -> APIs にアクセスすることで API キーを作成・取得できます。

    トークンページ

    この例ではキー decafbaddeadbeef が表示されています。お客様の API キーは、これとは異なります。このキーを忘れないようにメモしてください。

Datadog をログエンドポイントとして追加する

Datadog アカウントを作成し Datadog API キーを書き留めたら、以下の手順で Fastly サービスのログエンドポイントとして Datadog を追加します。

  1. Deliver サービス
  2. Compute services
  1. リモートログストリーミングの設定に関するガイドの情報をご確認ください。

  2. Datadog エリアで、Create endpoint をクリックします。
  3. Create a Datadog endpoint に以下のように記入します。
    • Name フィールドに、エンドポイントの分かりやすい名前を入力します。

    • Placement エリアで、生成された VCL のどこにログコールを配置するかを選択します。有効な値は、形式のバージョンのデフォルトなしです。詳細については、ログの配置の変更に関するガイドをご覧ください。

    • Log format フィールドに、Datadog に送信するデータを入力します。 この形式の使用方法については以下をご覧ください。
    • Region メニューから、ログの送信先の地域を選択します。
    • API key フィールドに、Datadog アカウントの API キーを入力します。
  4. Create をクリックして、新しいログ記録エンドポイントを作成します。

  5. Activate メニューから、Activate on Production を選択して、設定の変更をデプロイします。

エンドポイントの作成とサービスへの変更が完了すると、数秒後にログが Datadog アカウントに表示されるようになります。これらのログは Datadog アカウント内の Datadog Log Explorer を介してアクセスできます。

JSON のロギング形式を使用する

Datadog に送信されるデータは、JSON オブジェクトとしてシリアル化されている必要があります。Datadog は JSON として作成されたログファイルを自動的に解析し、servicehostdate などの複数ある予約フィールドを認識することができます。

この例の JSON ログは、読み取りやすくフォーマットされています。正しく解析されるためには、改行とインデントの空白をすべて取り除いた上で Log format 欄に1行で入力する必要があります。

例えば、以下の JSON では、ログを送信した Fastly サービスの ID を service と設定していますが、対人可読形式の名前を使用したり fastly などの共通の名前のもとにすべてのログをグループ化することも可能です。

{
"ddsource": "fastly",
"service": "%{req.service_id}V",
"date": "%{begin:%Y-%m-%dT%H:%M:%S%z}t",
"time_start": "%{begin:%Y-%m-%dT%H:%M:%S%Z}t",
"time_end": "%{end:%Y-%m-%dT%H:%M:%S%Z}t",
"http": {
"request_time_ms": %{time.elapsed.msec}V,
"method": "%m",
"url": "%{json.escape(req.url)}V",
"useragent": "%{json.escape(req.http.User-Agent)}V",
"referer": "%{json.escape(req.http.referer)}V",
"protocol": "%H",
"request_x_forwarded_for": "%{X-Forwarded-For}i",
"status_code": "%s"
},
"network": {
"client": {
"ip": "%h",
"name": "%{client.as.name}V",
"number": "%{client.as.number}V",
"connection_speed": "%{client.geo.conn_speed}V"
},
"destination": {
"ip": "%A"
},
"geoip": {
"geo_city": "%{client.geo.city.utf8}V",
"geo_country_code": "%{client.geo.country_code}V",
"geo_continent_code": "%{client.geo.continent_code}V",
"geo_region": "%{client.geo.region}V"
},
"bytes_written": %B,
"bytes_read": %{req.body_bytes_read}V
},
"host":"%{if(req.http.Fastly-Orig-Host, req.http.Fastly-Orig-Host, req.http.Host)}V",
"origin_host": "%v",
"is_ipv6": %{if(req.is_ipv6, "true", "false")}V,
"is_tls": %{if(req.is_ssl, "true", "false")}V,
"tls_client_protocol": "%{json.escape(tls.client.protocol)}V",
"tls_client_servername": "%{json.escape(tls.client.servername)}V",
"tls_client_cipher": "%{json.escape(tls.client.cipher)}V",
"tls_client_cipher_sha": "%{json.escape(tls.client.ciphers_sha)}V",
"tls_client_tlsexts_sha": "%{json.escape(tls.client.tlsexts_sha)}V",
"is_h2": %{if(fastly_info.is_h2, "true", "false")}V,
"is_h2_push": %{if(fastly_info.h2.is_push, "true", "false")}V,
"h2_stream_id": "%{fastly_info.h2.stream_id}V",
"request_accept_content": "%{Accept}i",
"request_accept_language": "%{Accept-Language}i",
"request_accept_encoding": "%{Accept-Encoding}i",
"request_accept_charset": "%{Accept-Charset}i",
"request_connection": "%{Connection}i",
"request_dnt": "%{DNT}i",
"request_forwarded": "%{Forwarded}i",
"request_via": "%{Via}i",
"request_cache_control": "%{Cache-Control}i",
"request_x_requested_with": "%{X-Requested-With}i",
"request_x_att_device_id": "%{X-ATT-Device-Id}i",
"content_type": "%{Content-Type}o",
"is_cacheable": %{if(fastly_info.state~"^(HIT|MISS)$", "true","false")}V,
"response_age": "%{Age}o",
"response_cache_control": "%{Cache-Control}o",
"response_expires": "%{Expires}o",
"response_last_modified": "%{Last-Modified}o",
"response_tsv": "%{TSV}o",
"server_datacenter": "%{server.datacenter}V",
"req_header_size": %{req.header_bytes_read}V,
"resp_header_size": %{resp.header_bytes_written}V,
"socket_cwnd": %{client.socket.cwnd}V,
"socket_nexthop": "%{client.socket.nexthop}V",
"socket_tcpi_rcv_mss": %{client.socket.tcpi_rcv_mss}V,
"socket_tcpi_snd_mss": %{client.socket.tcpi_snd_mss}V,
"socket_tcpi_rtt": %{client.socket.tcpi_rtt}V,
"socket_tcpi_rttvar": %{client.socket.tcpi_rttvar}V,
"socket_tcpi_rcv_rtt": %{client.socket.tcpi_rcv_rtt}V,
"socket_tcpi_rcv_space": %{client.socket.tcpi_rcv_space}V,
"socket_tcpi_last_data_sent": %{client.socket.tcpi_last_data_sent}V,
"socket_tcpi_total_retrans": %{client.socket.tcpi_total_retrans}V,
"socket_tcpi_delta_retrans": %{client.socket.tcpi_delta_retrans}V,
"socket_ploss": %{client.socket.ploss}V
}