O Deno tem suporte integrado a OpenTelemetry.

OpenTelemetry is a collection of APIs, SDKs, and tools. Use it to instrument, generate, collect, and export telemetry data (metrics, logs, and traces) to help you analyze your software’s performance and behavior.

- https://opentelemetry.io/

Essa integração permite monitorar aplicações Deno usando ferramentas de observabilidade OpenTelemetry com instrumentos como logs, métricas e traces.

O Deno fornece os seguintes recursos:

Início rápido

Para ativar a integração OpenTelemetry, defina a variável de ambiente OTEL_DENO=true:

OTEL_DENO=true deno run my_script.ts

Isso coletará e exportará automaticamente dados de observabilidade do runtime para um endpoint OpenTelemetry em localhost:4318, usando Protobuf sobre HTTP (http/protobuf).

:::tip

Se quiser ver rapidamente a saída OpenTelemetry sem configurar um collector, você pode usar o console exporter integrado para imprimir spans, logs e métricas diretamente em stderr em formato legível:

OTEL_DENO=true OTEL_EXPORTER_OTLP_PROTOCOL=console deno run my_script.ts

Saída de exemplo:

SPAN inner span [00000000000000000000000000000001/0000000000000002] Internal 0.495ms
  parent: 0000000000000001
  scope: example-tracer
  key: value
LOG [INFO] 2025-03-14T13:47:07.235Z "hello from inner"
  scope: [email protected]
  trace: 00000000000000000000000000000001/0000000000000002

:::

:::tip

Se quiser visualizar dados de telemetria em um dashboard, você pode começar com uma stack LGTM local no Docker (Loki (logs), Grafana (dashboard), Tempo (traces) e Prometheus (metrics)) executando o comando:

docker run --name lgtm -p 3000:3000 -p 4317:4317 -p 4318:4318 --rm -ti \
	-v "$PWD"/lgtm/grafana:/data/grafana \
	-v "$PWD"/lgtm/prometheus:/data/prometheus \
	-v "$PWD"/lgtm/loki:/data/loki \
	-e GF_PATHS_DATA=/data/grafana \
	docker.io/grafana/otel-lgtm:0.8.1

Depois você pode acessar o dashboard Grafana em http://localhost:3000 com o usuário admin e senha admin.

:::

Isso coletará e exportará automaticamente dados de observabilidade do runtime, como console.log, traces para requisições HTTP e métricas do runtime Deno. Saiba mais sobre auto instrumentação.

Você também pode criar suas próprias métricas, traces e logs usando o pacote npm:@opentelemetry/api. Saiba mais sobre métricas definidas pelo usuário.

Auto instrumentation

O Deno coleta e exporta automaticamente alguns dados de observabilidade para o endpoint OTLP.

Esses dados são exportados no instrumentation scope integrado do runtime Deno. Esse scope tem o nome deno. A versão do runtime Deno é a versão do instrumentation scope deno (por exemplo, deno:2.1.4).

Traces

O Deno cria spans automaticamente para várias operações, como:

  • Requisições HTTP recebidas servidas com Deno.serve.
  • Requisições HTTP de saída feitas com fetch.
  • Invocações de jobs Deno.cron() (adicionado no Deno 2.7).

Deno.serve

Quando você usa Deno.serve para criar um servidor HTTP, um span é criado para cada requisição recebida. O span termina automaticamente quando os headers de resposta são enviados (não quando o corpo da resposta termina de ser enviado).

O nome do span criado é ${method}. O span kind é server.

Os seguintes atributos são adicionados automaticamente ao span na criação:

  • http.request.method: o método HTTP da requisição.
  • url.full: a URL completa da requisição (como seria reportada por req.url).
  • url.scheme: o scheme da URL da requisição (por exemplo, http ou https).
  • url.path: o caminho da URL da requisição.
  • url.query: a query string da URL da requisição.

