wrangler tail testing instructions
What's changed?
Release Candidate 1 adds support for port configuration. Add flag --port to set the localhost server used to receive tail logs (by default 8080 or OS allocated port); add flag --metrics to set the localhost server used to serve tunnel metrics (by default 8081 or OS allocated port).
Installation
Installing wrangler beta
npm i @cloudflare/wrangler@beta -gInstall cloudflared
Wrangler tail uses cloudflared under the hood. If you are already using cloudflared, be sure you have installed the latest version. Otherwise, follow the getting started guide for Argo Tunnel.
Creating a project
The documentation below assumes you have some familiarity with Wrangler and are already developing Workers. If this is not the case that is OK, come back after you've read through our Quickstart and have gotten up and running with Wrangler.
What gets logged?
Currently your tail will pick up console statements and exceptions thrown in your Worker. To illustrate, here is an example of a Hello World Worker (the result of wrangler generate) with a console statement and a thrown exception added:
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
/**
* Respond with hello worker text
* @param {Request} request
*/
async function handleRequest(request) {
console.log('hello tail!') // all console messages will be forwarded to your tail
throw new Error('oh dang')
return new Response('Hello worker!', {
headers: { 'content-type': 'text/plain' },
})
}Deploy your worker
Wrangler tail is designed to consume logs emitted by a published worker instance in production; this isn't a development tool like wrangler dev or wrangler preview. If you wish to "test" tails, we recommend publishing a new [env] and tailing that. See more on using environments in Wrangler here.
Run wrangler tail
Once your Worker has been published, you can run wrangler tail (or wrangler tail --env foo if you are tailing a Worker specified in your wrangler.toml with [env.foo]). We recommend piping the output through a JSON parser such as jq as shown in the example command below, but this isn't strictly necessary.
The command can take up to a minute to establish the tail, but once it is ready you should get a stderr message saying so:
$ wrangler tail | jq
Setting up log streaming from Worker script "tail-worker" to Wrangler. This may take a few seconds…
Now prepared to stream logs.Log Output and TraceItems
NOTE: the logging output schema is subject to change substantially before wrangler tail is fully released.
For each request received by a tailed Worker, a log will be sent to Wrangler and printed to stdout on a newline. Below is an example of a request to our example worker logged and piped through jq:
{
"scriptName": "example",
"outcome": "exception",
"event": {
"request": {
"url": "https://example.com/some/requested/url",
"method": "GET",
"headers": {
"CF-Ray": "57d55f210d7b95f3",
"X-Custom-Header-Name": "my-header-value"
},
"cf": {
"colo": "SJC"
}
},
},
"exceptions": [
{
"name": "Error",
"message": "oh dang",
"timestamp": 1587058642005
}
],
"logs": [
{
"message": "[\"hello tail!\"]",
"level": "log",
"timestamp": 1587058642005
}
]
}
Note that if you are using a browser to hit your worker, you may end up with at least two entries; one of these is a request made automatically by your browser to fetch the favicon.ico for the domain. If you are serving assets with something like Workers Sites, you will see a request for each asset referenced in your index.html.
Each line represents a TraceItem, which has the following attributes:
scriptName
scriptName is just the name of your uploaded Worker Script. Note: work to populate this field is ongoing, so you may see null
outcome
outcome is a string describing the outcome of the worker invocation, one of:
ok: The worker invocation succeeded.exception: An unhandled exception was thrown. This can happen for many reasons, including:- An uncaught JavaScript exception
- A
'fetch'handler that does not result in a Response - An internal error
exceededCpu: The Worker invocation exceeded either its CPU or memory limits.scriptNotFound: an internal error indicating a misconfigured pipeline or a difficulty retrieving the script.canceled: The worker invocation was canceled before it completed, commonly because the client disconnected before a response could be sent.
Note that outcome is not the same as HTTP status. A Worker can have an ok outcome when it successfully sends a 4xx or 5xx error. Likewise, a worker can have a non-ok outcome even after successfully sending a 200 response — for example, when an asynchronous task registered via waitUntil() later exceeds CPU or memory limits.
event
event is a FetchEventInfo object that contains information about the Worker's triggering fetchEvent. This object currently contains a single field, request, that holds a TraceRequest object, which contains properties that selectively mirror properties on FetchEvent's event.request. These properties include:
cf: a JavaScript Object containing the data fromFetchEvent.request.cfmethod: a string containing the data fromFetchEvent.request.methodheaders: an object containing header keys and values. Headers are down-cased, and duplicate header values are comma-concatenated under the appropriate key. Note that this is not a standard Headers object but a read only struct!url: a string containingFetchEvent.request.url
Redaction
The headers and url properties of the TraceRequest object are subject to redaction rules. This makes it harder to accidentally record sensitive information like user credentials or API tokens. The redactions use heuristic rules, so they are subject to false positives and negatives.
- Header redaction: The header value will be the string
REDACTEDwhen the (case-insensitive) header name is "Cookie"/"Set-Cookie" or contains a substring "auth", "key", "secret", or "token". - URL redaction: For each greedily matched substring of ID characters
(a-z, A-Z, 0-9, '+', '-', '_')in the URL, if it meets the following criteria for a hex or base-64 ID, the substring will be replaced with the stringREDACTED:- Hex ID: Contains 32 or more hex digits, and contains only hex digits and separators
('+', '-', '_') - Base-64 ID: Contains 21 or more characters, and contains at least two uppercase, two lowercase, and two digits.
- Hex ID: Contains 32 or more hex digits, and contains only hex digits and separators
exceptions
exceptions is populated with an array of TraceExceptions. Note that a single worker invocation might result in multiple unhandled exceptions, since a worker can register multiple asynchronous tasks.
TraceException
Records an unhandled exception that occurred during the Worker invocation. Made up of the following properties:
timestamp: a Number indicating milliseconds since time originmessage: a string, typically the error description (e.g. "'x' is not a function")name: a string, typically the error type (e.g. "Error", "TypeError", etc.)
logs
logs is populated with an array of TraceLogs. These reflect calls to console methods in your worker.
TraceLog
Records information sent to console functions. Made up of the following properties:
timestamp: a Number indicating milliseconds since time originlevel: a string indicating the console function that was called, one of:debuginfologwarnerror
message: a JSON-encoded string of the array of parameters passed to theconsolefunction.
Limitations
How many tails can I run at once?
Scripts are limited to three concurrent tails at any given time.
How long can I tail?
Each tail is automatically closed after a period of 24 hours.
If I lose my connection do I lose my tail?
Wrangler sends a heartbeat every ~60s. If no heartbeat is received for 10 minutes, the tail is removed.
Traffic limits
In order to avoid DOSing your local machine, tails are currently rate limited and will be denied/closed if the Worker they are tailing is receiving more than 6000 requests over the previous 10 min period.
Expected questions
how do logs work with async code?
You'll want to use event.waitUntil() for async operations that may return after your worker sends a response.
Feedback
Love it? Hate it? Wish it was better? Tell us! If you'd like to provide feedback on wrangler tail, you can comment on this issue or file a new one! Just make sure to prefix your issue title with [tail].