Usando bibliotecas de instrumentação

Como instrumentar bibliotecas das quais uma aplicação depende

Ao desenvolver uma aplicação, é possível utilizar bibliotecas e frameworks de terceiros para acelerar seu trabalho. Caso você instrumente sua aplicação utilizando OpenTelemetry, talvez queira evitar gastar tempo adicional para adicionar manualmente rastros, logs e métricas às bibliotecas e frameworks de terceiros que utiliza.

Muitas bibliotecas e frameworks já oferecem suporte ao OpenTelemetry ou são compatíveis por meio da instrumentação, permitindo gerar dados de telemetria que podem ser exportados para um backend de observabilidade.

Caso você esteja instrumentando uma aplicação ou serviço que utilize bibliotecas ou frameworks de terceiros, siga estas instruções para aprender como usar bibliotecas instrumentadas nativamente e bibliotecas de instrumentação para as dependências do seu projeto.

Usar bibliotecas com instrumentação nativa

Se uma biblioteca oferece suporte ao OpenTelemetry por padrão, é possível obter rastros, métricas e logs emitidos por essa biblioteca ao adicionar e configurar o SDK do OpenTelemetry na sua aplicação.

A biblioteca pode exigir alguma configuração adicional para sua instrumentação. Consulte a documentação dessa biblioteca para saber mais.

Usando bibliotecas de instrumentação

Se uma biblioteca não vem com OpenTelemetry de forma nativa, é possível utilizar bibliotecas de instrumentação para gerar dados de telemetria para uma biblioteca ou framework.

Por exemplo, a biblioteca de instrumentação para Express irá criar automaticamente trechos baseados nas requisições HTTP de entrada.

Configuração

Cada biblioteca de instrumentação é um pacote NPM. Por exemplo, veja como instalar as bibliotecas instrumentation-express e instrumentation-http para instrumentar tráfego HTTP de entrada e saída:

npm install --save @opentelemetry/instrumentation-http @opentelemetry/instrumentation-express

O OpenTelemetry JavaScript também define metapacotes (metapackages) auto-instrumentation-node e auto-instrumentation-web, que agrupam todas as bibliotecas de instrumentação baseadas em Node.js ou web em um único pacote. É uma maneira conveniente de adicionar telemetria gerada automaticamente para todas as suas bibliotecas com esforço mínimo:

npm install --save @opentelemetry/auto-instrumentations-node
npm install --save @opentelemetry/auto-instrumentations-web

Note que usar esses metapacotes aumenta o tamanho do seu grafo de dependências. Utilize bibliotecas de instrumentação individuais caso você saiba exatamente quais precisa.

Registro

Após instalar as bibliotecas de instrumentação necessárias, registre-as no SDK do OpenTelemetry para Node.js. Se você seguiu os Primeiros Passos, você já utiliza os metapacotes. Se você seguiu as instruções para inicializar o SDK com instrumentação manual, atualize seu instrumentation.ts (ou instrumentation.js) da seguinte forma:

/*instrumentation.ts*/
...
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';

const sdk = new NodeSDK({
  ...
  // Registra todos os pacotes de instrumentação
  instrumentations: [getNodeAutoInstrumentations()]
});

sdk.start()
/*instrumentation.js*/
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');

const sdk = new NodeSDK({
  ...
  // Registra todos os pacotes de instrumentação
  instrumentations: [getNodeAutoInstrumentations()]
});

Para desabilitar bibliotecas de instrumentação individuais, aplique a seguinte alteração:

/*instrumentation.ts*/
...
import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';

const sdk = new NodeSDK({
  ...
  // Registra todos os pacotes de instrumentação
  instrumentations: [
    getNodeAutoInstrumentations({
      '@opentelemetry/instrumentation-fs': {
        enabled: false,
      },
    }),
  ],
});

sdk.start()
/*instrumentation.js*/
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');

