Описание проблемы
Плагин Instance (mamonsu/plugins/pgsql/instance.py) мутирует атрибут класса self.Items на каждом цикле run(), из-за чего количество столбцов в SELECT-запросе постоянно растёт, пока не упирается в лимит PostgreSQL MaxTupleAttributeNumber (1664 столбца) и не начинает падать с ошибкой:
[ERROR] plugin instance caught error: target lists can have at most 1664 entries
После этого ошибка логируется на каждом цикле сбора (~60 сек), при этом Python-процесс непрерывно течёт по памяти.
Причина
В instance.py, метод run():
def run(self, zbx):
all_items = self.Items # ← ссылка на список класса, НЕ копия
if Pooler.server_version_greater("12.0"):
all_items += self.Items_pg_12 # ← эквивалент self.Items.extend(self.Items_pg_12)
if Pooler.server_version_greater("18.0"):
all_items += self.Items_pg_18 # ← то же самое: мутирует self.Items на месте
all_items = self.Items привязывает all_items к тому же объекту, что и атрибут класса. Оператор += для списка — это list.__iadd__, эквивалент .extend(): он мутирует список на месте и возвращает тот же объект. Поэтому на каждом вызове run():
self.Items вырастает на len(self.Items_pg_12) элементов (и на len(self.Items_pg_18) при PG ≥ 18).
- Генерируемый SQL
SELECT получает больше столбцов с каждым циклом.
- Через ~80–90 минут на PG ≥ 12 (в зависимости от размера Items_pg_12) количество столбцов превышает 1664 и PostgreSQL отклоняет запрос.
Та же ошибка присутствует в методе keys_and_queries() в том же файле:
def keys_and_queries(self, template_zabbix):
all_items = self.Items # ← та же ошибка со ссылкой
if Pooler.server_version_greater("12.0"):
all_items += self.Items_pg_12
if Pooler.server_version_greater("18.0"):
all_items += self.Items_pg_18
Аналогичная проблема в issue #187
В issue #187 была описана идентичная проблема в плагине Statements — sum(wal_bytes), sum(wal_records), sum(wal_fpi) добавлялись в запрос на каждом цикле. Исправлено в v3.5.2 (коммит 3d0e0ce, changelog: "fixed Statements plugin list of metrics creation") заменой на:
all_items = self.Items.copy() # ← создаёт новый список каждый раз
Источник бага
Баг внесён при рефакторинге для поддержки PostgreSQL 18. До этого коммита в instance.py использовалась безопасная конкатенация:
all_items = self.Items + self.Items_pg_12 # создаёт НОВЫЙ список
Коммит, заменивший её на мутирующий паттерн:
- Коммит:
c1a761b5bb (2025-11-17, "feat: add columns support for PostgreSQL 18")
- Diff:
- all_items = self.Items + self.Items_pg_12
+ all_items = self.Items
+ if Pooler.server_version_greater("12.0"):
+ all_items += self.Items_pg_12
+ if Pooler.server_version_greater("18.0"):
+ all_items += self.Items_pg_18
Предлагаемый фикс
Применить тот же фикс, что был сделан для Statements в 3.5.2 — использовать .copy():
--- a/mamonsu/plugins/pgsql/instance.py
+++ b/mamonsu/plugins/pgsql/instance.py
@@ in method run():
- all_items = self.Items
+ all_items = self.Items.copy()
if Pooler.server_version_greater("12.0"):
all_items += self.Items_pg_12
if Pooler.server_version_greater("18.0"):
all_items += self.Items_pg_18
@@ in method keys_and_queries():
- all_items = self.Items
+ all_items = self.Items.copy()
if Pooler.server_version_greater("12.0"):
all_items += self.Items_pg_12
if Pooler.server_version_greater("18.0"):
all_items += self.Items_pg_18
Окружение
- mamonsu 3.5.16-1.noble
- PostgreSQL 16
- Ubuntu 24.04 (noble)
Описание проблемы
Плагин
Instance(mamonsu/plugins/pgsql/instance.py) мутирует атрибут классаself.Itemsна каждом циклеrun(), из-за чего количество столбцов в SELECT-запросе постоянно растёт, пока не упирается в лимит PostgreSQLMaxTupleAttributeNumber(1664 столбца) и не начинает падать с ошибкой:После этого ошибка логируется на каждом цикле сбора (~60 сек), при этом Python-процесс непрерывно течёт по памяти.
Причина
В
instance.py, методrun():all_items = self.Itemsпривязываетall_itemsк тому же объекту, что и атрибут класса. Оператор+=для списка — этоlist.__iadd__, эквивалент.extend(): он мутирует список на месте и возвращает тот же объект. Поэтому на каждом вызовеrun():self.Itemsвырастает наlen(self.Items_pg_12)элементов (и наlen(self.Items_pg_18)при PG ≥ 18).SELECTполучает больше столбцов с каждым циклом.Та же ошибка присутствует в методе
keys_and_queries()в том же файле:Аналогичная проблема в issue #187
В issue #187 была описана идентичная проблема в плагине Statements —
sum(wal_bytes), sum(wal_records), sum(wal_fpi)добавлялись в запрос на каждом цикле. Исправлено в v3.5.2 (коммит 3d0e0ce, changelog: "fixed Statements plugin list of metrics creation") заменой на:Источник бага
Баг внесён при рефакторинге для поддержки PostgreSQL 18. До этого коммита в
instance.pyиспользовалась безопасная конкатенация:Коммит, заменивший её на мутирующий паттерн:
c1a761b5bb(2025-11-17, "feat: add columns support for PostgreSQL 18")Предлагаемый фикс
Применить тот же фикс, что был сделан для Statements в 3.5.2 — использовать
.copy():Окружение