Фронтенд

Фронтенд відповідає за надання інтерфейсу користувача, а також API, яке використовується інтерфейсом або іншими клієнтами. Застосунок базується на Next.JS, щоб забезпечити вебінтерфейс на основі React та маршрути API.

Сирці фронтенду

Інструментування сервера

Рекомендується використовувати модулі Node, що вимагається, при запуску вашого застосунку Node.js для ініціалізації SDK та автоінструментування. При ініціалізації OpenTelemetry Node.js SDK ви можете опціонально вказати, які бібліотеки автоінструментування використовувати, або скористатися функцією getNodeAutoInstrumentations(), яка включає більшість популярних фреймворків. Файл utils/telemetry/Instrumentation.js містить весь код, необхідний для ініціалізації SDK та автоінструментування на основі стандартних змінних середовища OpenTelemetry для експорту OTLP, атрибутів ресурсу та назви сервісу.

const FrontendTracer = async () => {
  const { ZoneContextManager } = await import('@opentelemetry/context-zone');

  let resource = resourceFromAttributes({
    [ATTR_SERVICE_NAME]: NEXT_PUBLIC_OTEL_SERVICE_NAME,
  });
  const detectedResources = detectResources({ detectors: [browserDetector] });
  resource = resource.merge(detectedResources);

  const provider = new WebTracerProvider({
    resource,
    spanProcessors: [
      new SessionIdProcessor(),
      new BatchSpanProcessor(
        new OTLPTraceExporter({
          url:
            NEXT_PUBLIC_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT ||
            'http://localhost:4318/v1/traces',
        }),
        {
          scheduledDelayMillis: 500,
        },
      ),
    ],
  });

  const contextManager = new ZoneContextManager();

  provider.register({
    contextManager,
    propagator: new CompositePropagator({
      propagators: [
        new W3CBaggagePropagator(),
        new W3CTraceContextPropagator(),
      ],
    }),
  });

  registerInstrumentations({
    tracerProvider: provider,
    instrumentations: [
      getWebAutoInstrumentations({
        '@opentelemetry/instrumentation-fetch': {
          propagateTraceHeaderCorsUrls: /.*/,
          clearTimingResources: true,
          applyCustomAttributesOnSpan(span) {
            span.setAttribute('app.synthetic_request', IS_SYNTHETIC_REQUEST);
          },
        },
      }),
    ],
  });
};

Модулі Node, що вимагаються, завантажуються за допомогою аргументу командного рядка --require. Це можна зробити в розділі scripts.start файлу package.json і запустити застосунок за допомогою npm start.

"scripts": {
  "start": "node --require ./Instrumentation.js server.js",
},

Трейси

Винятки та статуси відрізків

Ви можете використовувати функцію recordException обʼєкта відрізка, щоб створити подію відрізка з повним стеком обробленої помилки. При записі винятку також не забудьте встановити статус відрізка відповідно. Ви можете побачити це в блоці catch функції NextApiHandler у файлі utils/telemetry/InstrumentationMiddleware.ts.

span.recordException(error as Exception);
span.setStatus({ code: SpanStatusCode.ERROR });

Створення нових відрізків

Нові відрізки можна створити та запустити за допомогою Tracer.startSpan("spanName", options). Декілька опцій можна використовувати для вказівки як відрізок може бути створений.

  • root: true створить нове трасування, встановивши цей відрізок як кореневий.
  • links використовуються для вказівки посилань на інші відрізки (навіть в іншому трасуванні), які повинні бути згадані.
  • attributes є парами ключ/значення, доданими до відрізка, зазвичай використовуються для контексту застосунку.
span = tracer.startSpan(`${method}`, {
  root: true,
  kind: SpanKind.SERVER,
  links: [{ context: syntheticSpan.spanContext() }],
  attributes: {
    'app.synthetic_request': true,
    [ATTR_HTTP_RESPONSE_STATUS_CODE]: response.statusCode,
    [ATTR_HTTP_REQUEST_METHOD]: method,
    [ATTR_USER_AGENT_ORIGINAL]: headers['user-agent'] || '',
    [ATTR_URL_PATH]: target,
    [ATTR_URL_FULL]: `${headers.host}${url}`,
    [ATTR_NETWORK_PROTOCOL_VERSION]: httpVersion,
  },
});

Інструментування оглядача

Вебінтерфейс, який надає фронтенд, також інструментується для вебоглядачів. Інструментування OpenTelemetry включено як частина компонента застосунку Next.js у файлі pages/_app.tsx. Тут інструментування імпортується та ініціалізується.

import FrontendTracer from '../utils/telemetry/FrontendTracer';

if (typeof window !== 'undefined') FrontendTracer();

Файл utils/telemetry/FrontendTracer.ts містить код для ініціалізації TracerProvider, встановлення експорту OTLP, реєстрації поширювачів контексту трасування, та реєстрації бібліотек автоінструментування, специфічних для вебу. Оскільки оглядач буде надсилати дані до OpenTelemetry Collector, який, ймовірно, буде на окремому домені, заголовки CORS також налаштовані відповідним чином.

Як частина змін для перенесення прапорця атрибута synthetic_request для бекенд-сервісів, функція конфігурації applyCustomAttributesOnSpan була додана до логіки користувацьких атрибутів відрізків бібліотеки instrumentation-fetch, таким чином кожен відрізок на стороні оглядача буде включати його.

import {
  CompositePropagator,
  W3CBaggagePropagator,
  W3CTraceContextPropagator,
} from '@opentelemetry/core';
import { WebTracerProvider } from '@opentelemetry/sdk-trace-web';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { getWebAutoInstrumentations } from '@opentelemetry/auto-instrumentations-web';
import { resourceFromAttributes } from '@opentelemetry/resources';
import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';

const FrontendTracer = async () => {
  const { ZoneContextManager } = await import('@opentelemetry/context-zone');

  const provider = new WebTracerProvider({
    resource: resourceFromAttributes({
      [ATTR_SERVICE_NAME]: process.env.NEXT_PUBLIC_OTEL_SERVICE_NAME,
    }),
    spanProcessors: [new SimpleSpanProcessor(new OTLPTraceExporter())],
  });

  const contextManager = new ZoneContextManager();

  provider.register({
    contextManager,
    propagator: new CompositePropagator({
      propagators: [
        new W3CBaggagePropagator(),
        new W3CTraceContextPropagator(),
      ],
    }),
  });

  registerInstrumentations({
    tracerProvider: provider,
    instrumentations: [
      getWebAutoInstrumentations({
        '@opentelemetry/instrumentation-fetch': {
          propagateTraceHeaderCorsUrls: /.*/,
          clearTimingResources: true,
          applyCustomAttributesOnSpan(span) {
            span.setAttribute('app.synthetic_request', 'false');
          },
        },
      }),
    ],
  });
};

export default FrontendTracer;

Метрики

TBD

Логи

TBD

Baggage

OpenTelemetry Baggage використовується у фронтенді для перевірки, чи є запит синтетичним (від генератора навантаження). Синтетичні запити примусять створення нового трасування. Кореневий відрізок нового трасування міститиме багато тих самих атрибутів, що й відрізок HTTP-запиту.

Щоб визначити, чи встановлено елемент Baggage, ви можете використовувати API propagation для розбору заголовка Baggage, та використовувати API baggage для отримання або встановлення записів.

const baggage = propagation.getBaggage(context.active());
if (baggage?.getEntry("synthetic_request")?.value == "true") {...}

Востаннє змінено December 26, 2024: [uk] Ukrainian documentation for OpenTelemetry (2a3c5648)