track-time-first-attempt

GlobalХаб задаёт сам

Запоминать ли время первой попытки доставки
в конфигурации это строкаtrack-time-first-attempt falseвнутри блока Global
Задержка между приёмом и первым действием

Строка заставляет MTA запоминать, когда он впервые попытался доставить письмо. Попыткой считается любой исход: доставка, отказ, временная ошибка получателя или очереди. Умолчание — false.

🔴 Это не запись события, а включение подсчёта. Пока строка выключена, величины не существует: её не восстановить ни из учёта, ни из журнала. Всё, что можно сделать задним числом, — включить и ждать новых писем.

Открывается сразу двумя способами. Значение появляется в записях учёта видов d, b и t — то есть его надо ещё перечислить в record-fields (при наборе * попадает само). И оно же становится метрикой pmta_smtp_first_attempt_seconds, если настроен <prometheus-listener>.

Что эта величина означает на самом деле. Не время доставки, а задержку между приёмом письма и первым действием с ним. Это прямая мера того, успевает ли узел разгребать очередь: растёт она — значит письма ждут, и растёт она раньше, чем портится доставляемость.

Цена названа вендором: заметное влияние на обращения к диску, особенно когда много попыток кончается временными ошибками. То есть дороже всего она стоит ровно в тот момент, когда полезнее всего.

Главная ловушка — включить и не перечислить поле. При явном списке в record-fields значение никуда не попадёт, и строка будет только тратить обращения к диску. При наборе * поле попадает само.
Что делает Хаб. Пишет true — в корне обоих шаблонов, с 30.08.2026: без строки время письма было бы одной величиной, с ней оно распадается на ожидание в очереди, саму доставку и повторы.

К полям доставок и отказов Хаб явно добавляет timeFirstAttempt, totalSecondsQueued и numRetries — в звёздочку они не входят. По ним телеметрия считает время доставки без очереди, а «Статистика учёта» — куда уходит время внутри доставки. Цена — обращения к диску, и она выше как раз на проблемном узле: руководство называет рост дисковых операций при большом числе временных отказов.

Рекомендуемые значения

Решение простое, но с ценой:

Значение Когда
false (умолчание) всегда, пока величина не нужна
true нужна задержка приёма-отправки в учёте или в метриках

Рядом две строки, работающие только при включённой этой: time-first-attempt-hires-timestamp — миллисекунды в записи учёта, и time-first-attempt-domains-file — разбивка метрики по приёмникам.

Умолчание false, перечень видов записей, где появляется значение, и предупреждение о влиянии на диск при частых временных ошибках — из руководства (§ 3.3.1.41, § 11.22). Толкование величины как меры разгребания очереди — наше.
Пример в конфигурации
# величина появится в учёте и в метрике — но только с этого момента
track-time-first-attempt truetime-first-attempt-hires-timestamp true

<prometheus-listener 0/0:9090>
</prometheus-listener>
Вторая строка без первой не работает. Блок нужен только для метрики: в учёт значение попадёт и без него.
жёлтым — — имена директив, голубым — блоки. Так же они подсвечены и в тексте карточки.
▲

Типичные ошибки и проблемы

что делают не так и чем это кончается2 ошибки▶

Включают задним числом, чтобы посмотреть прошлое

наш опыт

Чем чреватоВеличина не хранилась нигде и не вычисляется из имеющегося. Данные появятся только для писем, принятых после правки.
Как заметитьПосле включения поле заполнено у новых записей и пусто у старых.
Как правильноВключать заранее — вместе с остальным набором учёта, а не когда понадобилось.

Включают на узле, который и так упирается в диск

§ 11.22

Чем чреватоВендор называет влияние на обращения к диску, особенно при частых временных ошибках. На перегруженном узле строка добавит нагрузку именно тогда, когда он и без того в беде.
Как заметитьПосле включения выросло время ожидания диска на узле с большой долей 4xx.
Как правильноВключать на здоровом узле заранее, а не на проблемном во время разбора.
Совместимость
PowerMTA 6.0
описана в руководстве этой версии · платформа: любая
С какой версии директива доступна, вендор указывает не для всех — здесь пометки нет. Имя встречается и в издании руководства 5.0.
Справочные данные
Синтаксис
track-time-first-attempt <boolean>
Значения
yes | no | true | false
Умолчание
false § 3.3.1.41
Применение
reload, перезапуск не нужен
Очередь
уже поставленное в очередь не затронет
Где писать
Global
Сколько раз
один раз в блоке
Всё здесь — из руководства, с разделом.
Наследование
Наследования нет: строка пишется в корне файла, раздел Global, и действует на все письма узла. Выборочно — по приёмнику или потоку — подсчёт не включается; разбить по приёмникам можно только метрику, и только через time-first-attempt-domains-file.
Как проверить на узле
Проверять надо в учёте — по наличию значения в поле:
head -1 "$(ls -t /var/log/pmta/acct-*.csv | head -1)" | tr ',' '\n' | grep -i first
Колонка появится только при включённой строке и попадании поля в набор. В формате JSON то же смотрят по любой записи. Метрику — запросом к порту слушателя Prometheus.
В Хабе
Значение
Хаб подбирает сам — темп, стадия прогрева, метрики
Цена ошибки
безопасно: неверное значение ничего не ломает
Сценарии
Разобраться с доставляемостью · Собрать телеметрию