Как соединить OpenTelemetry (opentelemetry-java-instrumentation) и Micrometer

Моя установка:

  1. Приложение Spring Boot на основе версии 3.1.3
  2. Добавлена ​​зависимость spring-boot-starter-actuator
  3. Добавлен специальный показатель MyHealthMetricsExportConfiguration согласно документации (показан ниже).
  4. Под /actuator/metrics я вижу health метрику
  5. Я скачал последнюю версию Java-агента Otel с GitHub
  6. Я добавил конфигурацию в intellij «параметры vm»:

-javaagent:./opentelemetry-javaagent.jar
-Dotel.metrics.exporter=otlp

  1. Я запустил сборщик отелей с receiver, установленным на otlp

Вопрос

Я не знаю, как заставить агента отеля «видеть» и экспортировать показатели Spring, такие как f.e. «MyHealthMetricsExportConfiguration». В этом блоге это должно быть так просто:

  // Unregister the OpenTelemetryMeterRegistry from Metrics.globalRegistry and make it available
  // as a Spring bean instead.
  @Bean
  @ConditionalOnClass(name = "io.opentelemetry.javaagent.OpenTelemetryAgent")
  public MeterRegistry otelRegistry() {
    Optional<MeterRegistry> otelRegistry = Metrics.globalRegistry.getRegistries().stream()
        .filter(r -> r.getClass().getName().contains("OpenTelemetryMeterRegistry"))
        .findAny();
    otelRegistry.ifPresent(Metrics.globalRegistry::remove);
    return otelRegistry.orElse(null);
  }

Но это не работает для меня. Прежде всего, создание durig bean Metrics.globalRegistry.getRegistries() пусто. Во-вторых, в коллекторе отелей нет метрики health. Что я могу сделать, чтобы этот агент отправил мою специальную метрику сборщику?


@Configuration(proxyBeanMethods = false)
public class MyHealthMetricsExportConfiguration {

    public MyHealthMetricsExportConfiguration(MeterRegistry registry, HealthEndpoint healthEndpoint) {
        // This example presumes common tags (such as the app) are applied elsewhere
        Gauge.builder("health", healthEndpoint, this::getStatusCode).strongReference(true).register(registry);
    }

    private int getStatusCode(HealthEndpoint health) {
        Status status = health.health().getStatus();
        if (Status.UP.equals(status)) {
            return 3;
        }
        if (Status.OUT_OF_SERVICE.equals(status)) {
            return 2;
        }
        if (Status.DOWN.equals(status)) {
            return 1;
        }
        return 0;
    }

}

Я не знаю, почему это не работает, поскольку отсутствует информация о вашей инициализации (автоконфигурация, руководство, envvars, версия агента...), но в качестве подсказки: вы прошли opentelemetry.io/docs/languages/java /инструменты ? Если нет, то должно сработать, по крайней мере у меня так было 2 дня назад. Еще одно место, где можно задать вопрос, — это #otel-java в cncf Slack.

Dominik 06.05.2024 22:42

Если вы напишете ответ здесь, с ф.э. кусок кода, который подойдет вам, тогда я могу дать вам награду.

user3529850 07.05.2024 20:16
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
2
1 194
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Судя по вашему описанию, вы смешиваете 2 подхода.

  1. используя opentelemetry-spring-boot-starter, что означает, что агент optl содержится в вашей банке Spring-Boot.
  2. используя -javaagent:, который будет инструментировать ваше приложение с весенней загрузкой во время выполнения

это условие @ConditionalOnClass(name = "io.opentelemetry.javaagent.OpenTelemetryAgent") вернет false для второго варианта (поставьте точку останова или журнал отладки, и вы увидите, что ваше приложение не создает otelRegistry bean-компонент).

Если вы решите использовать javaagent + prometheus (включите io.micrometer:micrometer-registry-prometheus в свои зависимости), вы можете отказаться от OpenTelemetryMeterRegistry (условный компонент) Metrics.globalRegistry.getRegistries() чтобы вернуться PrometheusMeterRegistry

Если вы предпочитаете формат optl, перейдите по ссылке выше.

Ответ принят как подходящий

Вам необходимо включить мост OpenTelemetry для Micrometer. Он отключен по умолчанию, начиная с версии 2.0.0 агента OpenTelemetry: https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/tag/v2.0.0

Использование агента

Для использования агента (ваш случай) добавьте это системное свойство в параметры виртуальной машины: -Dotel.instrumentation.micrometer.enabled=true.

И я бы рекомендовал сначала настроить консольный экспортер (-Dotel.metrics.exporter=console), чтобы проверять именно в консоли, что экспортируется, независимо от того, что происходит на принимающей стороне (на сборщике).

