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

Інструментування для OpenTelemetry Swift

Інструментування — це процес додавання коду спостереження до вашого застосунку.

Якщо ви інструментуєте застосунок, вам потрібно використовувати OpenTelemetry SDK для вашої мови програмування. Потім ви будете використовувати SDK для ініціалізації OpenTelemetry та API для інструментування вашого коду. Це буде генерувати телеметрію з вашого застосунку та будь-якої бібліотеки, яку ви встановили, що також містить інструментування.

Якщо ви інструментуєте бібліотеку, встановіть лише пакет OpenTelemetry API для вашої мови програмування. Ваша бібліотека не буде генерувати телеметрію самостійно. Вона буде генерувати телеметрію лише тоді, коли буде частиною застосунку, що використовує OpenTelemetry SDK. Для отримання додаткової інформації про інструментування бібліотек дивіться Бібліотеки.

Для отримання додаткової інформації про OpenTelemetry API та SDK дивіться специфікацію.

Налаштування

OpenTelemetry Swift надає обмежену функціональність у своїй стандартній конфігурації. Для більш корисної функціональності потрібні деякі налаштування.

Стандартний зареєстрований TracerProvider та MetricProvider не налаштовані з експортером. Існує кілька експортерів доступних залежно від ваших потреб. Нижче ми розглянемо налаштування OTLP експортера, який можна використовувати для надсилання даних до колектора.

import GRPC
import OpenTelemetryApi
import OpenTelemetrySdk
import OpenTelemetryProtocolExporter

// ініціалізація OtlpTraceExporter
let otlpConfiguration = OtlpConfiguration(timeout: OtlpConfiguration.DefaultTimeoutInterval)

let grpcChannel = ClientConnection.usingPlatformAppropriateTLS(for: MultiThreadedEventLoopGroup(numberOfThreads:1))
                                                  .connect(host: <collector host>, port: <collector port>)

let traceExporter = OtlpTraceExporter(channel: grpcChannel,
                                      config: otlpConfiguration)

// створення та реєстрація Tracer Provider з використанням створеного otlp trace exporter
OpenTelemetry.registerTracerProvider(tracerProvider: TracerProviderBuilder()
                                                      .add(spanProcessor:SimpleSpanProcessor(spanExporter: traceExporter))
                                                      .with(resource: Resource())
                                                      .build())

Схожий шаблон використовується для OtlpMetricExporter:

// otlpConfiguration та grpcChannel можна використовувати повторно
OpenTelemetry.registerMeterProvider(meterProvider: MeterProviderBuilder()
            .with(processor: MetricProcessorSdk())
            .with(exporter: OtlpMetricExporter(channel: channel, config: otlpConfiguration))
            .with(resource: Resource())
            .build())

Після налаштування MeterProvider та TracerProvider всі наступні ініціалізовані інструменти будуть експортувати дані за допомогою цього OTLP експортера.

Трейси

Отримання Tracer

Для виконання трасування вам потрібен трасувальник. Трасувальник отримується через провайдера трасувальників і відповідає за створення відрізків. OpenTelemetry керує провайдером трасувальників, як ми визначили та зареєстрували вище. Для створення трасувальника потрібна назва інструменту та необовʼязкова версія:

let  tracer = OpenTelemetry.instance.tracerProvider.get(instrumentationName: "instrumentation-library-name", instrumentationVersion: "1.0.0")

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

Відрізок представляє одиницю роботи або операцію. Відрізки є будівельними блоками Трейсів. Для створення відрізка використовуйте будівельник відрізків, повʼязаний з трасувальником:

let span = tracer.spanBuilder(spanName: "\(name)").startSpan()
...
span.end()

Необхідно викликати end(), щоб завершити відрізок.

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

Відрізки використовуються для побудови відносин між операціями. Нижче наведено приклад як ми можемо вручну побудувати відносини між відрізками.

Нижче у нас є parent(), що викликає child(), і як вручну повʼязати відрізки кожного з цих методів.

func parent() {
  let parentSpan = someTracer.spanBuilder(spanName: "parent span").startSpan()
  child(span: parentSpan)
  parentSpan.end()
}

func child(parentSpan: Span) {
let childSpan = someTracer.spanBuilder(spanName: "child span")
                             .setParent(parentSpan)
                             .startSpan()
  // виконання роботи
  childSpan.end()
}

Відносини пращур-нащадок будуть автоматично повʼязані, якщо використовується activeSpan:

func parent() {
  let parentSpan = someTracer.spanBuilder(spanName: "parent span")
                      .setActive(true) // автоматично встановлює контекст
                      .startSpan()
  child()
  parentSpan.end()
}

func child() {
  let childSpan = someTracer.spanBuilder(spanName: "child span")
                             .startSpan() // автоматично захоплює `active span` як батько
  // виконання роботи
  childSpan.end()
}

Отримання поточного відрізка

Іноді корисно зробити щось з поточним/активним відрізком. Ось як отримати доступ до поточного відрізка з будь-якої точки вашого коду.