Depois que a requisição é tratada, os seguintes atributos são adicionados:

  • http.response.status_code: o status code da resposta.

O Deno não adiciona automaticamente um atributo http.route ao span, pois a rota não é conhecida pelo runtime e é determinada pela lógica de roteamento na função handler do usuário. Se quiser adicionar um atributo http.route ao span, você pode fazê-lo na sua função handler usando npm:@opentelemetry/api. Nesse caso, você também deve atualizar o nome do span para incluir a rota.

import { trace } from "npm:@opentelemetry/api@1";

const INDEX_ROUTE = new URLPattern({ pathname: "/" });
const BOOK_ROUTE = new URLPattern({ pathname: "/book/:id" });

Deno.serve(async (req) => {
  const span = trace.getActiveSpan();
  if (INDEX_ROUTE.test(req.url)) {
    span.setAttribute("http.route", "/");
    span.updateName(`${req.method} /`);

    // handle index route
  } else if (BOOK_ROUTE.test(req.url)) {
    span.setAttribute("http.route", "/book/:id");
    span.updateName(`${req.method} /book/:id`);

    // handle book route
  } else {
    return new Response("Not found", { status: 404 });
  }
});

fetch

Quando você usa fetch para fazer uma requisição HTTP, um span é criado para a requisição. O span termina automaticamente quando os headers da resposta são recebidos.

O nome do span criado é ${method}. O span kind é client.

Os seguintes atributos são adicionados automaticamente ao span na criação:

  • http.request.method: o método HTTP da requisição.
  • url.full: a URL completa da requisição.
  • url.scheme: o scheme da URL da requisição.
  • url.path: o caminho da URL da requisição.
  • url.query: a query string da URL da requisição.

Depois que a resposta é recebida, os seguintes atributos são adicionados:

  • http.status_code: o status code da resposta.

Métricas

As seguintes métricas são coletadas e exportadas automaticamente:

Deno.serve / Deno.serveHttp

http.server.request.duration

Um histograma da duração de requisições HTTP recebidas servidas com Deno.serve ou Deno.serveHttp. O tempo medido vai do recebimento da requisição até o envio dos headers de resposta. Isso não inclui o tempo para enviar o corpo da resposta. A unidade dessa métrica é segundos. Os buckets do histograma são [0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1.0, 2.5, 5.0, 7.5, 10.0].

Esta métrica é registrada com os seguintes atributos:

  • http.request.method: o método HTTP da requisição.
  • url.scheme: o scheme da URL da requisição.
  • network.protocol.version: a versão do protocolo HTTP usado na requisição (por exemplo, 1.1 ou 2).
  • server.address: o endereço em que o servidor está escutando.
  • server.port: a porta em que o servidor está escutando.
  • http.response.status_code: o status code da resposta (se a requisição foi tratada sem erro fatal).
  • error.type: o tipo de erro ocorrido (se o tratamento da requisição foi sujeito a erro).
http.server.active_requests

Um gauge do número de requisições ativas sendo tratadas por Deno.serve ou Deno.serveHttp em um dado momento. Este é o número de requisições recebidas mas ainda não respondidas (quando os headers de resposta ainda não foram enviados). Esta métrica é registrada com os seguintes atributos:

  • http.request.method: o método HTTP da requisição.
  • url.scheme: o scheme da URL da requisição.
  • server.address: o endereço em que o servidor está escutando.
  • server.port: a porta em que o servidor está escutando.
http.server.request.body.size

Um histograma do tamanho do corpo da requisição em requisições HTTP recebidas servidas com Deno.serve ou Deno.serveHttp. A unidade dessa métrica é bytes. Os buckets do histograma são [0, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000].

