summaryrefslogtreecommitdiffstats
path: root/library/cpp/monlib/encode/prometheus/prometheus_decoder_ut.cpp
diff options
context:
space:
mode:
authorivantsvetkov <[email protected]>2026-07-07 15:53:29 +0300
committerivantsvetkov <[email protected]>2026-07-07 16:37:15 +0300
commit17735a730250296d50b59dec1519c693c685a541 (patch)
tree406065a9177496dc5831cc30b9472d0a4b67c4c5 /library/cpp/monlib/encode/prometheus/prometheus_decoder_ut.cpp
parent86de72e6933d47749a9283bfa20c54c0fb4bcb6f (diff)
label size extension
**Было:** Prometheus decoder ограничивает длину значений меток метрик максимум 256 символами. Попытка передать метрику с более длинным значением метки приводит к исключению `TPrometheusDecodeException`. **Стало:** Максимальная длина значения метки расширена до 1024 символов. Системы, которые генерируют метрики с более длинными значениями (например, с ID источников данных, URL, или сложных идентификаторов), теперь могут успешно передавать такие метрики в Unified Agent без ошибок. **Практический эффект:** Улучшение совместимости с внешними системами мониторинга и приложениями, которые требуют передачи длинных меток. Существующие системы с метками < 256 символов продолжают работать без изменений. --- ## С точки зрения разработчика ### Структурные изменения Расширение требовало изменения способа хранения длины строки в пуле коротких строк: 1. **Prometheus decoder** (library/cpp/monlib): - `MAX_LABEL_VALUE_LEN`: 256 → 1024 2. **Short string pool** (logbroker/unified_agent/common): - `MaxLabelSize`: 255 → 1024 - **Ключевое изменение:** Размер строки теперь хранится как `ui16` (2 байта) вместо `unsigned char` (1 байт) - Было: `*slot->Payload() = static_cast<unsigned char>(s.size())` - Стало: `memcpy(slot->Payload(), &size, sizeof(ui16))` - Это позволяет хранить строки до 65535 символов (но логически ограничено на уровне валидации) ### Изменённые файлы | Файл | Основные изменения | |------|------------------| | `prometheus_decoder.cpp` | `MAX_LABEL_VALUE_LEN: 256 → 1024` | | `prometheus_decoder_ut.cpp` | +2 юнит-теста для новых граничных значений | | `short_string_pool.h` | `MaxLabelSize: 255 → 1024`, operator[] использует ui16 для чтения размера | | `short_string_pool.cpp` | Allocation и copy логика адаптирована для ui16 | ### Тестирование Добавлены два новых юнит-теста: - **LabelValueAtNewLimitIsAccepted:** Метрика с меткой ровно 1023 символа успешно парсится ``` "m{l=\"" + string(1023, 'a') + "\"} 1\n" ``` - **LabelValueOverNewLimitStillThrows:** Метрика с меткой ≥1024 символов выбрасывает исключение ``` "m{l=\"" + string(1024, 'a') + "\"} 1\n" // → TPrometheusDecodeException: "trying to parse too long label value, size >= 1024" ``` ### Безопасность и совместимость - ✅ Обратно совместимо: строки < 256 символов работают так же - ✅ Валидация: лимит 1024 проверяется на уровне Ref() в пуле - ✅ Граничные случаи: добавлены тесты для 1023 и 1024 символов - ✅ Выделение памяти: правильно рассчитано с учётом новых 2 байт для размера - ✅ Я не нашел ситуации когда закодированная строка (длина + строка) улетала куда-то из пула и потом пыталась раскодироваться. Так что считаю, что миграции никакой не надо и все обратно совместимо. НАДЕЮСЬ Я НЕ ОШИБАЮСЬ commit_hash:b30852954951bd8e65d69777a59ffeb58da76b47
Diffstat (limited to 'library/cpp/monlib/encode/prometheus/prometheus_decoder_ut.cpp')
-rw-r--r--library/cpp/monlib/encode/prometheus/prometheus_decoder_ut.cpp24
1 files changed, 24 insertions, 0 deletions
diff --git a/library/cpp/monlib/encode/prometheus/prometheus_decoder_ut.cpp b/library/cpp/monlib/encode/prometheus/prometheus_decoder_ut.cpp
index f6b3eb01667..834c3295741 100644
--- a/library/cpp/monlib/encode/prometheus/prometheus_decoder_ut.cpp
+++ b/library/cpp/monlib/encode/prometheus/prometheus_decoder_ut.cpp
@@ -105,6 +105,30 @@ Y_UNIT_TEST_SUITE(TPrometheusDecoderTest) {
}
}
+ // ReadTokenAsLabelValue's loop runs MAX_LABEL_VALUE_LEN times: one iteration per
+ // appended character plus one final iteration to detect the closing quote. So the
+ // longest value it can successfully parse is (MAX_LABEL_VALUE_LEN - 1) characters.
+ Y_UNIT_TEST(LabelValueAtNewLimitIsAccepted) {
+ const auto value = TString(1023, 'a');
+ const auto inputMetrics = TString("m{l=\"") + value + "\"} 1\n";
+
+ auto samples = Decode(inputMetrics);
+
+ UNIT_ASSERT_VALUES_EQUAL(samples.SamplesSize(), 1);
+ auto& s = samples.GetSamples(0);
+ UNIT_ASSERT_VALUES_EQUAL(s.LabelsSize(), 2);
+ ASSERT_LABEL_EQUAL(s.GetLabels(0), "sensor", "m");
+ ASSERT_LABEL_EQUAL(s.GetLabels(1), "l", value);
+ }
+
+ Y_UNIT_TEST(LabelValueOverNewLimitStillThrows) {
+ const auto value = TString(1024, 'a');
+ const auto inputMetrics = TString("m{l=\"") + value + "\"} 1\n";
+
+ UNIT_ASSERT_EXCEPTION_CONTAINS(Decode(inputMetrics), TPrometheusDecodeException,
+ "trying to parse too long label value, size >= 1024");
+ }
+
Y_UNIT_TEST(NameAlreadyPresent) {
constexpr auto inputMetrics =
"# A normal comment.\n"