<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://doc.ruscomtech.ru/index.php?action=history&amp;feed=atom&amp;title=%D0%A0%D1%83%D1%87%D0%BD%D0%BE%D0%B5_%D0%B2%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_OpenTelemetry_%D0%B2_Java-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5</id>
	<title>Ручное внедрение OpenTelemetry в Java-приложение - История изменений</title>
	<link rel="self" type="application/atom+xml" href="https://doc.ruscomtech.ru/index.php?action=history&amp;feed=atom&amp;title=%D0%A0%D1%83%D1%87%D0%BD%D0%BE%D0%B5_%D0%B2%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_OpenTelemetry_%D0%B2_Java-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5"/>
	<link rel="alternate" type="text/html" href="https://doc.ruscomtech.ru/index.php?title=%D0%A0%D1%83%D1%87%D0%BD%D0%BE%D0%B5_%D0%B2%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_OpenTelemetry_%D0%B2_Java-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5&amp;action=history"/>
	<updated>2026-05-02T12:09:25Z</updated>
	<subtitle>История изменений этой страницы в вики</subtitle>
	<generator>MediaWiki 1.36.1</generator>
	<entry>
		<id>https://doc.ruscomtech.ru/index.php?title=%D0%A0%D1%83%D1%87%D0%BD%D0%BE%D0%B5_%D0%B2%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_OpenTelemetry_%D0%B2_Java-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5&amp;diff=5848&amp;oldid=prev</id>
		<title>IKuznetsov: Новая страница: «В этом пошаговом руководстве показано, как добавить возможность наблюдения в ваше '''Java-п...»</title>
		<link rel="alternate" type="text/html" href="https://doc.ruscomtech.ru/index.php?title=%D0%A0%D1%83%D1%87%D0%BD%D0%BE%D0%B5_%D0%B2%D0%BD%D0%B5%D0%B4%D1%80%D0%B5%D0%BD%D0%B8%D0%B5_OpenTelemetry_%D0%B2_Java-%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5&amp;diff=5848&amp;oldid=prev"/>
		<updated>2025-10-09T15:40:46Z</updated>

		<summary type="html">&lt;p&gt;Новая страница: «В этом пошаговом руководстве показано, как добавить возможность наблюдения в ваше &amp;#039;&amp;#039;&amp;#039;Java-п...»&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая страница&lt;/b&gt;&lt;/p&gt;&lt;div&gt;В этом пошаговом руководстве показано, как добавить возможность наблюдения в ваше '''Java-приложение''' с помощью библиотек ручного инструментария и инструментов, предоставляемых '''OpenTelemetry''' '''Java'''.&lt;br /&gt;
&lt;br /&gt;
== Получите данные для доступа к Ключ-АСТРОМ ==&lt;br /&gt;
&lt;br /&gt;
=== Определение базового URL API ===&lt;br /&gt;
Подробную информацию о том, как собрать базовый '''URL-адрес''' конечной точки '''OTLP''', см. в разделе [[Экспорт с помощью OTLP]] .&lt;br /&gt;
&lt;br /&gt;
'''URL-адрес''' должен заканчиваться на &amp;lt;code&amp;gt;/api/v2/otlp&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Получение токена доступа API ===&lt;br /&gt;
Токен доступа для сбора трассировок, логов и метрик можно создать в разделе [[Токен доступа|Токены доступа]] .&lt;br /&gt;
&lt;br /&gt;
Экспорт с помощью '''OTLP''' содержит более подробную информацию о формате и необходимых областях доступа.&lt;br /&gt;
&lt;br /&gt;
== Инструментируйте свое приложение ==&lt;br /&gt;
&lt;br /&gt;
=== С автоматической настройкой SDK ===&lt;br /&gt;
1. Добавьте текущие версии следующих пакетов в конфигурацию вашего пакета (например, '''Maven''', '''Gradle''').&lt;br /&gt;
&lt;br /&gt;
* [https://central.sonatype.com/artifact/io.opentelemetry/opentelemetry-sdk-extension-autoconfigure opentelemetry-sdk-extension-autoconfigure]﻿&lt;br /&gt;
* [https://central.sonatype.com/artifact/io.opentelemetry/opentelemetry-exporter-otlp opentelemetry-exporter-otlp]﻿&lt;br /&gt;
* [https://central.sonatype.com/artifact/io.opentelemetry.semconv/opentelemetry-semconv opentelemetry-semconv]﻿&lt;br /&gt;
&lt;br /&gt;
2. Настройте следующие переменные среды, чтобы задать предпочтение временности &amp;lt;code&amp;gt;delta&amp;lt;/code&amp;gt;и определить параметры экспорта, заменив &amp;lt;code&amp;gt;[URL]&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;[TOKEN]&amp;lt;/code&amp;gt; значениями для базового '''URL-адреса''' и '''токена''' '''доступа'''.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|OTEL_EXPORTER_OTLP_ENDPOINT=[URL]&lt;br /&gt;
&lt;br /&gt;
OTEL_EXPORTER_OTLP_HEADERS=&amp;quot;Authorization=Api-Token [TOKEN]&amp;quot;&lt;br /&gt;
&lt;br /&gt;
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf&lt;br /&gt;
&lt;br /&gt;
OTEL_RESOURCE_ATTRIBUTES=&amp;quot;service.name=java-quickstart,service.version=1.0.1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=delta&lt;br /&gt;
|}&lt;br /&gt;
3. Добавьте следующие операторы импорта в класс запуска, который инициирует загрузку вашего приложения.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|import io.opentelemetry.api.common.Attributes;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.OpenTelemetrySdk;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.resources.Resource;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.instrumentation.log4j.appender.v2_17.OpenTelemetryAppender;&lt;br /&gt;
|}&lt;br /&gt;
4. Добавьте метод &amp;lt;code&amp;gt;initOpenTelemetry&amp;lt;/code&amp;gt; в класс запуска и вызовите его как можно раньше при запуске приложения. Это инициализирует '''OpenTelemetry''' для бэкенда Ключ-АСТРОМ и создаст поставщиков трассировщиков и счётчиков по умолчанию.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|private static void initOpenTelemetry() {&lt;br /&gt;
&lt;br /&gt;
    OpenTelemetrySdk sdk = AutoConfiguredOpenTelemetrySdk.builder().addResourceCustomizer((resource, properties) -&amp;gt; {&lt;br /&gt;
&lt;br /&gt;
        Resource dtMetadata = Resource.empty();&lt;br /&gt;
&lt;br /&gt;
        for (String name : new String[]{&amp;quot;dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties&amp;quot;, &amp;quot;/var/lib/astromkey/enrichment/dt_metadata.properties&amp;quot;}) {&lt;br /&gt;
&lt;br /&gt;
            try {&lt;br /&gt;
&lt;br /&gt;
                Properties props = new Properties();&lt;br /&gt;
&lt;br /&gt;
                props.load(name.startsWith(&amp;quot;/var&amp;quot;) ? new FileInputStream(name) : new FileInputStream(Files.readAllLines(Paths.get(name)).get(0)));&lt;br /&gt;
&lt;br /&gt;
                dtMetadata = dtMetadata.merge(Resource.create(props.entrySet().stream()&lt;br /&gt;
&lt;br /&gt;
                        .collect(Attributes::builder, (b, e) -&amp;gt; b.put(e.getKey().toString(), e.getValue().toString()), (b1, b2) -&amp;gt; b1.putAll(b2.build()))&lt;br /&gt;
&lt;br /&gt;
                        .build())&lt;br /&gt;
&lt;br /&gt;
                );&lt;br /&gt;
&lt;br /&gt;
            } catch (IOException e) {&lt;br /&gt;
&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return resource.merge(dtMetadata);&lt;br /&gt;
&lt;br /&gt;
    }).build().getOpenTelemetrySdk();&lt;br /&gt;
&lt;br /&gt;
    OpenTelemetryAppender.install(sdk);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
''&amp;lt;u&amp;gt;Обогащение данных Ключ-АСТРОМ&amp;lt;/u&amp;gt;''&lt;br /&gt;
&lt;br /&gt;
Операции чтения файлов, анализирующие файлы &amp;lt;code&amp;gt;dt_metadata&amp;lt;/code&amp;gt; в примере кода, пытаются прочитать файлы данных ЕдиногоАгента, чтобы обогатить запрос '''OTLP''' и гарантировать, что вся соответствующая информация о топологии доступна в Ключ-АСТРОМ.&lt;br /&gt;
&lt;br /&gt;
=== Без автонастройки SDK ===&lt;br /&gt;
1. Добавьте текущие версии следующих пакетов в конфигурацию вашего пакета (например, '''Maven''', '''Gradle''').&lt;br /&gt;
&lt;br /&gt;
* [https://central.sonatype.com/artifact/io.opentelemetry/opentelemetry-api/ opentelemetry-api]﻿&lt;br /&gt;
* [https://central.sonatype.com/artifact/io.opentelemetry/opentelemetry-sdk/ opentelemetry-sdk]﻿&lt;br /&gt;
* [https://central.sonatype.com/artifact/io.opentelemetry/opentelemetry-exporter-otlp opentelemetry-exporter-otlp]﻿&lt;br /&gt;
* [https://central.sonatype.com/artifact/io.opentelemetry.semconv/opentelemetry-semconv opentelemetry-semconv]﻿&lt;br /&gt;
&lt;br /&gt;
2. Добавьте текущую версию [https://central.sonatype.com/artifact/io.opentelemetry.instrumentation/opentelemetry-log4j-appender-2.17 opentelemetry-log4j-appender-2.17]﻿ в качестве библиотеки времени выполнения в конфигурацию вашего пакета (область для '''Maven''' &amp;lt;code&amp;gt;runtime&amp;lt;/code&amp;gt;, для '''Gradle''' &amp;lt;code&amp;gt;runtimeOnly&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
3. Добавьте следующие операторы импорта в класс запуска, который инициирует загрузку вашего приложения.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|import io.opentelemetry.api.common.AttributeKey;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.api.common.Attributes;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.context.propagation.ContextPropagators;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.exporter.otlp.http.logs.OtlpHttpLogRecordExporter;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.exporter.otlp.http.metrics.OtlpHttpMetricExporter;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.OpenTelemetrySdk;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.resources.Resource;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.trace.SdkTracerProvider;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.trace.export.SpanExporter;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.trace.samplers.Sampler;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.metrics.SdkMeterProvider;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.metrics.export.PeriodicMetricReader;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.metrics.export.AggregationTemporalitySelector;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.logs.SdkLoggerProvider;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.sdk.logs.export.BatchLogRecordProcessor;&lt;br /&gt;
&lt;br /&gt;
import io.opentelemetry.instrumentation.log4j.appender.v2_17.OpenTelemetryAppender;&lt;br /&gt;
|}&lt;br /&gt;
4. При приеме данных с использованием '''OTLP''' добавьте в класс запуска два поля для '''URL-адреса''' Ключ-АСТРОМ и '''токена доступа'''.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|private static final String DT_API_URL = &amp;quot;&amp;quot;; // TODO: Provide your SaaS/Managed URL here&lt;br /&gt;
&lt;br /&gt;
private static final String DT_API_TOKEN = &amp;quot;&amp;quot;; // TODO: Provide the OpenTelemetry-scoped access token here&lt;br /&gt;
|}&lt;br /&gt;
5. Настройте имя службы с помощью переменной среды &amp;lt;code&amp;gt;OTEL_SERVICE_NAME&amp;lt;/code&amp;gt;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|OTEL_SERVICE_NAME=java-quickstart&lt;br /&gt;
|}&lt;br /&gt;
6. Добавьте метод &amp;lt;code&amp;gt;initOpenTelemetry&amp;lt;/code&amp;gt; в класс инициализатора и вызовите его как можно раньше при запуске приложения. Это инициализирует '''OpenTelemetry''' для бэкенда Ключ-АСТРОМ и создаст поставщиков трассировщиков и счётчиков по умолчанию.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|private static void initOpenTelemetry()&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // ===== GENERAL SETUP =====&lt;br /&gt;
&lt;br /&gt;
    // Read service name from the environment variable OTEL_SERVICE_NAME, if present&lt;br /&gt;
&lt;br /&gt;
    Resource serviceName = Optional.ofNullable(System.getenv(&amp;quot;OTEL_SERVICE_NAME&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
        .map(n -&amp;gt; Attributes.of(AttributeKey.stringKey(&amp;quot;service.name&amp;quot;), n))&lt;br /&gt;
&lt;br /&gt;
        .map(Resource::create)&lt;br /&gt;
&lt;br /&gt;
        .orElseGet(Resource::empty);&lt;br /&gt;
&lt;br /&gt;
    // Parse the environment variable OTEL_RESOURCE_ATTRIBUTES into key-value pairs&lt;br /&gt;
&lt;br /&gt;
    Resource envResourceAttributes = Resource.create(Stream.of(Optional.ofNullable(System.getenv(&amp;quot;OTEL_RESOURCE_ATTRIBUTES&amp;quot;)).orElse(&amp;quot;&amp;quot;).split(&amp;quot;,&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
        .filter(pair -&amp;gt; pair != null &amp;amp;&amp;amp; pair.length() &amp;gt; 0 &amp;amp;&amp;amp; pair.contains(&amp;quot;=&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
        .map(pair -&amp;gt; pair.split(&amp;quot;=&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
        .filter(pair -&amp;gt; pair.length == 2)&lt;br /&gt;
&lt;br /&gt;
        .collect(Attributes::builder, (b, p) -&amp;gt; b.put(p[0], p[1]), (b1, b2) -&amp;gt; b1.putAll(b2.build()))&lt;br /&gt;
&lt;br /&gt;
        .build()&lt;br /&gt;
&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
// Define enrichment files&lt;br /&gt;
&lt;br /&gt;
String[] files = new String[] {&lt;br /&gt;
&lt;br /&gt;
&amp;quot;dt_metadata_e617c525669e072eebe3d0f08212e8f2.properties&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;/var/lib/astromkey/enrichment/dt_metadata.properties&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
&amp;quot;/var/lib/astromkey/enrichment/dt_host_metadata.properties&amp;quot;&lt;br /&gt;
&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
    // Read host information from OneAgent files to enrich telemetry&lt;br /&gt;
&lt;br /&gt;
    Resource dtMetadata = Resource.empty();&lt;br /&gt;
&lt;br /&gt;
    for (String name : files) {&lt;br /&gt;
&lt;br /&gt;
        try {&lt;br /&gt;
&lt;br /&gt;
            Properties props = new Properties();&lt;br /&gt;
&lt;br /&gt;
            props.load(name.startsWith(&amp;quot;/var&amp;quot;) ? new FileInputStream(name) : new FileInputStream(Files.readAllLines(Paths.get(name)).get(0)));&lt;br /&gt;
&lt;br /&gt;
            dtMetadata = dtMetadata.merge(Resource.create(&lt;br /&gt;
&lt;br /&gt;
                props.entrySet().stream()&lt;br /&gt;
&lt;br /&gt;
                    .collect(Attributes::builder, (b, e) -&amp;gt; b.put(e.getKey().toString(), e.getValue().toString()), (b1, b2) -&amp;gt; b1.putAll(b2.build()))&lt;br /&gt;
&lt;br /&gt;
                    .build()&lt;br /&gt;
&lt;br /&gt;
            ));&lt;br /&gt;
&lt;br /&gt;
        } catch (IOException e) {}&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ===== TRACING SETUP =====&lt;br /&gt;
&lt;br /&gt;
    // Configure span exporter with the astromkey URL and the API token&lt;br /&gt;
&lt;br /&gt;
    SpanExporter exporter = OtlpHttpSpanExporter.builder()&lt;br /&gt;
&lt;br /&gt;
        .setEndpoint(DT_API_URL + &amp;quot;/v1/traces&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        .addHeader(&amp;quot;Authorization&amp;quot;, &amp;quot;Api-Token &amp;quot; + DT_API_TOKEN)&lt;br /&gt;
&lt;br /&gt;
        .build();&lt;br /&gt;
&lt;br /&gt;
    // Set up tracer provider with a batch processor and the span exporter&lt;br /&gt;
&lt;br /&gt;
    SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()&lt;br /&gt;
&lt;br /&gt;
        .setResource(Resource.getDefault().merge(envResourceAttributes).merge(serviceName).merge(dtMetadata))&lt;br /&gt;
&lt;br /&gt;
        .setSampler(Sampler.alwaysOn())&lt;br /&gt;
&lt;br /&gt;
        .addSpanProcessor(BatchSpanProcessor.builder(exporter).build())&lt;br /&gt;
&lt;br /&gt;
        .build();&lt;br /&gt;
&lt;br /&gt;
    // ===== METRIC SETUP =====&lt;br /&gt;
&lt;br /&gt;
    // Configure metric exporter with the astromkey URL and the API token&lt;br /&gt;
&lt;br /&gt;
    OtlpHttpMetricExporter metricExporter = OtlpHttpMetricExporter.builder()&lt;br /&gt;
&lt;br /&gt;
        .setEndpoint(DT_API_URL + &amp;quot;/v1/metrics&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        .addHeader(&amp;quot;Authorization&amp;quot;, &amp;quot;Api-Token &amp;quot; + DT_API_TOKEN)&lt;br /&gt;
&lt;br /&gt;
        .setAggregationTemporalitySelector(AggregationTemporalitySelector.deltaPreferred())&lt;br /&gt;
&lt;br /&gt;
        .build();&lt;br /&gt;
&lt;br /&gt;
    // Set up meter provider with a periodic reader and the metric exporter&lt;br /&gt;
&lt;br /&gt;
    SdkMeterProvider meterProvider = SdkMeterProvider.builder()&lt;br /&gt;
&lt;br /&gt;
        .setResource(Resource.getDefault().merge(envResourceAttributes).merge(serviceName).merge(dtMetadata))&lt;br /&gt;
&lt;br /&gt;
        .registerMetricReader(PeriodicMetricReader.builder(metricExporter).build())&lt;br /&gt;
&lt;br /&gt;
        .build();&lt;br /&gt;
&lt;br /&gt;
    // ===== LOG SETUP =====&lt;br /&gt;
&lt;br /&gt;
    // Configure log exporter with the astromkey URL and the API token&lt;br /&gt;
&lt;br /&gt;
    OtlpHttpLogRecordExporter logExporter = OtlpHttpLogRecordExporter.builder()&lt;br /&gt;
&lt;br /&gt;
        .setEndpoint(DT_API_URL + &amp;quot;/v1/logs&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        .addHeader(&amp;quot;Authorization&amp;quot;, &amp;quot;Api-Token &amp;quot; + DT_API_TOKEN)&lt;br /&gt;
&lt;br /&gt;
        .build();&lt;br /&gt;
&lt;br /&gt;
    // Set up log provider with the log exporter&lt;br /&gt;
&lt;br /&gt;
    SdkLoggerProvider sdkLoggerProvider = SdkLoggerProvider.builder()&lt;br /&gt;
&lt;br /&gt;
        .setResource(Resource.getDefault().merge(envResourceAttributes).merge(serviceName).merge(dtMetadata))&lt;br /&gt;
&lt;br /&gt;
        .addLogRecordProcessor(BatchLogRecordProcessor.builder(logExporter).build())&lt;br /&gt;
&lt;br /&gt;
        .build();&lt;br /&gt;
&lt;br /&gt;
    // ===== INITIALIZATION =====&lt;br /&gt;
&lt;br /&gt;
    // Initialize OpenTelemetry with the tracer and meter providers&lt;br /&gt;
&lt;br /&gt;
    OpenTelemetrySdk sdk = OpenTelemetrySdk.builder()&lt;br /&gt;
&lt;br /&gt;
        .setTracerProvider(sdkTracerProvider)&lt;br /&gt;
&lt;br /&gt;
        .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))&lt;br /&gt;
&lt;br /&gt;
        .setMeterProvider(meterProvider)&lt;br /&gt;
&lt;br /&gt;
        .setLoggerProvider(sdkLoggerProvider)&lt;br /&gt;
&lt;br /&gt;
        .buildAndRegisterGlobal();&lt;br /&gt;
&lt;br /&gt;
    //&lt;br /&gt;
&lt;br /&gt;
    Runtime.getRuntime().addShutdownHook(new Thread(sdkTracerProvider::close));&lt;br /&gt;
&lt;br /&gt;
    OpenTelemetryAppender.install(sdk);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
''&amp;lt;u&amp;gt;Обогащение данных Ключ-АСТРОМ&amp;lt;/u&amp;gt;''&lt;br /&gt;
&lt;br /&gt;
Операции чтения файлов, анализирующие файлы &amp;lt;code&amp;gt;dt_metadata&amp;lt;/code&amp;gt; в примере кода, пытаются прочитать файлы данных ЕдиногоАгента, чтобы обогатить запрос '''OTLP''' и гарантировать, что вся соответствующая информация о топологии доступна в Ключ-АСТРОМ.&lt;br /&gt;
&lt;br /&gt;
== Добаление телеметрических сигналов вручную (необязательно) ==&lt;br /&gt;
&lt;br /&gt;
=== Создание интервалов ===&lt;br /&gt;
1. Для создания новых интервалов нам сначала нужен объект трассировки.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|Tracer tracer = GlobalOpenTelemetry&lt;br /&gt;
&lt;br /&gt;
    .getTracerProvider()&lt;br /&gt;
&lt;br /&gt;
    .tracerBuilder(&amp;quot;my-tracer&amp;quot;) //TODO Replace with the name of your tracer&lt;br /&gt;
&lt;br /&gt;
    .build();&lt;br /&gt;
|}&lt;br /&gt;
2. Теперь с помощью &amp;lt;code&amp;gt;tracer&amp;lt;/code&amp;gt;, мы можем использовать конструктор интервалов для создания и запуска новых интервалов.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|// Obtain and name new span from tracer&lt;br /&gt;
&lt;br /&gt;
Span span = tracer.spanBuilder(&amp;quot;Call to /myendpoint&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    .setSpanKind(SpanKind.CLIENT)&lt;br /&gt;
&lt;br /&gt;
    .startSpan();&lt;br /&gt;
&lt;br /&gt;
// Set demo span attributes using semantic naming&lt;br /&gt;
&lt;br /&gt;
span.setAttribute(&amp;quot;http.method&amp;quot;, &amp;quot;GET&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
span.setAttribute(&amp;quot;net.protocol.version&amp;quot;, &amp;quot;1.1&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
// Set the span as current span and parent for future child spans&lt;br /&gt;
&lt;br /&gt;
try (Scope scope = span.makeCurrent())&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // TODO your code goes here&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
finally&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
    // Completing the span&lt;br /&gt;
&lt;br /&gt;
    span.end();&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
В приведенном выше коде мы:&lt;br /&gt;
&lt;br /&gt;
* Создали новый диапазон и назвали его «'''Call to /myendpoint'''».&lt;br /&gt;
* Добавили два атрибута, следуя [https://opentelemetry.io/docs/specs/semconv/general/trace/ семантическому соглашению об именовании]﻿, специфичные для действия этого диапазона: информацию о методе '''HTTP''' и версии.&lt;br /&gt;
* Использовали метод '''span''' &amp;lt;code&amp;gt;makeCurrent()&amp;lt;/code&amp;gt;, чтобы отметить его как активный '''span''' и родительский для будущих '''span''' (пока '''span''' не завершится)&lt;br /&gt;
* Вызвали метод '''span''' &amp;lt;code&amp;gt;end()&amp;lt;/code&amp;gt; для завершения '''span''' (в блоке &amp;lt;code&amp;gt;finally&amp;lt;/code&amp;gt;, чтобы гарантировать вызов метода)&lt;br /&gt;
&lt;br /&gt;
=== Сборка метрик ===&lt;br /&gt;
1. Для создания новых инструментов измерения нам сначала нужен объект счетчика.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|Meter meter = GlobalOpenTelemetry&lt;br /&gt;
&lt;br /&gt;
    .getMeterProvider()&lt;br /&gt;
&lt;br /&gt;
    .meterBuilder(&amp;quot;my-meter&amp;quot;) //TODO Replace with the name of your meter&lt;br /&gt;
&lt;br /&gt;
    .build();&lt;br /&gt;
|}&lt;br /&gt;
2. С помощью &amp;lt;code&amp;gt;meter&amp;lt;/code&amp;gt; мы теперь можем создавать отдельные инструменты, например, счетчик.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|LongCounter counter = meter.counterBuilder(&amp;quot;request_counter&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    .setDescription(&amp;quot;The number of requests we received&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    .setUnit()&lt;br /&gt;
&lt;br /&gt;
    .build();&lt;br /&gt;
|}&lt;br /&gt;
3. Теперь мы можем вызвать метод &amp;lt;code&amp;gt;add()&amp;lt;/code&amp;gt; для записи новых значений &amp;lt;code&amp;gt;counter&amp;lt;/code&amp;gt; с помощью нашего счетчика и сохранения дополнительных атрибутов (например, &amp;lt;code&amp;gt;action.type&amp;lt;/code&amp;gt;).&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|Attributes attrs = Attributes.of(stringKey(&amp;quot;action.type&amp;quot;), &amp;quot;create&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
counter.add(1, attrs);&lt;br /&gt;
|}&lt;br /&gt;
Вы также можете создать асинхронный датчик, для которого потребуется функция обратного вызова, которая будет вызываться '''OpenTelemetry''' при сборе данных.&lt;br /&gt;
&lt;br /&gt;
В следующем примере при каждом вызове записывается доступная память, а также атрибут количества активных пользователей, полученный из вымышленного метода &amp;lt;code&amp;gt;getUserCount()&amp;lt;/code&amp;gt;.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|meter.gaugeBuilder(&amp;quot;free_memory&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    .setDescription(&amp;quot;Available memory in bytes&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    .setUnit(&amp;quot;bytes&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    .buildWithCallback(measurement -&amp;gt; {&lt;br /&gt;
&lt;br /&gt;
        measurement.record(&lt;br /&gt;
&lt;br /&gt;
            Runtime.getRuntime().freeMemory(),&lt;br /&gt;
&lt;br /&gt;
            Attributes.of(stringKey(&amp;quot;user_count&amp;quot;), getUserCount())&lt;br /&gt;
&lt;br /&gt;
        );&lt;br /&gt;
&lt;br /&gt;
    });&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Подключение логов ===&lt;br /&gt;
Сначала вам необходимо настроить файл конфигурации '''Log4j 2''' &amp;lt;code&amp;gt;log4j.xml&amp;lt;/code&amp;gt;, чтобы включить в него приложение '''OpenTelemetry'''.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Configuration status=&amp;quot;WARN&amp;quot; packages=&amp;quot;io.opentelemetry.instrumentation.log4j.appender.v2_17&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;Appenders&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;Console name=&amp;quot;Console&amp;quot; target=&amp;quot;SYSTEM_OUT&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
      &amp;lt;PatternLayout&lt;br /&gt;
&lt;br /&gt;
          pattern=&amp;quot;%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} trace_id: %X{trace_id} span_id: %X{span_id} trace_flags: %X{trace_flags} - %msg%n&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/Console&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;OpenTelemetry name=&amp;quot;OpenTelemetryAppender&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/Appenders&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;Loggers&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;Root&amp;gt;&lt;br /&gt;
&lt;br /&gt;
      &amp;lt;AppenderRef ref=&amp;quot;OpenTelemetryAppender&amp;quot; level=&amp;quot;All&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
      &amp;lt;AppenderRef ref=&amp;quot;Console&amp;quot; level=&amp;quot;All&amp;quot;/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;/Root&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/Loggers&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/Configuration&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
В этой конфигурации мы добавили новую запись &amp;lt;code&amp;gt;&amp;lt;OpenTelemetry&amp;gt;&amp;lt;/code&amp;gt; в раздел &amp;lt;code&amp;gt;&amp;lt;Appenders&amp;gt;&amp;lt;/code&amp;gt;, а также запись &amp;lt;code&amp;gt;&amp;lt;AppenderRef&amp;gt;&amp;lt;/code&amp;gt; в раздел &amp;lt;code&amp;gt;&amp;lt;Loggers&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
С помощью вызова &amp;lt;code&amp;gt;GlobalLoggerProvider&amp;lt;/code&amp;gt;, который мы ранее выполнили в разделе '''Настройка''', этот аппендер настраивается для бэкэнда Ключ-АСТРОМ.&lt;br /&gt;
&lt;br /&gt;
== Обеспечение распространения контекста ==&lt;br /&gt;
Распространение контекста особенно важно, когда задействованы сетевые вызовы (например, '''REST''').&lt;br /&gt;
&lt;br /&gt;
Если вы используете автоматическое инструментирование и ваши сетевые библиотеки также им охватываются, то это будет автоматически реализовано библиотеками инструментирования. В противном случае ваш код должен это учитывать.&lt;br /&gt;
&lt;br /&gt;
=== Извлечение контекста при получении запроса ===&lt;br /&gt;
В следующем примере мы предполагаем, что получили сетевой вызов через &amp;lt;code&amp;gt;com.sun.net.httpserver.HttpExchange&amp;lt;/code&amp;gt; и определяем экземпляр &amp;lt;code&amp;gt;TextMapGetter&amp;lt;/code&amp;gt; для извлечения контекстной информации из '''HTTP-заголовков'''. Затем мы передаем этот экземпляр в &amp;lt;code&amp;gt;extract()&amp;lt;/code&amp;gt;, возвращая объект контекста, что позволяет нам продолжить предыдущую трассировку с нашими интервалами.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|//The getter will be used for incoming requests&lt;br /&gt;
&lt;br /&gt;
TextMapGetter&amp;lt;HttpExchange&amp;gt; getter =&lt;br /&gt;
&lt;br /&gt;
    new TextMapGetter&amp;lt;&amp;gt;() {&lt;br /&gt;
&lt;br /&gt;
        @Override&lt;br /&gt;
&lt;br /&gt;
        public String get(HttpExchange carrier, String key) {&lt;br /&gt;
&lt;br /&gt;
            if (carrier.getRequestHeaders().containsKey(key)) {&lt;br /&gt;
&lt;br /&gt;
                return carrier.getRequestHeaders().get(key).get(0);&lt;br /&gt;
&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            return null;&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        @Override&lt;br /&gt;
&lt;br /&gt;
        public Iterable&amp;lt;String&amp;gt; keys(HttpExchange carrier) {&lt;br /&gt;
&lt;br /&gt;
            return carrier.getRequestHeaders().keySet();&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
@Override&lt;br /&gt;
&lt;br /&gt;
public void handle(HttpExchange httpExchange) {&lt;br /&gt;
&lt;br /&gt;
    //Extract the SpanContext and other elements from the request&lt;br /&gt;
&lt;br /&gt;
    Context extractedContext = GlobalOpenTelemetry.getPropagators().getTextMapPropagator()&lt;br /&gt;
&lt;br /&gt;
        .extract(Context.current(), httpExchange, getter);&lt;br /&gt;
&lt;br /&gt;
    try (Scope scope = extractedContext.makeCurrent()) {&lt;br /&gt;
&lt;br /&gt;
        //This will automatically propagate context by creating child spans within the extracted context&lt;br /&gt;
&lt;br /&gt;
        Span serverSpan = tracer.spanBuilder(&amp;quot;my-server-span&amp;quot;) //TODO Replace with the name of your span&lt;br /&gt;
&lt;br /&gt;
            .setSpanKind(SpanKind.SERVER) //TODO Set the kind of your span&lt;br /&gt;
&lt;br /&gt;
            .startSpan();&lt;br /&gt;
&lt;br /&gt;
        serverSpan.setAttribute(SemanticAttributes.HTTP_METHOD, &amp;quot;GET&amp;quot;); //TODO Add attributes&lt;br /&gt;
&lt;br /&gt;
        serverSpan.end();&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Внедрение контекста при отправке запросов ===&lt;br /&gt;
В следующем примере мы отправляем '''REST'''-запрос к другой службе и предоставляем наш существующий контекст как часть '''HTTP-заголовков''' нашего запроса.&lt;br /&gt;
&lt;br /&gt;
Для этого мы определяем экземпляр &amp;lt;code&amp;gt;TextMapSetter&amp;lt;/code&amp;gt;, который добавляет соответствующую информацию с помощью &amp;lt;code&amp;gt;setRequestProperty()&amp;lt;/code&amp;gt;. После создания экземпляра '''REST-объекта''' мы передаем его вместе с контекстом и экземпляром сеттера в &amp;lt;code&amp;gt;inject()&amp;lt;/code&amp;gt;, который добавит необходимые заголовки к запросу.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|//The setter will be used for outgoing requests&lt;br /&gt;
&lt;br /&gt;
TextMapSetter&amp;lt;HttpURLConnection&amp;gt; setter =&lt;br /&gt;
&lt;br /&gt;
    (carrier, key, value) -&amp;gt; {&lt;br /&gt;
&lt;br /&gt;
        assert carrier != null;&lt;br /&gt;
&lt;br /&gt;
        // Insert the context as Header&lt;br /&gt;
&lt;br /&gt;
        carrier.setRequestProperty(key, value);&lt;br /&gt;
&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
URL url = new URL(&amp;quot;&amp;lt;URL&amp;gt;&amp;quot;); //TODO Replace with the URL of the service to be called&lt;br /&gt;
&lt;br /&gt;
Span outGoing = tracer.spanBuilder(&amp;quot;my-client-span&amp;quot;) //TODO Replace with the name of your span&lt;br /&gt;
&lt;br /&gt;
    .setSpanKind(SpanKind.CLIENT) //TODO Set the kind of your span&lt;br /&gt;
&lt;br /&gt;
    .startSpan();&lt;br /&gt;
&lt;br /&gt;
try (Scope scope = outGoing.makeCurrent()) {&lt;br /&gt;
&lt;br /&gt;
    outGoing.setAttribute(SemanticAttributes.HTTP_METHOD, &amp;quot;GET&amp;quot;); //TODO Add attributes&lt;br /&gt;
&lt;br /&gt;
    HttpURLConnection transportLayer = (HttpURLConnection) url.openConnection();&lt;br /&gt;
&lt;br /&gt;
    // Inject the request with the *current*  Context, which contains our current span&lt;br /&gt;
&lt;br /&gt;
    GlobalOpenTelemetry.getPropagators().getTextMapPropagator().inject(Context.current(), transportLayer, setter);&lt;br /&gt;
&lt;br /&gt;
    // Make outgoing call&lt;br /&gt;
&lt;br /&gt;
} finally {&lt;br /&gt;
&lt;br /&gt;
    outGoing.end();&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Настройка сбора данных в соответствии с требованиями конфиденциальности (необязательно) ==&lt;br /&gt;
Хотя Ключ-АСТРОМ автоматически собирает все атрибуты '''OpenTelemetry''', в веб-интерфейсе Ключ-АСТРОМ сохраняются и отображаются только значения атрибутов, указанные в списке разрешенных. Это предотвращает случайное сохранение персональных данных, позволяя вам соблюдать требования к конфиденциальности и контролировать объем хранимых данных мониторинга.&lt;br /&gt;
&lt;br /&gt;
Чтобы просматривать пользовательские атрибуты, необходимо сначала разрешить их использование в веб-интерфейсе Ключ-АСТРОМ.&lt;br /&gt;
&lt;br /&gt;
== Проверка загрузки данных в Ключ-АСТРОМ ==&lt;br /&gt;
После завершения инструментирования вашего приложения выполните несколько тестовых действий для создания и отправки демонстрационных трассировок, метрик и логов, а также проверьте, что они были правильно загружены в Ключ-АСТРОМ.&lt;br /&gt;
&lt;br /&gt;
Чтобы сделать это для трассировок, перейдите в раздел '''Трассировки''' и выберите вкладку '''Распределенные трассировки'''. Если вы используете ЕдиныйАгент, выберите '''PurePaths''' .&lt;br /&gt;
&lt;br /&gt;
Для просмотра метрик и логов перейдите в раздел '''Метрики''' или '''Журналы''' или '''Журналы и события'''.&lt;/div&gt;</summary>
		<author><name>IKuznetsov</name></author>
	</entry>
</feed>