Esta métrica é registrada com os seguintes atributos:

  • http.request.method: o método HTTP da requisição.
  • url.scheme: o scheme da URL da requisição.
  • network.protocol.version: a versão do protocolo HTTP usado na requisição (por exemplo, 1.1 ou 2).
  • server.address: o endereço em que o servidor está escutando.
  • server.port: a porta em que o servidor está escutando.
  • http.response.status_code: o status code da resposta (se a requisição foi tratada sem erro fatal).
  • error.type: o tipo de erro ocorrido (se o tratamento da requisição foi sujeito a erro).
http.server.response.body.size

Um histograma do tamanho do corpo da resposta em requisições HTTP recebidas servidas com Deno.serve ou Deno.serveHttp. A unidade dessa métrica é bytes. Os buckets do histograma são [0, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000].

Esta métrica é registrada com os mesmos atributos de http.server.request.body.size.

Logs

Os seguintes logs são coletados e exportados automaticamente:

  • Qualquer log criado com métodos console.*, como console.log e console.error.
  • Qualquer log criado pelo runtime Deno, como logs de debug, logs Downloading e similares.
  • Qualquer erro que faça o runtime Deno sair (tanto de código do usuário quanto do próprio runtime).

Logs emitidos por código JavaScript serão exportados com o contexto de span relevante, se o log ocorreu dentro de um span ativo.

A auto instrumentação de console pode ser configurada com a variável de ambiente OTEL_DENO_CONSOLE:

  • capture: logs são emitidos para stdout/stderr e também exportados com OpenTelemetry (padrão).
  • replace: logs são apenas exportados com OpenTelemetry, não emitidos para stdout/stderr.
  • ignore: logs são emitidos apenas para stdout/stderr e não serão exportados com OpenTelemetry.

Auditoria de permissões

O Deno pode rotear o log de auditoria de permissões para o exporter OpenTelemetry junto do restante dos seus traces, métricas e logs. Defina DENO_AUDIT_PERMISSIONS=otel (em vez de um caminho de arquivo) e cada acesso a permissão — permitido ou negado — será emitido como um registro de log OpenTelemetry com estes atributos:

  • deno.permission.type — o nome da permissão (read, net, env, …).
  • deno.permission.value — o valor específico sendo verificado (um caminho, host, nome de variável etc.).
  • deno.permission.stack — os frames de stack JavaScript no local de acesso, presente apenas quando DENO_TRACE_PERMISSIONS também está definido.
OTEL_DENO=true DENO_AUDIT_PERMISSIONS=otel deno run -A main.ts

Isso é útil quando você já coleta dados OpenTelemetry: a auditoria chega ao mesmo backend dos traces de requisição, então você pode correlacionar qual requisição acionou qual acesso de permissão. Veja auditoria de permissões para o conjunto completo de atributos e o modo JSONL com caminho de arquivo.

Métricas do usuário

Além dos dados de telemetria coletados automaticamente, você também pode criar suas próprias métricas e traces usando o pacote npm:@opentelemetry/api.

Você não precisa configurar o pacote npm:@opentelemetry/api para usá-lo com o Deno. O Deno configura o pacote automaticamente. Não é necessário chamar metrics.setGlobalMeterProvider(), trace.setGlobalTracerProvider() ou context.setGlobalContextManager(). Toda configuração de resources, exporter settings etc. é feita por variáveis de ambiente.

O Deno funciona com a versão 1.x do pacote npm:@opentelemetry/api. Você pode importar diretamente de npm:@opentelemetry/api@1 ou instalar o pacote localmente com deno add e importar de @opentelemetry/api.

deno add npm:@opentelemetry/api@1

Tanto para traces quanto para métricas, você precisa definir nomes para o tracer e o meter. Se está instrumentando uma biblioteca, nomeie o tracer ou meter a partir da biblioteca (como my-awesome-lib). Se está instrumentando uma aplicação, use o nome da aplicação (como my-app). A versão do tracer ou meter deve ser definida como a versão da biblioteca ou aplicação.

Traces

Para criar um novo span, primeiro importe o objeto trace de npm:@opentelemetry/api e crie um novo tracer:

import { trace } from "npm:@opentelemetry/api@1";

