O Deno oferece suporte ao V8 Inspector Protocol usado pelo Chrome, Edge e Node.js. Isso torna possível depurar programas Deno usando Chrome DevTools ou outros clientes que oferecem suporte ao protocolo (por exemplo, VSCode).

Para ativar recursos de depuração, execute o Deno com uma das seguintes flags:

  • --inspect
  • --inspect-wait
  • --inspect-brk

--inspect

Usar a flag --inspect iniciará seu programa com um servidor inspector que permite conexões de clientes de ferramentas que oferecem suporte ao V8 Inspector Protocol, por exemplo Chrome DevTools.

Acesse chrome://inspect em um navegador derivado do Chromium para conectar o Deno ao servidor inspector. Isso permite inspecionar seu código, adicionar breakpoints e avançar passo a passo.

deno run --inspect your_script.ts

Você pode especificar opcionalmente um host e uma porta para o servidor inspector. Tanto o endereço completo quanto apenas o número da porta são aceitos:

# Default: listen on 127.0.0.1:9229
deno run --inspect your_script.ts

# Custom port
deno run --inspect=9230 your_script.ts

# Custom host and port
deno run --inspect=0.0.0.0:9229 your_script.ts

--inspect-publish-uid

Por padrão, o Deno imprime a URL WebSocket do inspector em stderr quando começa a escutar. Você pode controlar isso com --inspect-publish-uid:

  • stderr (padrão) — imprime a URL em stderr na inicialização
  • http — expõe a URL pelo endpoint HTTP /json/list na porta do inspector, em vez de imprimi-la; útil para ferramentas programáticas que fazem polling de targets disponíveis
deno run --inspect --inspect-publish-uid=http your_script.ts

:::note

Se você usar a flag --inspect, o código começará a executar imediatamente. Se seu programa for curto, talvez você não tenha tempo suficiente para conectar o debugger antes de o programa terminar a execução.

Nesses casos, tente executar com a flag --inspect-wait ou --inspect-brk, ou adicione um timeout ao final do seu código.

:::

--inspect-wait

A flag --inspect-wait espera um debugger se conectar antes de executar seu código.

deno run --inspect-wait your_script.ts

--inspect-brk

A flag --inspect-brk espera um debugger se conectar antes de executar seu código e então coloca um breakpoint no seu programa assim que você conecta, permitindo adicionar breakpoints extras ou avaliar expressões antes de retomar a execução.

Esta é a flag inspect mais usada. IDEs JetBrains e VSCode usam essa flag por padrão.

deno run --inspect-brk your_script.ts

Exemplo com Chrome DevTools

Vamos tentar depurar um programa usando Chrome Devtools. Para isso, usaremos @std/http/file-server, um servidor de arquivos estáticos.

Use a flag --inspect-brk para interromper a execução na primeira linha:

$ deno run --inspect-brk -RN jsr:@std/http/file-server
Debugger listening on ws://127.0.0.1:9229/ws/1e82c406-85a9-44ab-86b6-7341583480b1
...

Em um navegador derivado do Chromium, como Google Chrome ou Microsoft Edge, abra chrome://inspect e clique em Inspect ao lado do target:

chrome://inspect

Pode levar alguns segundos depois de abrir o DevTools para carregar todos os módulos.

DevTools opened

Você pode notar que o DevTools pausa a execução na primeira linha de _constants.ts em vez de file_server.ts. Este é o comportamento esperado, causado pela forma como ES modules são avaliados em JavaScript (_constants.ts é a dependência mais à esquerda e mais profunda de file_server.ts, então é avaliada primeiro).

Neste ponto, todo o código-fonte está disponível no DevTools, então vamos abrir file_server.ts e adicionar um breakpoint ali; vá para o painel "Sources" e expanda a árvore:

Open file_server.ts

Olhando com atenção você encontrará entradas duplicadas para cada arquivo; uma escrita normalmente e outra em itálico. A primeira é o arquivo-fonte compilado (então, no caso de arquivos .ts, será fonte JavaScript emitida), enquanto a segunda é um source map do arquivo.

Depois, adicione um breakpoint no método listenAndServe:

Break in file_server.ts

Assim que adicionamos o breakpoint, o DevTools abre automaticamente o arquivo de source map, o que permite avançar pelo código-fonte real que inclui tipos.

Agora que configuramos nossos breakpoints, podemos retomar a execução do script para inspecionar uma requisição recebida. Clique no botão "Resume script execution" para fazer isso. Talvez você precise clicar duas vezes!