const sdk = new NodeSDK({
  ...
  // Registra todos os pacotes de instrumentação
  instrumentations: [
    getNodeAutoInstrumentations({
      '@opentelemetry/instrumentation-fs': {
        enabled: false,
      },
    }),
  ],
});

Para carregar apenas bibliotecas de instrumentação individuais, substitua [getNodeAutoInstrumentations()] pela lista daquelas que você precisa:

/*instrumentation.ts*/
...
import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";

const sdk = new NodeSDK({
  ...
  instrumentations: [
    // A instrumentação Express espera que a camada HTTP esteja instrumentada
    new HttpInstrumentation(),
    new ExpressInstrumentation(),
  ]
});

sdk.start()
/*instrumentation.js*/
const { HttpInstrumentation } = require("@opentelemetry/instrumentation-http");
const { ExpressInstrumentation } = require("@opentelemetry/instrumentation-express");

const sdk = new NodeSDK({
  ...
  instrumentations: [
    // A instrumentação Express espera que a camada HTTP esteja instrumentada
    new HttpInstrumentation(),
    new ExpressInstrumentation(),
  ]
});

Configuração

Algumas bibliotecas de instrumentação oferecem opções de configuração adicionais.

Por exemplo, a instrumentação Express oferece formas de ignorar middlewares especificados ou enriquecer trechos criados automaticamente com um hook de requisição:

import { Span } from '@opentelemetry/api';
import {
  SEMATTRS_HTTP_METHOD,
  SEMATTRS_HTTP_URL,
} from '@opentelemetry/semantic-conventions';
import {
  ExpressInstrumentation,
  ExpressLayerType,
  ExpressRequestInfo,
} from '@opentelemetry/instrumentation-express';

const expressInstrumentation = new ExpressInstrumentation({
  requestHook: function (span: Span, info: ExpressRequestInfo) {
    if (info.layerType === ExpressLayerType.REQUEST_HANDLER) {
      span.setAttribute(SEMATTRS_HTTP_METHOD, info.request.method);
      span.setAttribute(SEMATTRS_HTTP_URL, info.request.baseUrl);
    }
  },
});
/*instrumentation.js*/
const {
  SEMATTRS_HTTP_METHOD,
  SEMATTRS_HTTP_URL,
} = require('@opentelemetry/semantic-conventions');
const {
  ExpressInstrumentation,
  ExpressLayerType,
} = require('@opentelemetry/instrumentation-express');

const expressInstrumentation = new ExpressInstrumentation({
  requestHook: function (span, info) {
    if (info.layerType === ExpressLayerType.REQUEST_HANDLER) {
      span.setAttribute(SEMATTRS_HTTP_METHOD, info.request.method);
      span.setAttribute(SEMATTRS_HTTP_URL, info.request.baseUrl);
    }
  },
});

Consulte a documentação de cada biblioteca de instrumentação para opções avançadas.

Bibliotecas de instrumentação disponíveis

É possível encontrar a lista de instrumentações disponíveis no registro.

Instrumentar uma biblioteca nativamente

Caso queira adicionar instrumentação nativa à sua biblioteca, consulte a seguinte documentação:

  • A página de conceito Bibliotecas fornece informações úteis sobre quando instrumentar e o que instrumentar.
  • A página de instrumentação manual fornece exemplos de código necessários para criar rastros, métricas e logs para sua biblioteca.
  • O Guia de Implementação de Instrumentação para Node.js e navegador contém boas práticas específicas de JavaScript para criar instrumentação de bibliotecas.

Criar uma biblioteca de instrumentação

Embora ter observabilidade pronta para uso em uma aplicação seja a forma preferida, isso nem sempre é possível ou desejado. Nesses casos, você pode criar uma biblioteca de instrumentação, que irá injetar chamadas de instrumentação utilizando mecanismos como empacotamento de interfaces, assinatura de funções de retorno (callbacks) específicos da biblioteca ou tradução de telemetria existente para o modelo do OpenTelemetry.

Para criar uma biblioteca desse tipo, siga o Guia de Implementação de Instrumentação para Node.js e navegador.