const tracer = trace.getTracer("my-app", "1.0.0");

Depois, crie um novo span usando tracer.startActiveSpan e passe uma função callback. Você precisa encerrar manualmente o span chamando end no objeto span retornado por startActiveSpan.

function myFunction() {
  return tracer.startActiveSpan("myFunction", (span) => {
    try {
      // do myFunction's work
    } catch (error) {
      span.recordException(error);
      span.setStatus({
        code: trace.SpanStatusCode.ERROR,
        message: (error as Error).message,
      });
      throw error;
    } finally {
      span.end();
    }
  });
}

span.end() deve ser chamado em um bloco finally para garantir que o span termine mesmo se ocorrer erro. span.recordException e span.setStatus também devem ser chamados em um bloco catch, para registrar erros ocorridos.

Dentro do callback, o span criado é o "active span". Você pode obtê-lo com trace.getActiveSpan(). O "active span" será usado como parent span para spans criados (manualmente ou automaticamente pelo runtime) dentro do callback (ou em funções chamadas a partir dele). Saiba mais sobre propagação de contexto.

O método startActiveSpan retorna o valor de retorno do callback.

Spans podem receber atributos durante sua vida. Atributos são pares chave-valor que representam metadados estruturados sobre o span. Eles podem ser adicionados com setAttribute e setAttributes.

span.setAttribute("key", "value");
span.setAttributes({ success: true, "bar.count": 42n, "foo.duration": 123.45 });

Valores de atributo podem ser strings, números (floats), bigints (limitados a u64), booleans ou arrays desses tipos. Outros valores são ignorados.

O nome de um span pode ser atualizado com updateName.

span.updateName("new name");

O status de um span pode ser definido com setStatus. recordException registra uma exceção ocorrida durante a vida do span, criando um evento com stack trace e nome da exceção e anexando-o ao span. recordException não define o status do span como ERROR; você deve fazer isso manualmente.

import { SpanStatusCode } from "npm:@opentelemetry/api@1";

span.setStatus({
  code: SpanStatusCode.ERROR,
  message: "An error occurred",
});
span.recordException(new Error("An error occurred"));

// or

span.setStatus({
  code: SpanStatusCode.OK,
});

Spans também podem ter events e links adicionados. Events são pontos no tempo associados ao span. Links são referências a outros spans.

// Add an event to the span
span.addEvent("button_clicked", {
  id: "submit-button",
  action: "submit",
});

// Add an event with a timestamp
span.addEvent("process_completed", { status: "success" }, Date.now());

Events podem incluir atributos opcionais semelhantes a spans. Eles são úteis para marcar momentos significativos dentro da vida do span sem criar spans separados.

Spans também podem ser criados manualmente com tracer.startSpan, que retorna um objeto span. Esse método não define o span criado como active span, então ele não será usado automaticamente como parent span para spans criados depois, nem para chamadas console.log. Um span pode ser definido manualmente como active span para um callback usando a API de propagação de contexto.

Tanto tracer.startActiveSpan quanto tracer.startSpan podem receber um objeto de opções opcional contendo:

  • kind: o tipo do span. Pode ser SpanKind.CLIENT, SpanKind.SERVER, SpanKind.PRODUCER, SpanKind.CONSUMER ou SpanKind.INTERNAL. O padrão é SpanKind.INTERNAL.
  • startTime: um objeto Date representando o início do span, ou um número em milissegundos desde Unix epoch. Se omitido, usa o horário atual.
  • attributes: objeto com atributos para adicionar ao span.
  • links: array de links para adicionar ao span.
  • root: boolean indicando se o span deve ser root. Se true, o span não terá parent span (mesmo se houver um active span).

Depois do objeto de opções, ambos também podem receber um objeto context da API de propagação de contexto.

Saiba mais sobre a API completa de tracing na documentação da API OpenTelemetry JS.

Métricas