let currentSpan = OpenTelemetry.instance.contextProvider.activeSpan

Атрибути відрізків

Відрізки також можуть бути анотовані додатковими атрибутами. Всі відрізки будуть автоматично анотовані атрибутами Resource, прикріпленими до провайдера трасувальників. SDK Opentelemetry-swift вже надає інструментування загальних атрибутів у інструментуванні SDKResourceExtension. У цьому прикладі відрізок для мережевого запиту захоплює деталі про цей запит, використовуючи наявні семантичні домовленості.

let span = tracer.spanBuilder("/resource/path").startSpan()
span.setAttribute("http.method", "GET");
span.setAttribute("http.url", url.toString());

Створення подій відрізка

Подія Відрізка може бути розглянута як структуроване повідомлення логу (або анотація) на відрізку, зазвичай використовується для позначення значущої, одиничної точки в часі під час тривалості відрізка.

let attributes = [
    "key" : AttributeValue.string("value"),
    "result" : AttributeValue.int(100)
]
span.addEvent(name: "computation complete", attributes: attributes)

Встановлення статусу відрізка

Статус можна встановити на Відрізок, зазвичай використовується для вказівки, що Відрізок не завершився успішно — Error. Стандартно, всі відрізки мають статус Unset, що означає, що відрізок завершився без помилок. Статус Ok зарезервований для випадків, коли потрібно явно позначити відрізок як успішний, а не залишати його зі статусом Unset (тобто “без помилок”).

Статус можна встановити в будь-який час до завершення відрізка.

func myFunction() {
  let span = someTracer.spanBuilder(spanName: "my span").startSpan()
  defer {
    span.end()
  }
  guard let criticalData = get() else {
      span.status = .error(description: "щось пішло не так")
      return
  }
  // виконання чогось
}

Запис помилок у відрізки

Семантичні конвенції надають спеціальне позначення для подій, що записують помилки:

let span = someTracer.spanBuilder(spanName: "my span").startSpan()
do {
  try throwingFunction()
} catch {
  span.addEvent(name: SemanticAttributes.exception.rawValue,
    attributes: [SemanticAttributes.exceptionType.rawValue: AttributeValue.string(String(describing: type(of: error))),
                 SemanticAttributes.exceptionEscaped.rawValue: AttributeValue.bool(false),
                 SemanticAttributes.exceptionMessage.rawValue: AttributeValue.string(error.localizedDescription)])
  })
  span.status = .error(description: error.localizedDescription)
}
span.end()

Метрики

Документація для API та SDK метрик відсутня, ви можете допомогти зробити її доступною, редагуючи цю сторінку.

Логи

API та SDK логів наразі розробляються.

Конфігурація SDK

Процесори

OpenTelemetry-swift пропонує різні процесори Відрізків. SimpleSpanProcessor негайно пересилає завершені відрізки до експортера, тоді як BatchSpanProcessor групує їх і відправляє гуртом. Можна налаштувати кілька процесорів відрізків, щоб вони були активні одночасно, використовуючи MultiSpanProcessor. Наприклад, ви можете створити SimpleSpanProcessor, який експортує до логера, та BatchSpanProcessor, який експортує до OpenTelemetry Collector:

let otlpConfiguration = OtlpConfiguration(timeout: OtlpConfiguration.DefaultTimeoutInterval)

let grpcChannel = ClientConnection.usingPlatformAppropriateTLS(for: MultiThreadedEventLoopGroup(numberOfThreads:1))
                                                  .connect(host: <collector host>, port: <collector port>)

let traceExporter = OtlpTraceExporter(channel: grpcChannel
                                      config: otlpConfiguration)

// створення та реєстрація Tracer Provider з використанням створеного otlp trace exporter
OpenTelemetry.registerTracerProvider(tracerProvider: TracerProviderBuilder()
                                                      .add(spanProcessor:BatchSpanProcessor(spanExporter: traceExporter))
                                                      .add(spanProcessor:SimpleSpanProcessor(spanExporter: StdoutExporter))
                                                      .with(resource: Resource())
                                                      .build())

Процесор групових відрізків дозволяє налаштовувати різні параметри.

Експортери

OpenTelemetry-Swift надає наступні експортери:

  • InMemoryExporter: Зберігає дані відрізків у памʼяті. Це корисно для тестування та налагодження.
  • DatadogExporter: Конвертує дані відрізків OpenTelemetry у трасування Datadog та події відрізків у логи Datadog.
  • JaegerExporter: Конвертує дані відрізків OpenTelemetry у формат Jaeger та експортує до точки доступу Jaeger.
  • Persistence exporter: Декоратор експортера, який надає збереження даних для наявних експортерів метрик та відрізків.
  • PrometheusExporter: Конвертує дані метрик у формат Prometheus та експортує до точки доступу Prometheus.
  • StdoutExporter: Експортує дані відрізків до Stdout. Корисно для налагодження.
  • ZipkinTraceExporter: Експортує дані відрізків у формат Zipkin до точки доступу Zipkin.

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