P.S. Вам не нужен фрагмент кода из упомянутого вами сообщения в блоге (public MeterRegistry otelRegistry() {...). Возможно, это полезно для чего-то, но ему уже 2 года, а OpenTelemetry все еще находится в альфа-версии и имеет множество критических изменений. Так что на сегодняшний день у меня все работает без него. Примечание: OpenTelemetryMeterRegistry, о котором они там упоминают, взят из библиотеки моста OpenTelemetry (она автоматически включается как в агент, так и в Spring Starter).

Использование OpenTelemetry Spring Starter

Для тех, кто использует пружинный стартер opentelemetry (io.opentelemetry.instrumentation:opentelemetry-spring-boot-starter) вместо агента, в него уже включен микрометрический мост, поэтому включите его, установив то же системное свойство (например, в application.properties добавьте строку otel.instrumentation.micrometer.enabled=true).


Попробовал оба варианта с последней версией (2.3.0), всё заработало (Spring Boot 3.2.5). Используя ваш класс, я получил следующий журнал показателей (среди многих других) в выводе консоли (см. ...name=health...value=3.0...):

[otel.javaagent 2024-05-11 00:11:00:926 +0400] [PeriodicMetricReader-1] INFO io.opentelemetry.exporter.logging.LoggingMetricExporter - metric: ImmutableMetricData{resource=Resource{schemaUrl=https://opentelemetry.io/schemas/1.24.0, attributes = {host.arch = "amd64", host.name = "DESKTOP-NCP", os.description = "Windows 10 10.0", os.type = "windows", process.command_line = "C:\Program Files\Eclipse Adoptium\jdk-17.0.10.7-hotspot\bin\java.exe -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:13011,suspend=y,server=n -javaagent:./opentelemetry-javaagent.jar -Dotel.instrumentation.micrometer.enabled=true -Dotel.metrics.exporter=console -XX:TieredStopAtLevel=1 -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:C:\Users\Artem\AppData\Local\JetBrains\IntelliJIdea2024.1\captureAgent\debugger-agent.jar -Dfile.encoding=UTF-8 com.backend.BackendApplication", process.executable.path = "C:\Program Files\Eclipse Adoptium\jdk-17.0.10.7-hotspot\bin\java.exe", process.pid=44220, process.runtime.description = "Eclipse Adoptium OpenJDK 64-Bit Server VM 17.0.10+7", process.runtime.name = "OpenJDK Runtime Environment", process.runtime.version = "17.0.10+7", service.instance.id = "3c1b88b9-bdf6-457f-9e46-abb511930f80", service.name = "backend", telemetry.distro.name = "opentelemetry-java-instrumentation", telemetry.distro.version = "2.3.0", telemetry.sdk.language = "java", telemetry.sdk.name = "opentelemetry", telemetry.sdk.version = "1.37.0"}}, instrumentationScopeInfo=InstrumentationScopeInfo{name=io.opentelemetry.micrometer-1.5, version=null, schemaUrl=null, attributes = {}}, name=health, description=, unit=, type=DOUBLE_GAUGE, data=ImmutableGaugeData{points=[ImmutableDoublePointData{startEpochNanos=1715371800406007400, epochNanos=1715371860420845000, attributes = {}, value=3.0, exemplars=[]}]}}

Отдельно мост Микрометр доступен на этой странице (найдите его в таблице): https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/supported-libraries.md#libraries --фреймворки


Будьте осторожны: включение моста Micrometer также начнет экспортировать метрики Spring по умолчанию, а некоторые из них имеют те же имена, что и инструменты OpenTelemetry. Поскольку у них разные атрибуты, сборщик, похоже, рассматривает их как одну и ту же метрику с разными атрибутами. Так, например, в Grafana вы увидите одну метрику jvm_memory_used, но некоторые измерения будут дублироваться (пример G1 Eden Space дублирования):

...
comes from "io.opentelemetry.micrometer-1.5" bridge:
jvm_memory_used{area = "heap", id = "G1 Eden Space", instance = "07d3f12f-c3a5-43bf-a268-bb80bceb6c56", job = "stolpy-backend"}
...
comes from "io.opentelemetry.runtime-telemetry-java8":
jvm_memory_used{instance = "07d3f12f-c3a5-43bf-a268-bb80bceb6c56", job = "stolpy-backend", jvm_memory_pool_name = "G1 Eden Space", jvm_memory_type = "heap"}

Итак, вы, вероятно, захотите отключить метрики Spring Micrometer по умолчанию, где-то в документации должно быть объяснено, как это сделать. Например, в этом сообщении SO упоминается что-то: Метрики привода/микрометра Spring Boot отключают некоторые

Откуда вы это узнали? Должен ли я отлаживать низкоуровневые вещи после рабочего времени, чтобы стать лучше, проходить через вопросы/ответы SO, чтобы быть знакомым с такими проблемами? Проголосуйте против меня столько, сколько хотите, но я впечатлен и буду признателен за совет, что делать, чтобы быть похожим на вас.

user3529850 11.05.2024 13:29

@user3529850 user3529850 По иронии судьбы, вчера я наткнулся на ваш вопрос, когда пытался найти ответ на свой собственный вопрос об OpenTelemetry (не на SO), и заметил, что на этот вопрос я могу ответить :) Я сам все еще изучаю OpenTelemetry. Мне пришлось много экспериментировать (проверка вывода отладки часто является хорошей идеей), прочитать много их документации, блогов, кода Github, примечаний к выпуску и т. д., чтобы понять, что происходит. К сожалению, информация пока очень скудная, я согласен, надеюсь, что после альфа-версии она улучшится. Случайно в результате своих экспериментов я узнал ответ на ваш вопрос.

Artem Novikov 11.05.2024 14:34

Другие вопросы по теме