Para criar uma métrica, primeiro importe o objeto metrics de npm:@opentelemetry/api e crie um novo meter:

import { metrics } from "npm:@opentelemetry/api@1";

const meter = metrics.getMeter("my-app", "1.0.0");

Depois, um instrumento pode ser criado a partir do meter e usado para registrar valores:

const counter = meter.createCounter("my_counter", {
  description: "A simple counter",
  unit: "1",
});

counter.add(1);
counter.add(2);

Cada registro também pode ter atributos associados:

counter.add(1, { color: "red" });
counter.add(2, { color: "blue" });

:::tip

Em OpenTelemetry, atributos de métricas geralmente devem ter baixa cardinalidade. Isso significa que não devem existir combinações únicas demais de valores de atributos. Por exemplo, provavelmente tudo bem ter um atributo para o continente do usuário, mas seria cardinalidade alta demais ter latitude e longitude exatas. Atributos de alta cardinalidade podem causar problemas de armazenamento e exportação de métricas e devem ser evitados. Use spans e logs para dados de alta cardinalidade.

:::

Há vários tipos de instrumentos que podem ser criados com um meter:

  • Counter: valor monotonicamente crescente. Counters só podem ser positivos e servem para valores que sempre aumentam, como número de requisições tratadas.
  • UpDownCounter: valor que pode aumentar e diminuir, como número de conexões ativas ou requisições em andamento.
  • Gauge: valor que pode ser definido para qualquer valor, usado para coisas que não "acumulam" ao longo do tempo, mas têm um valor específico em dado momento, como temperatura atual.
  • Histogram: valor registrado como distribuição. Histogramas servem para valores como tempo de resposta de uma requisição em milissegundos e podem calcular percentis, médias e outras estatísticas. Eles têm limites de buckets predefinidos; por padrão: [0.0, 5.0, 10.0, 25.0, 50.0, 75.0, 100.0, 250.0, 500.0, 750.0, 1000.0, 2500.0, 5000.0, 7500.0, 10000.0].

Também existem instrumentos observáveis. Eles não têm método síncrono de registro; em vez disso, retornam um callback chamado quando o SDK OpenTelemetry está pronto para registrar um valor, por exemplo logo antes de exportar.

const counter = meter.createObservableCounter("my_counter", {
  description: "A simple counter",
  unit: "1",
});
counter.addCallback((res) => {
  res.observe(1);
  // or
  res.observe(1, { color: "red" });
});

Há três tipos de instrumentos observáveis:

  • ObservableCounter: counter observado assincronamente, útil para valores que sempre aumentam.
  • ObservableUpDownCounter: valor que pode aumentar e diminuir e ser observado assincronamente.
  • ObservableGauge: valor observado assincronamente que pode assumir qualquer valor em dado momento.

Saiba mais sobre a API completa de métricas na documentação da API OpenTelemetry JS.

Exemplos práticos

Para exemplos práticos de implementação de OpenTelemetry em aplicações Deno, veja nossos tutoriais:

Propagação de contexto

Em OpenTelemetry, propagação de contexto é o processo de passar informações de contexto (como o span atual) de uma parte da aplicação para outra, sem precisar passá-las explicitamente como argumento para toda função.

No Deno, a propagação de contexto usa as regras de AsyncContext, a proposta TC39 para propagação de contexto assíncrono. A API AsyncContext ainda não é exposta a usuários no Deno, mas é usada internamente para propagar o active span e outras informações de contexto através de fronteiras assíncronas.

Resumo rápido de como a propagação AsyncContext funciona:

  • Quando uma nova task assíncrona é iniciada (como uma promise ou timer), o contexto atual é salvo.
  • Então outro código pode executar concorrentemente com a task assíncrona, em um contexto diferente.
  • Quando a task assíncrona termina, o contexto salvo é restaurado.

Isso significa que a propagação de contexto assíncrono se comporta essencialmente como uma variável global escopada à task assíncrona atual, e é copiada automaticamente para novas tasks assíncronas iniciadas a partir dela.

