# Fastly logs

## Start logging in 5 minutes

Stream Fastly CDN access logs to Better Stack using Fastly's [real-time log streaming](https://www.fastly.com/documentation/guides/integrations/streaming-logs/setting-up-remote-log-streaming/).

### 1. Create a Fastly source

Create a [new Fastly source in Better Stack](https://telemetry.betterstack.com/team/t0/sources/new?platform=fastly ";_blank").

### 2. Create an HTTPS logging endpoint in Fastly

Open your service in [Fastly](https://manage.fastly.com/ ";_blank") → **Edit configuration** → **Clone version** to create a new draft version.

Click **Logging** → **HTTPS** → **Create endpoint** and use the following settings:

- **Name**: `Better Stack`
- **Log format**: use the snippet below
- **URL**: use the snippet below
- **Maximum logs** and **Maximum bytes**: `0`
- **Content type**: `application/x-ndjson`
- **Custom header name**: `Authorization`
- **Custom header value**: use the snippet below
- **Method**: `POST`
- **JSON log entry format**: Newline delimited
- **Log line format**: Blank
- **Compression**: None
- TLS fields: leave empty


```json
[label Log format]
{ "timestamp": "%{strftime(\{"%Y-%m-%dT%H:%M:%S%z"\}, time.start)}V", "client_ip": "%{req.http.Fastly-Client-IP}V", "geo_country": "%{client.geo.country_name}V", "geo_city": "%{client.geo.city}V", "host": "%{if(req.http.Fastly-Orig-Host, req.http.Fastly-Orig-Host, req.http.Host)}V", "url": "%{json.escape(req.url)}V", "request_method": "%{json.escape(req.method)}V", "request_protocol": "%{json.escape(req.proto)}V", "request_referer": "%{json.escape(req.http.referer)}V", "request_user_agent": "%{json.escape(req.http.User-Agent)}V", "response_state": "%{json.escape(fastly_info.state)}V", "response_status": %{resp.status}V, "response_reason": %{if(resp.response, "%22"+json.escape(resp.response)+"%22", "null")}V, "response_body_size": %{resp.body_bytes_written}V, "fastly_server": "%{json.escape(server.identity)}V", "fastly_is_edge": %{if(fastly.ff.visits_this_service == 0, "true", "false")}V, "duration_us": %{time.elapsed.usec}V, "pop": "%{server.datacenter}V", "tls_version": "%{tls.client.protocol}V", "service_id": "%{req.service_id}V" }
```

The JSON matches Fastly's suggested log format, with four extra fields at the end (`duration_us`, `pop`, `tls_version`, `service_id`) that power the latency and traffic dashboards. Add any other [Fastly logging variables](https://www.fastly.com/documentation/reference/vcl/variables/) as needed.

```
[label URL]
https://$INGESTING_HOST
```

```
[label Custom header value]
Bearer $SOURCE_TOKEN
```

Fastly verifies the endpoint automatically when you create it.

### 3. Activate the new version

Click **Activate** to deploy the draft version of your Fastly service.

### 4. Start logging 🎉

Requests to your Fastly service now stream to Better Stack within seconds.

You should see your logs in [Better Stack → Live tail](https://telemetry.betterstack.com/team/0/tail ";_blank") with fields like `response_status`, `response_state``, and `pop` parsed and ready for filtering and dashboards.

## Prefer syslog?

Fastly can also stream logs over TLS syslog. Create a **Syslog** logging endpoint instead of the HTTPS one:

- **Name**: `Better Stack`
- **Log format**: use the snippet below — the HTTPS snippet prepended with the token block
- **Syslog address**: use the snippet below, port `6514`
- **TLS**: Yes
- **TLS hostname**: same as the syslog address
- **TLS CA certificate**: leave empty
- **Token**: leave empty
- **Log line format**: Classic

```
[label Syslog address]
$INGESTING_HOST_VEC
```

```json
[label Log format]
[logtail@11993 source_token="$SOURCE_TOKEN"] { "timestamp": "%{strftime(\{"%Y-%m-%dT%H:%M:%S%z"\}, time.start)}V", "client_ip": "%{req.http.Fastly-Client-IP}V", "gentry_name}V", "geo_city": "%{client.geo.city}V", "host": "%{if(req.http.Fastly-Orig-Host, req.http.Fastly-Orig-Host, req.http.Host)}V", "url":"%{json.escape(req.url)}V", "request_method": "%{json.escape(req.method)}V", "request_protocol": "%{json.escape(req.proto)}V", "request_referer": "%{json.escape(req.http.referer)}V", "request_user_agent": "%{json.escape(req.http.User-Agent)}V", "response_state": "%{json.escape(fastly_info.state)}V", "response_status": %{resp.status}V, "response_reason":
%{if(resp.response, "%22"+json.escape(resp.response)+"%22", "null")}V, "response_body_size": %{resp.body_bytes_written}V, "fastly_server": "%{json.escape(server.ide%{if(fastly.ff.visits_this_service == 0, "true", "false")}V, "duration_us": %{time.elapsed.usec}V, "pop": "%{server.datacenter}V", "tls_version":"%{tls.client.protocol}V", "service_id": "%{req.service_id}V" }
```

[info]
#### Keep the token block at the start of the log format

Over syslog, the `[logtail@11993 source_token="$SOURCE_TOKEN"]` block at the very start of the **Log format**, followed by a single space, authenticates your logs.

Set **Log line format** to **Classic** and leave Fastly's **Token** field empty. With the **Blank** line format, or with the token in the **Token** field, Fastly delivers logs in a format that can't be authenticated, and they won't appear in Better Stack.
[/info]

## Need help?

Please let us know at hello@betterstack.com.
We're happy to help! 🙏