Верстакфорум практиков
рекламаiprazon: приватные серверные адреса IPv4 и SOCKS5, безлимитный трафик, бесплатный тест до 2 часов
ФорумРазбор ошибок

Логи ничего не говорят: как поднять подробность

mila_ops
mila_ops
Новичок
сообщений 175
с апр, второй сезон
8 октября, 11:57первое сообщение

Прогон падает примерно раз в сорок минут, и всё, что у меня есть в файле, вот такое:

14:22:07 ERROR ошибка при обращении, пропускаю
14:58:31 ERROR ошибка при обращении, пропускаю
15:31:02 ERROR ошибка при обращении, пропускаю

Писала это я сама, полгода назад, и теперь кусаю локти. Ни адреса, ни кода, ни текста исключения. Хочу поднять подробность так, чтобы по логу можно было разобрать случай без повтора прогона. С чего начать?

ferrum
ferrum
Участник
сообщений 660
с сен
15 марта, 14:14#2

Начните с трёх уровней подробности, они разные по цене и включаются в разных ситуациях.

Уровень первый, постоянный. Одна строка на каждое обращение, всегда, даже на успешных. В строке обязаны быть: метка времени с миллисекундами, порядковый номер обращения, адрес, код ответа, размер тела, время целиком, номер попытки. Семь полей, строка короткая, места ест немного, а разобрать по ней можно почти всё.

Уровень второй, на отказах. При любом исходе, кроме успеха, дописываете тип исключения и его текст целиком, вместе со следом вызовов. Ловить голое Exception и печатать своё слово это худшее, что можно сделать с отладкой, у вас именно это и вышло.

import logging, traceback

log = logging.getLogger("obhod")

try: otvet = sessiya.get(adres, timeout=20) log.info("%s %s код=%s байт=%s время=%.3f попытка=%s", nomer, adres, otvet.status_code, len(otvet.content), otvet.elapsed.total_seconds(), popytka) except Exception as e: log.error("%s %s сорвалось: %s: %s\n%s", nomer, adres, type(e).__name__, e, traceback.format_exc()) ```

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

import http.client
http.client.HTTPConnection.debuglevel = 1
logging.getLogger("urllib3").setLevel(logging.DEBUG)

Для проверки руками тот же третий уровень даёт curl -v, а если нужен совсем сырой поток, curl --trace-ascii /tmp/obmen.txt. Там видно каждый байт в обе стороны.

Данила Р
Данила Р
Новичок
сообщений 145
с мар, второй сезон
22 августа, 17:31#3

а третий уровень можно включать только на упавших адресах?

parser_ru
parser_ru
Ветеран
сообщений 3140
с фев
1 января, 08:48#4

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

Второй приём в ту же копилку: заведите каждому обращению сквозной номер и таскайте его во все строки лога, включая строки повторов и строки разбора. Тогда падение собирается по номеру одной командой grep, без чтения всего файла глазами.

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

mila_ops
mila_ops
Новичок
сообщений 175
с апр, второй сезон
8 июня, 11:05#5
ferrum: ловить голое Exception и печатать своё слово это худшее, что можно сделать

Прямо про меня, каюсь. Переписала логирование за вечер, отчитываюсь.

Поставила семь полей на каждое обращение, сквозной номер, отдельный файл под отказы и кольцо на сто последних обменов. Прогон упал через сорок с небольшим минут, как обычно, и в этот раз я увидела всё сразу: ConnectionResetError на одном и том же хосте, третья попытка подряд, тело нулевое, время 20 секунд ровно, то есть упёрлось в мой же таймаут.

Дальше уже понятно, куда идти. Что помогло больше всего: сквозной номер обращения. Раньше я не могла связать строку повтора с исходным обращением и путалась в порядке событий.