A API context de npm:@opentelemetry/api@1 expõe essa funcionalidade:

import { context } from "npm:@opentelemetry/api@1";

// Get the currently active context
const currentContext = context.active();

// You can add create a new context with a value added to it
const newContext = currentContext.setValue("id", 1);

// The current context is not changed by calling setValue
console.log(currentContext.getValue("id")); // undefined

// You can run a function inside a new context
context.with(newContext, () => {
  // Any code in this block will run with the new context
  console.log(context.active().getValue("id")); // 1

  // The context is also available in any functions called from this block
  function myFunction() {
    return context.active().getValue("id");
  }
  console.log(myFunction()); // 1

  // And it is also available in any asynchronous callbacks scheduled from here
  setTimeout(() => {
    console.log(context.active().getValue("id")); // 1
  }, 10);
});

// Outside, the context is still the same
console.log(context.active().getValue("id")); // undefined

A API de contexto também integra com spans. Para rodar uma função no contexto de um span específico, o span pode ser adicionado a um contexto, e então a função pode rodar nesse contexto:

import { context, trace } from "npm:@opentelemetry/api@1";

const tracer = trace.getTracer("my-app", "1.0.0");

const span = tracer.startSpan("myFunction");
const contextWithSpan = trace.setSpan(context.active(), span);

context.with(contextWithSpan, () => {
  const activeSpan = trace.getActiveSpan();
  console.log(activeSpan === span); // true
});

// Don't forget to end the span!
span.end();

Saiba mais sobre a API completa de contexto na documentação da API OpenTelemetry JS.

Configuração

A integração OpenTelemetry pode ser ativada definindo a variável de ambiente OTEL_DENO=true.

O endpoint e protocolo do OTLP exporter podem ser configurados com as variáveis OTEL_EXPORTER_OTLP_ENDPOINT e OTEL_EXPORTER_OTLP_PROTOCOL. Valores aceitos para OTEL_EXPORTER_OTLP_PROTOCOL:

  • http/protobuf (padrão): exporta usando Protobuf sobre HTTP para o endpoint configurado.
  • http/json: exporta usando JSON sobre HTTP para o endpoint configurado.
  • grpc: exporta usando gRPC (Protobuf sobre HTTP/2). Disponível no Deno 2.8+. Útil para collectors que aceitam apenas gRPC, como o agente OpenTelemetry gerenciado do Azure Container Apps. A porta OTLP gRPC padrão é 4317, então você normalmente também define OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317.
  • console: imprime spans, logs e métricas em stderr em formato de texto legível. Útil para depurar e testar instrumentação sem rodar um collector OTLP. Ao usar console, nenhuma configuração de endpoint é necessária.

Se o endpoint exigir autenticação, headers podem ser configurados com OTEL_EXPORTER_OTLP_HEADERS.

Endpoints também podem ser sobrescritos individualmente para métricas, traces e logs usando variáveis específicas, como:

  • OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
  • OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
  • OTEL_EXPORTER_OTLP_LOGS_ENDPOINT

Para mais informações sobre headers que podem configurar o OTLP exporter, veja o site OpenTelemetry.

O resource associado aos dados de telemetria pode ser configurado com OTEL_SERVICE_NAME e OTEL_RESOURCE_ATTRIBUTES. Além dos atributos definidos via OTEL_RESOURCE_ATTRIBUTES, os seguintes são definidos automaticamente:

  • service.name: se OTEL_SERVICE_NAME não estiver definido, o valor é <unknown_service>.
  • process.runtime.name: deno
  • process.runtime.version: a versão do runtime Deno.
  • telemetry.sdk.name: deno-opentelemetry
  • telemetry.sdk.language: deno-rust
  • telemetry.sdk.version: a versão do runtime Deno mais a versão do crate Rust opentelemetry usado pelo Deno, separadas por -.