Quando nosso script estiver rodando, tente enviar uma requisição e inspecioná-la no Devtools:

curl http://0.0.0.0:4507/

Break in request handling

Neste ponto, podemos inspecionar o conteúdo da requisição e avançar passo a passo para depurar o código.

Inspecionando tráfego de rede

A partir do Deno 2.8, o Chrome DevTools pode inspecionar tráfego de rede feito pelo seu programa da mesma forma que inspeciona tráfego em uma aba do navegador. Execute seu programa com --inspect-wait (ou --inspect / --inspect-brk), abra chrome://inspect em um navegador derivado do Chromium, clique em Inspect no target Deno e mude para a aba Network.

As seguintes APIs integradas são conectadas à aba Network:

  • fetch() — requisições aparecem com Type: fetch
  • requisições cliente node:http e node:https (http.request, http.get, https.request, https.get) — a coluna Type reflete o content-type da resposta (por exemplo, json, document), então qualquer biblioteca npm que faça requisições HTTP por node:http aparece junto do tráfego fetch()
  • WebSocket — conexões cliente aparecem junto das requisições HTTP, com status de handshake e headers da resposta de upgrade, message frames e um evento de close quando o socket é fechado
  • Deno.upgradeWebSocket() — upgrades WebSocket do lado servidor também são instrumentados, então você pode inspecionar os dois lados de um handshake Deno-para-Deno

Para cada requisição, você pode ver URL, método, status code, headers de request e response, corpos de request e response, e informações de timing.

Vamos testar com um pequeno programa que usa fetch():

const res = await fetch("https://api.github.com/repos/denoland/deno");
console.log(res.status, (await res.json()).stargazers_count);

Execute com --inspect-wait para que o programa pause até o DevTools conectar:

$ deno run --inspect-wait --allow-net net.ts
Debugger listening on ws://127.0.0.1:9229/...
Visit chrome://inspect to connect to the debugger.
Deno is waiting for debugger to connect.

Abra chrome://inspect, clique em Inspect no target Deno e mude para a aba Network. A requisição fetch() aparece como uma entrada normal de rede, com os painéis de request e response preenchidos:

fetch() request in the Network tab

Clique em uma requisição para ver seus headers, payload, corpo de resposta e detalhamento de timing:

Inspecting response headers and body

O mesmo se aplica a node:http e node:https, então bibliotecas npm que fazem requisições HTTP pelo cliente integrado do Node (em vez de fetch()) também aparecem na aba Network. Por exemplo:

import https from "node:https";

const options = {
  hostname: "api.github.com",
  path: "/repos/denoland/deno",
  headers: { "User-Agent": "deno-docs-example" },
};

https.get(options, (res) => {
  let body = "";
  res.on("data", (chunk) => body += chunk);
  res.on(
    "end",
    () => console.log(res.statusCode, JSON.parse(body).stargazers_count),
  );
});
$ deno run --inspect-wait --allow-net node-http.ts

A requisição aparece na aba Network com os mesmos headers, corpo e informações de timing de uma requisição fetch() — a coluna Type reflete o content-type da resposta (json neste exemplo):

node:https request in the Network tab

Conexões WebSocket aparecem na mesma aba Network, com mensagens e o evento de close mostrados conforme a conexão progride:

WebSocket connection in the Network tab

WebSockets do lado servidor criados com Deno.upgradeWebSocket() também são instrumentados, então você pode inspecionar os dois lados de uma conexão — o WebSocket cliente de saída e o upgrade do servidor que o aceita. Por exemplo, um pequeno servidor echo:

Deno.serve({ port: 8000 }, (req) => {
  if (req.headers.get("upgrade") !== "websocket") {
    return new Response("send a WebSocket request", { status: 426 });
  }
  const { socket, response } = Deno.upgradeWebSocket(req);
  socket.onmessage = (e) => socket.send(`echo: ${e.data}`);
  return response;
});
$ deno run --inspect-wait --allow-net ws-server.ts

Depois de conectar o DevTools e retomar a execução, conecte ao servidor a partir de outro terminal (por exemplo, com deno eval):

deno eval 'const ws = new WebSocket("ws://localhost:8000");
  ws.onopen = () => ws.send("hello");
  ws.onmessage = (e) => { console.log(e.data); ws.close(); };'

O upgrade e os message frames aparecem na aba Network da sessão DevTools do servidor:

Deno.upgradeWebSocket() in the Network tab

