Edge Functions

Logging

How to access logs for your Edge Functions.


Logs are provided for each function invocation, locally and in hosted environments.

How to access logs

Hosted

You can access both tools from the Functions section of the Dashboard. Select your function from the list, and click Invocations or Logs:

  • Invocations: shows the Request and Response for each execution. You can see the headers, body, status code, and duration of each invocation. You can also filter the invocations by date, time, or status code.
  • Logs: shows any platform events, uncaught exceptions, and custom log events. You can see the timestamp, level, and message of each log event. You can also filter the log events by date, time, or level.

Function invocations.

Local

When developing locally you will see error messages and console log statements printed to your local terminal window.

Events that get logged

  • Uncaught exceptions: Uncaught exceptions thrown by a function during execution are automatically logged. You can see the error message and stack trace in the Logs tool.
  • Custom log events: You can use console.log, console.error, and console.warn in your code to emit custom log events. These events also appear in the Logs tool.
  • Boot and Shutdown Logs: The Logs tool extends its coverage to include logs for the boot and shutdown of functions.

Here is an example of how to use custom logs events in your function:


_23
Deno.serve(async (req) => {
_23
try {
_23
const { name } = await req.json()
_23
_23
if (!name) {
_23
console.warn('Empty name provided')
_23
}
_23
_23
const data = {
_23
message: `Hello ${name || 'Guest'}!`, // Provide a default value if name is empty
_23
}
_23
_23
console.log(`Name: ${name}`)
_23
_23
return new Response(JSON.stringify(data), { headers: { 'Content-Type': 'application/json' } })
_23
} catch (error) {
_23
console.error(`Error processing request: ${error.message}`)
_23
return new Response(JSON.stringify({ error: 'Internal Server Error' }), {
_23
status: 500,
_23
headers: { 'Content-Type': 'application/json' },
_23
})
_23
}
_23
})

Logging Tips

Logging Request Headers

When debugging Edge Functions, a common mistake is to try to log headers to the developer console via code like this:

index.ts

_12
Deno.serve(async (req) => {
_12
const headers = JSON.stringify(req.headers)
_12
console.log(`Request headers: ${headers}`)
_12
// OR
_12
console.log(`Request headers: ${JSON.stringify(req.headers)}`)
_12
return new Response('ok', {
_12
headers: {
_12
'Content-Type': 'application/json',
_12
},
_12
status: 200,
_12
})
_12
})

Both attempts will give as output the string "{}", even though retrieving the value using request.headers.get("Your-Header-Name") will indeed give you the correct value. This behavior mirrors that of browsers.

The reason behind this behavior is that Headers objects don't store headers in JavaScript properties that can be enumerated. As a result, neither the developer console nor the JSON stringifier can properly interpret the names and values of the headers. Essentially, it's not an empty object, but rather an opaque one.

However, Headers objects are iterable. You can utilize this feature to craft a couple of succinct one-liners for debugging and printing headers.

Convert headers into an object with Object.fromEntries:

You can use Object.fromEntries which is a call to convert the headers into an object:

index.ts

_11
Deno.serve(async (req) => {
_11
let headersObject = Object.fromEntries(req.headers)
_11
let requestHeaders = JSON.stringify(headersObject, null, 2)
_11
console.log(`Request headers: ${requestHeaders}`)
_11
return new Response('ok', {
_11
headers: {
_11
'Content-Type': 'application/json',
_11
},
_11
status: 200,
_11
})
_11
})

This results in something like:

index.ts

_19
Request headers: {
_19
"accept": "*/*",
_19
"accept-encoding": "gzip",
_19
"authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InN1cGFuYWNobyIsInJvbGUiOiJhbm9uIiwieW91IjoidmVyeSBzbmVha3ksIGh1aD8iLCJpYXQiOjE2NTQ1NDA5MTYsImV4cCI6MTk3MDExNjkxNn0.cwBbk2tq-fUcKF1S0jVKkOAG2FIQSID7Jjvff5Do99Y",
_19
"cdn-loop": "cloudflare; subreqs=1",
_19
"cf-ew-via": "15",
_19
"cf-ray": "8597a2fcc558a5d7-GRU",
_19
"cf-visitor": "{\"scheme\":\"https\"}",
_19
"cf-worker": "supabase.co",
_19
"content-length": "20",
_19
"content-type": "application/x-www-form-urlencoded",
_19
"host": "edge-runtime.supabase.com",
_19
"my-custom-header": "abcd",
_19
"user-agent": "curl/8.4.0",
_19
"x-deno-subhost": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImtpZCI6InN1cGFiYXNlIn0.eyJkZXBsb3ltZW50X2lkIjoic3VwYW5hY2hvX2M1ZGQxMWFiLTFjYmUtNDA3NS1iNDAxLTY3ZTRlZGYxMjVjNV8wMDciLCJycGNfcm9vdCI6Imh0dHBzOi8vc3VwYWJhc2Utb3JpZ2luLmRlbm8uZGV2L3YwLyIsImV4cCI6MTcwODYxMDA4MiwiaWF0IjoxNzA4NjA5MTgyfQ.-fPid2kEeEM42QHxWeMxxv2lJHZRSkPL-EhSH0r_iV4",
_19
"x-forwarded-host": "edge-runtime.supabase.com",
_19
"x-forwarded-port": "443",
_19
"x-forwarded-proto": "https"
_19
}