During Speed Week 2021 we announced a new offering for Enterprise customers, Instant Logs. Since then, the team has not slowed down and has been working on new ways to enable our customers to consume their logs and gain powerful insights into their HTTP traffic in real time.
We recognize that as developers, UIs are useful but sometimes there is the need for a more powerful alternative. Today, I am going to introduce you to Instant Logs in your terminal! In order to get started we need to install a few open-source tools to help us:
Websocat - to connect to WebSockets.
Angle Grinder - a utility to slice-and-dice a stream of logs on the command line.
Creating an Instant Log’s Session
For enterprise zones with access to Instant Logs, you can create a new session by sending a POST request to our jobs' endpoint. You will need:
Your Zone Tag / ID
An Authentication Key or an API Token with at least the Zone Logs Read permission
curl -X POST 'https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/logpush/edge/jobs' \
-H 'X-Auth-Key: <KEY>' \
-H 'X-Auth-Email: <EMAIL>' \
-H 'Content-Type: application/json' \
--data-raw '{
"fields": "ClientIP,ClientRequestHost,ClientRequestMethod,ClientRequestPath,EdgeEndTimestamp,EdgeResponseBytes,EdgeResponseStatus,EdgeStartTimestamp,RayID",
"sample": 1,
"filter": "",
"kind": "instant-logs"
}'
Response
The response will include a new field called destination_conf
. The value of this field is your unique WebSocket address that will receive messages directly from our network!
{
"errors": [],
"messages": [],
"result": {
"id": 401,
"fields": "ClientIP,ClientRequestHost,ClientRequestMethod,ClientRequestPath,EdgeEndTimestamp,EdgeResponseBytes,EdgeResponseStatus,EdgeStartTimestamp,RayID",
"sample": 1,
"filter": "",
"destination_conf": "wss://logs.cloudflare.com/instant-logs/ws/sessions/949f9eb846f06d8f8b7c91b186a349d2",
"kind": "instant-logs"
},
"success": true
}
Connect to WebSocket
Using a CLI utility like Websocat, you can connect to the WebSocket and start immediately receiving logs of line-delimited JSON.
websocat wss://logs.cloudflare.com/instant-logs/ws/sessions/949f9eb846f06d8f8b7c91b186a349d2
{"ClientRequestHost":"example.com","ClientRequestMethod":"GET","ClientRequestPath":"/","EdgeEndTimestamp":"2022-01-25T17:23:05Z","EdgeResponseBytes":363,"EdgeResponseStatus":200,"EdgeStartTimestamp":"2022-01-25T17:23:05Z","RayID":"6d332ff74fa45fbe","sampleInterval":1}
{"ClientRequestHost":"example.com","ClientRequestMethod":"GET","ClientRequestPath":"/","EdgeEndTimestamp":"2022-01-25T17:23:06Z","EdgeResponseBytes":363,"EdgeResponseStatus":200,"EdgeStartTimestamp":"2022-01-25T17:23:06Z","RayID":"6d332fffe9c4fc81","sampleInterval":1}
The Scenario
Now that you are able to create a new Instant Logs session let’s give it a purpose! Say you just recently deployed a new firewall rule blocking users from downloading a specific asset that is only available to users in Canada. For the purpose of this example, the asset is available at the path /canadians-only
.
Specifying Fields
In order to see what firewall actions (if any) were taken, we need to make sure that we include ClientRequestCountry
, FirewallMatchesActions
and FirewallMatchesRuleIDs
fields when creating our session.
Additionally, any field available in our HTTP request dataset is usable by Instant Logs. You can view the entire list of HTTP Request fields on our developer docs.
Choosing a Sample Rate
Instant Logs users also have the ability to choose a sample rate. The sample
parameter is the inverse probability of selecting a log. This means that "sample": 1
is 100% of records, "sample": 10
is 10% and so on.
Going back to our example of validating that our newly deployed firewall rule is working as expected, in this case, we are choosing not to sample the data by setting "sample": 1
.
Please note that Instant Logs has a maximum data rate supported. For high volume domains, we sample server side as indicated in the "sampleInterval" parameter returned in the logs. For example, "sampleInterval": 10 indicates this log message is just one out of 10 logs received.
Defining the Filters
Since we are only interested in requests with the path of /canadians-only
, we can use filters to remove any logs that do not match that specific path. The filters consist of three parts: key
, operator
and value
. The key
can be any field specified in the "fields": ""
list when creating the session. The complete list of supported operators can be found on our Instant Logs documentation.
To only get the logs of requests destined to /canadians-only
, we can specify the following filter:
{
"filter": "{\"where\":{\"and\":[{\"key\":\"ClientRequestPath\",\"operator\":\"eq\",\"value\":\"/canadians-only\"}]}}"
}
Creating an Instant Logs Session: Canadians Only
Using the information above, we can now craft the request for our custom Instant Logs session.
curl -X POST 'https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/logpush/edge/jobs' \
-H 'X-Auth-Key: <KEY>' \
-H 'X-Auth-Email: <EMAIL>' \
-H 'Content-Type: application/json' \
--data-raw '{
"fields": "ClientIP,ClientRequestHost,ClientRequestMethod,ClientRequestPath,ClientCountry,EdgeEndTimestamp,EdgeResponseBytes,EdgeResponseStatus,EdgeStartTimestamp,RayID,FirewallMatchesActions,FirewallMatchesRuleIDs",
"sample": 1,
"kind": "instant-logs",
"filter": "{\"where\":{\"and\":[{\"key\":\"ClientRequestPath\",\"operator\":\"eq\",\"value\":\"/canadians-only\"}]}}"
}'
Angle Grinder
Now that we have a connection to our WebSocket and are receiving logs that match the request path /canadians-only
, we can start slicing and dicing the logs to see that the rule is working as expected. A handy tool to use for this is Angle Grinder. Angle Grinder lets you apply filtering, transformations and aggregations on stdin with first class JSON support. For example, to get the number of visitors from each country we can sum the number of events by the ClientCountry
field.
websocat wss://logs.cloudflare.com/instant-logs/ws/sessions/949f9eb846f06d8f8b7c91b186a349d2 | agrind '* | json | sum(sampleInterval) by ClientCountry'
ClientCountry _sum
---------------------------------
pt 4
fr 3
us 3
Using Angle Grinder, we can create a query to count the firewall actions by each country.
websocat wss://logs.cloudflare.com/instant-logs/ws/sessions/949f9eb846f06d8f8b7c91b186a349d2 | agrind '* | json | sum(sampleInterval) by ClientCountry,FirewallMatchesActions'
ClientCountry FirewallMatchesActions _sum
---------------------------------------------------------------
ca [] 5
us [block] 1
Looks like our newly deployed firewall rule is working :)
Happy Logging!