Propagators podem ser configurados com OTEL_PROPAGATORS. O padrão é tracecontext,baggage. Múltiplos propagators podem ser separados por vírgula. Atualmente são aceitos:

  • tracecontext: formato W3C Trace Context
  • baggage: formato W3C Baggage

A frequência de coleta de métricas pode ser configurada com OTEL_METRIC_EXPORT_INTERVAL. O padrão é 60000 milissegundos (60 segundos).

Batching do span exporter e do log exporter pode ser configurado pelas variáveis descritas na especificação OpenTelemetry e na seção de batch log record processor.

Propagators

O Deno oferece suporte a propagators de contexto, que permitem propagação automática de contexto de trace entre limites de processo para distributed tracing, permitindo acompanhar requisições enquanto fluem por serviços diferentes.

Propagators são responsáveis por codificar e decodificar informações de contexto (como trace e span IDs) para e de formatos carrier (como headers HTTP). Isso permite manter o contexto de trace através de fronteiras de serviço.

Por padrão, o Deno oferece suporte a:

  • tracecontext: formato W3C Trace Context, o padrão para propagar contexto de trace via headers HTTP.
  • baggage: formato W3C Baggage, que permite passar pares chave-valor através de fronteiras de serviço.

:::note

Esses propagators funcionam automaticamente com a API fetch do Deno e Deno.serve, habilitando tracing ponta a ponta em requisições HTTP sem gerenciamento manual de contexto.

:::

Você pode acessar a API de propagação pelo pacote @opentelemetry/api:

import { context, propagation, trace } from "npm:@opentelemetry/api@1";

// Extract context from incoming headers
function extractContextFromHeaders(headers: Headers) {
  const ctx = context.active();
  return propagation.extract(ctx, headers);
}

// Inject context into outgoing headers
function injectContextIntoHeaders(headers: Headers) {
  const ctx = context.active();
  propagation.inject(ctx, headers);
  return headers;
}

// Example: Making a fetch request that propagates trace context
async function tracedFetch(url: string) {
  const headers = new Headers();
  injectContextIntoHeaders(headers);

  return await fetch(url, { headers });
}

Limitações

Enquanto a integração OpenTelemetry para Deno está em desenvolvimento, há algumas limitações importantes:

  • Traces são sempre amostrados (ou seja, OTEL_TRACE_SAMPLER=parentbased_always_on).
  • Traces só aceitam links sem atributos.
  • Metric exemplars não têm suporte.
  • Streams de log customizados (por exemplo, logs que não sejam console.log e console.error) não têm suporte.
  • Os exporters aceitos são OTLP (http/protobuf, http/json, grpc) e console. Outros formatos de exporter não têm suporte.
  • Métricas de meters observáveis (assíncronos) não são coletadas em exit/crash do processo, então o último valor pode não ser exportado. Métricas síncronas são exportadas em exit/crash.
  • Os limites especificados nas variáveis OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT, OTEL_ATTRIBUTE_COUNT_LIMIT, OTEL_SPAN_EVENT_COUNT_LIMIT, OTEL_SPAN_LINK_COUNT_LIMIT, OTEL_EVENT_ATTRIBUTE_COUNT_LIMIT e OTEL_LINK_ATTRIBUTE_COUNT_LIMIT não são respeitados para trace spans.
  • A variável OTEL_METRIC_EXPORT_TIMEOUT não é respeitada.
  • Métodos HTTP desconhecidos não são normalizados para _OTHER no atributo http.request.method, conforme as convenções semânticas OpenTelemetry.
  • O span de servidor HTTP para Deno.serve não tem um status OpenTelemetry definido; se o handler lança erro (ou seja, onError é invocado), o span não terá status de erro e o erro não será anexado ao span por evento.
  • Não há mecanismo para adicionar atributo http.route ao span cliente HTTP de fetch, nem para atualizar o nome do span para incluir a rota.