Как правильно настроить описание динамических показателей в микрометре?

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

Микрометр имеет классы Builder для каждого типа метрики следующего вида:

<MetricType>.builder(<metricName>).description(<description>).tags(<tagsArray>).register(<meterRegistry>)

В качестве примера возьмем показатели счетчика. Его можно увеличить следующим образом:

<meterRegistry>.Counter(<counterName>, <Pairs of labels and their values>).increment()

Проблема возникает, когда вы хотите задать описание. Если значения меток являются динамическими по своей природе, то есть значения определяются во время выполнения или если возможная комбинация меток слишком много, например 10+, то как вы должны установить описание?

Единственное решение, которое я мог придумать, - это где-нибудь сохранить описание при запуске метрической службы. Затем создайте оболочку вокруг метода приращения. Теперь, когда пользователь вызывает оболочку, вызовите метод регистрации (с сохраненным описанием), а затем метод приращения. И, как правило, метод register создает новую метрику, если она не существует, в противном случае возвращает существующую метрику.

Эту же проблему можно легко решить в Prometheus, поскольку у них есть метод регистрации, который позволяет вам устанавливать все метки (т.е. только ключи) и описание. Тогда метод приращения требует только значений этих меток.

Обеспечивает ли микрометр аналогичную функциональность? Создание оболочки для простого приложения кажется крайне неудобным. И учитывая, что микрометр уже является оболочкой для Prometheus (и других инструментальных сервисов), я также не хочу создавать оболочку вокруг него.

Если вопрос не имеет смысла, может помочь следующий пример:

Рассмотрим метрику счетчика requests с меткой type, значение которой может быть alpha, beta, gamma с описанием tracks requests from clients

Затем в качестве решения я могу добавить следующую строку в функцию регистрации, вызываемую при запуске метрической службы.

Counter.builder("requests")
    .description("tracks requests from clients)
    .tags("type", "alpha")
    .register(meterRegistry);

И затем, где бы я ни хотел использовать эту метрику, я могу запустить следующий код:

meterRegistry.Counter("request", "type", <valueOfType>).increment()

Меня беспокоит то, что в этом решении я инициирую только тип alpha, который кажется неправильным, поскольку это единственный тип. Другой вариант - зарегистрировать все 3 типа, однако при этом предполагается, что все возможные значения известны во время выполнения. Если значения обнаруживаются во время выполнения, это решение полностью не работает, и теперь вам придется использовать решение с оболочками, как описано выше, или полностью забыть описание.


person kernel0707    schedule 31.07.2020    source источник


Ответы (2)


Я столкнулся с аналогичной проблемой, когда пытался работать со счетчиками и несколькими значениями для одного тега.

Вот мое решение:

@RestController
public class HelloController {

    private final Counter.Builder counter;
    private MeterRegistry registry;

    public HelloController(MeterRegistry registry) {
        this.counter = Counter.builder("counter").description("A description");
        this.registry = registry;
    }

    @GetMapping("/count")
    public String count1() {
        counter.tag("tag2", "value1").register(registry).increment();
// I don't provide more description here, but I need to use .register('registry') at each call.
        return "Count";
    }

    @GetMapping("/count2")
    public String count2() {
        counter.tag("tag2", "value2").register(registry).increment();
        return "Count";
    }

}
  • Примечание. Мне нужно вызвать counter...register(registry), чтобы иметь одно описание и несколько значений для тегов.
person RUARO Thibault    schedule 31.07.2020
comment
Это хорошее решение, но все же кажется немного беспорядочным. Я действительно хотел бы, чтобы у Micrometer была функция, аналогичная той, что в Prometheus. - person kernel0707; 02.08.2020

У меня была такая же проблема, поэтому я нашел этот полезный пост, но ... мне это решение не понравилось.

Я думаю, что лучший подход - использовать заполнитель, например this. Так что, возможно, определите HierarchicalNameMapper, который заменит заполнитель тега, когда ключи тега совпадают, это хороший выбор.

Итак, теперь проблема динамических счетчиков тегов вроде бы решена, но описание все еще остается проблемой. Так что я тоже не использовал это решение.

Мое последнее решение заключалось в том, чтобы хранить Counters Gauges и другие счетчики на картах и ​​извлекать их по идентификаторам (имя и теги). Описание было предоставлено во время измерений, когда я просматриваю карту, и если метрика с этим идентификатором уже существует, будет увеличиваться (или уменьшаться), в противном случае будет создано описание, основанное на значимом имени метрики и ключах-значениях тегов.

    /**
     * Increment the {@link Counter}  with input tags. If it does not exists it will be created.
     */
    public void increment(String description, String unit, Tags tags) throws MetricsException {
            this.counter(description, unit, tags).increment();
    }

    /**
     * Search for a counter with input tags. If it does not exists it will be created.
     */
    private Counter counter(String description, String unit, Tags tags) {
        final String counterId = name.concat(tags.toString());

        Counter counter = counters.get(counterId);
        if (counter == null) {

            counter = Counter.builder(name)
                    .description(description)
                    .baseUnit(unit)
                    .tags(tags)
                    .register(registry);

            counters.put(counterId, counter);
        }

        return counter;
    }

Где:
registry - это MeterRegistry значение поля
counters - это Map<String, Counter>

Если у вас возникли проблемы с использованием памяти, я использовал инструментальный агент Java для проверки карты. Этот один. Запись карты имеет размер 1 КБ, поэтому у вас должно быть 1000 комбинаций имен тегов, чтобы использовать 1 МБ :)

Это решение подошло мне лучше всего. Сообщите мне, помогло ли это вам :)

person Marco Dalla Santa    schedule 06.10.2020