vcl_log
The built-in vcl_log
subroutine is executed after the response to the client has finished, and therefore has access to data about the final state of the request, and timing information about the response. Because it is not executed within the critical path of the VCL flow, it is the preferred place to transform and output data to a log endpoint using the log
statement.
HINT: Logs emitted from VCL are routed to your configured endpoint via a syslog daemon. To ensure that the log reaches the right endpoint, the message must be prefixed with your service ID and endpoint name. The service ID is available as the VCL variable req.service_id
, which can be used for convenience. For example:
log "syslog " + req.service_id + " my-endpoint-name :: ACTUAL LOG TEXT HERE";
When creating a log endpoint, Fastly will automatically generate a log
statement for you, which sends a log line to that endpoint for every request. You can disable this behavior by setting the placement
property of the log endpoint to "none"
when creating the endpoint.
For more information on creating log endpoints, what to log, and how to format log
statements, see our logging integration guide.
Shielding considerations
If using shielding, i.e. each request normally passes through two Fastly POPs, then the full VCL flow will be executed at both the edge POP and the shield POP. For requests that do not find a hit in the cache at the edge, this may result in double logging. To avoid logging at the shield, consider wrapping the log statement in a check of fastly.ff.visits_this_service
:
if (fastly.ff.visits_this_service == 0) { log "....";}
Alternatively, consider generating a random request ID (for example using uuid.version4
) at the edge and including it in the log statement at the edge and the shield, allowing for matching and de-duplication of the data in later analysis.
State transitions
| vcl_log |
|
To see this subroutine in the context of the full VCL flow, see using VCL.
Tokens available in this subroutine
The following limited-scope VCL functions and variables are available for use in this subroutine (those in bold are available only in this subroutine, those available in *all* subroutines are not listed):
- bereq.body_bytes_written
- bereq.bytes_written
- bereq.header_bytes_written
- client.socket.congestion_algorithm
- client.socket.cwnd
- client.socket.nexthop
- client.socket.pace
- client.socket.ploss
- client.socket.tcp_info
- client.socket.tcpi_advmss
- client.socket.tcpi_bytes_acked
- client.socket.tcpi_bytes_received
- client.socket.tcpi_data_segs_in
- client.socket.tcpi_data_segs_out
- client.socket.tcpi_delivery_rate
- client.socket.tcpi_delta_retrans
- client.socket.tcpi_last_data_sent
- client.socket.tcpi_max_pacing_rate
- client.socket.tcpi_min_rtt
- client.socket.tcpi_notsent_bytes
- client.socket.tcpi_pacing_rate
- client.socket.tcpi_pmtu
- client.socket.tcpi_rcv_mss
- client.socket.tcpi_rcv_rtt
- client.socket.tcpi_rcv_space
- client.socket.tcpi_rcv_ssthresh
- client.socket.tcpi_reordering
- client.socket.tcpi_rtt
- client.socket.tcpi_rttvar
- client.socket.tcpi_segs_in
- client.socket.tcpi_segs_out
- client.socket.tcpi_snd_cwnd
- client.socket.tcpi_snd_mss
- client.socket.tcpi_snd_ssthresh
- client.socket.tcpi_total_retrans
- fastly_info.h2.is_push
- fastly_info.h2.stream_id
- obj.age
- obj.entered
- obj.grace
- obj.hits
- obj.is_pci
- obj.lastuse
- obj.stale_if_error
- obj.stale_while_revalidate
- obj.ttl
- quic.cc.cwnd
- quic.cc.ssthresh
- quic.num_bytes.received
- quic.num_bytes.sent
- quic.num_packets.ack_received
- quic.num_packets.decryption_failed
- quic.num_packets.late_acked
- quic.num_packets.lost
- quic.num_packets.received
- quic.num_packets.sent
- quic.rtt.latest
- quic.rtt.minimum
- quic.rtt.smoothed
- quic.rtt.variance
- req.backend.ip
- req.backend.name
- req.backend.port
- req.body_bytes_read
- req.bytes_read
- req.digest.ratio
- req.is_ipv6
- req.is_purge
- resp.body_bytes_written
- resp.bytes_written
- resp.completed
- resp.header_bytes_written
- resp.headers
- resp.http.{NAME}
- resp.is_locally_generated
- resp.proto
- resp.response
- resp.status
- segmented_caching.autopurged
- segmented_caching.block_number
- segmented_caching.block_size
- segmented_caching.cancelled
- segmented_caching.client_req.is_open_ended
- segmented_caching.client_req.is_range
- segmented_caching.client_req.range_high
- segmented_caching.client_req.range_low
- segmented_caching.completed
- segmented_caching.error
- segmented_caching.failed
- segmented_caching.is_inner_req
- segmented_caching.is_outer_req
- segmented_caching.obj.complete_length
- segmented_caching.rounded_req.range_high
- segmented_caching.rounded_req.range_low
- segmented_caching.total_blocks
- time.end
- time.end.msec
- time.end.msec_frac
- time.end.sec
- time.end.usec
- time.end.usec_frac
- time.to_first_byte
- tls.client.certificate.dn
- tls.client.certificate.is_cert_bad
- tls.client.certificate.is_cert_expired
- tls.client.certificate.is_cert_missing
- tls.client.certificate.is_cert_unknown
- tls.client.certificate.is_unknown_ca
- tls.client.certificate.is_verified
- tls.client.certificate.issuer_dn
- tls.client.certificate.not_after
- tls.client.certificate.not_before
- tls.client.certificate.raw_certificate_b64
- tls.client.certificate.serial_number
- tls.client.cipher
- tls.client.ciphers_list
- tls.client.ciphers_list_sha
- tls.client.ciphers_list_txt
- tls.client.ciphers_sha
- tls.client.handshake_sent_bytes
- tls.client.iana_chosen_cipher_id
- tls.client.ja3_md5
- tls.client.ja4
- tls.client.protocol
- tls.client.servername
- tls.client.tlsexts_list
- tls.client.tlsexts_list_sha
- tls.client.tlsexts_list_txt
- tls.client.tlsexts_sha
- transport.bw_estimate
- transport.type
- waf.anomaly_score
- waf.blocked
- waf.executed
- waf.failures
- waf.http_violation_score
- waf.lfi_score
- waf.logdata
- waf.logged
- waf.message
- waf.passed
- waf.php_injection_score
- waf.rce_score
- waf.rfi_score
- waf.rule_id
- waf.session_fixation_score
- waf.severity
- waf.sql_injection_score
- waf.xss_score