Os mesmos eventos também são expostos por node:inspector para clientes programáticos, então ferramentas que já falam Chrome DevTools Protocol contra Node podem se conectar ao Deno e observar o mesmo tráfego de rede sem mudanças.

:::note

Quando nenhum debugger está conectado, a instrumentação de rede praticamente não tem overhead — os eventos só são emitidos enquanto uma sessão optou por Network.enable.

:::

VSCode

O Deno pode ser depurado usando VSCode. Isso é melhor feito com ajuda da extensão oficial vscode_deno. A documentação sobre isso pode ser encontrada aqui.

IDEs JetBrains

Observação: garanta que você tenha este plugin Deno instalado e ativado em Preferences / Settings | Plugins. Para mais informações, veja este post no blog.

Você pode depurar Deno usando seu IDE JetBrains clicando com o botão direito no arquivo que quer depurar e selecionando a opção Debug 'Deno: <file name>'.

Debug file

Isso criará uma configuração de run/debug sem flags de permissão definidas. Se quiser configurá-las, abra sua configuração de run/debug e adicione as flags necessárias ao campo Command.

--log-level=debug

Se você estiver com problemas para conectar ao inspector, pode usar a flag --log-level=debug para obter mais informações sobre o que está acontecendo. Isso mostrará informações como resolução de módulos, requisições de rede e outras verificações de permissão.

deno run --inspect-brk --log-level=debug your_script.ts

--strace-ops

Deno ops são um mecanismo de RPC entre JavaScript e Rust. Elas fornecem funcionalidade como I/O de arquivos, rede e timers ao JavaScript. A flag --strace-ops imprime todas as ops executadas pelo Deno quando um programa roda, junto com seus timings.

deno run --strace-ops your_script.ts

Cada op deve ter um evento Dispatch e um evento Complete. O tempo entre esses dois eventos é o tempo levado para executar a op. Essa flag pode ser útil para profiling de performance, depurar programas travados ou entender como o Deno funciona por baixo.

Perfil de CPU

O Deno tem um profiler de CPU integrado: colete um profile enquanto seu programa roda, depois leia-o como relatório Markdown, flamegraph interativo ou no Chrome DevTools. Veja Perfil de CPU para flags, formatos de relatório e dicas de análise.

Integração OpenTelemetry

Para aplicações de produção ou sistemas complexos, OpenTelemetry fornece uma abordagem mais abrangente para observabilidade e depuração. O Deno inclui suporte integrado a OpenTelemetry, permitindo que você:

  • Rastreie requisições pela sua aplicação
  • Monitore métricas de performance da aplicação
  • Colete logs estruturados
  • Exporte dados de telemetria para sistemas de monitoramento
OTEL_DENO=true deno run your_script.ts

Isso coletará e exportará automaticamente dados de observabilidade do runtime, incluindo:

  • Traces de requisições HTTP
  • Métricas do runtime
  • Logs e erros do console

Para detalhes completos sobre a integração OpenTelemetry do Deno, incluindo métricas customizadas, traces e opções de configuração, veja a documentação de OpenTelemetry.

Depurando Web Workers

A partir do Deno 2.7, Web Workers podem ser depurados pelo Chrome DevTools e VS Code. Quando você executa seu programa com qualquer flag --inspect, cada worker criado aparece como um target separado em chrome://inspect ao lado da thread principal.

const worker = new Worker(import.meta.resolve("./worker.ts"), {
  type: "module",
});
worker.postMessage("start");
self.onmessage = (e) => {
  console.log("Worker received:", e.data);
  // Set breakpoints here in DevTools
};
deno run --inspect-brk --allow-read main.ts

Abra chrome://inspect, e você verá main.ts e worker.ts listados como targets inspecionáveis separados. Clique em Inspect no target do worker para abrir um painel DevTools dedicado a esse worker, onde você pode definir breakpoints, avançar pelo código e inspecionar variáveis independentemente da thread principal.

No VS Code com a extensão Deno, workers aparecem como threads separadas no painel Call Stack do debugger.

Debugging de sessão TLS

Defina a variável de ambiente SSLKEYLOGFILE para registrar chaves de sessão TLS em um arquivo. Isso permite descriptografar e inspecionar tráfego de rede criptografado com ferramentas como Wireshark:

SSLKEYLOGFILE=./keys.log deno run -N main.ts

Depois carregue keys.log no Wireshark (Edit > Preferences > Protocols > TLS > (Pre)-Master-Secret log filename) para descriptografar tráfego TLS capturado.