Они перешли на новый уровень, когда им интересны принципиально новые варианты развития.
Вот что такое «тёмная материя»? Может, это как раз сверхцивилизации, которые скрываются от молодняка типа нас?
Сорри за офтоп ,просто не могу вспомнить за последние 15 лет ни одной жалобы , даже от ремонтников бытовой техники.=)
Неухоженные квартиры, обычно с алкоголиками, из которых усатые мигранты терроризируют весь дом; шурин с таким несколько лет жил рядом, пока сосед не ушёл в Валгаллу.
Обои, клеенные советским клейстером на крахмале — основной источник для живности в малых масштабах, но достаточных, чтобы их регулярно гонять, и чтобы они заводились там, откуда их фиг вытравишь (технологические внутренности типичной посудомойки).
В бедных районах такого ещё навалом.
Если сообщения часто повторяются, эти повторы легко сожмутся любым ближайшим gzip или более мощным аналогом.
Если нет — ну да, можно оставить только кода, поставить локальный расшифровщик и напускать его на полученные файлы. Но совсем без комментария можем прийти к стилю логов OS/360, когда наткнувшись на очередное «IEA0123A X=14 M=0 T=111» надо было лезть в подручную книжку читать, что это за зверь и почему. Но там поток событий был, мягко говоря, поменьше.
fatal, error, warning, info — это только называется уровнем логирования. На самом деле — это категории серьезности лог сообщений.
Я хотел сказать, что не вижу принципиальной разницы — это одно и то же, но названное по-разному. Но дальше Вы пытаетесь показать какие-то проблемы от смешения этих понятий. Тогда давайте дальше разберёмся, в чём же тут реальная проблема.
Например, давайте в работающей системе поставим fatal уровень логгирования ? Все сразу — низзя.
Как минимум — warning.
В «работающей системе» типа «этот проект только-только вышел из беты, и ошибок ещё триста вагонов» — да, обычно выше warning ставить нельзя.
Но представьте себе софтину, которая идеально вылизана поколениями разработчиков под давно устоявшиеся требования. Да, знаю, что в стране единорогов принцессы не имеют бытовых проблем. Но представим себе такое:) И что, от неё нужен лог уровня warning? Да на самом деле там даже fatal можно не писать, ибо его не бывает. :) Тогда что же реально важно? А то, например, что error, alert, critical, fatal могут отражать какие-то пришедшие извне проблемы. А ещё, как я писал в первом же своём комментарии в этой теме,
* alert, fatal — должны, скорее всего, немедленно передаваться в систему мониторинга и создавать в ней алармы (считаем, в стране единорогов есть мониторинг);
* >=error — должны анализироваться на регулярной основе и, скорее всего, человеком; кроме того, централизоваться в отдельный источник;
* >=warning — должны анализироваться на регулярной основе, попадать под сбор статистики подобных сообщений и анализ этой статистики; возможно, не централизуются, а остаются на конкретном хосте (и в центр пойдёт только статистика, или избранные категории, а остальная масса останется на локальном роторе).
Вот вам уже и различие уровней несмотря на то, что где-то кричат «пишем всё начиная от warning». Пишем — да, но в разные выходные логи. Обычно, лог уровня warning включает в себя и все уровни повыше.
Тогда вопрос — а зачем нам разные fatal, error, warning — если ПО ЛЮБОМУ ВСЕГДА надо выводить. Чем тогда отличаются fatal, error, warning ? приходим к выводу — что не уровнем логгирования.
Вот именно, что _уровнем_. Только Вы не хотите понимать, при чём тут этот уровень и где он применяется. Возможно, для Ваших задач это и не нужно?
В общем, беда всех систем логгирования — путаница и смешивание уровней логгирования и категорий сообщений. Если человек отрывается от одномерного подхода, сразу все складывается.
Что именно в данном случае Вы называете категорией сообщения? Мне привычно понимать под этим указание на подсистему/слой источника, по которому можно отдельно задавать уровень (в syslog это зовётся facility, а в log4xxx это текстовое имя логгера). И да, это даёт уже минимум двумерный подход (а с учётом иерархии —
Если Вы имеете в виду что-то другое — уточните.
Итак, то что я называю FORCED — по категории важности равно INFO, а по уровню логгирования —
FORCED = FATAL = ERROR — все это по любому логгируется, даже если есть формальная возможность отключить
Вот и плохо, что «по любому логгируется». Это значит, что если мне нужен лог fatal’ов со всей фермы на 100500 источников, я должен отдельный фильтр на все входы напускать??
ну собственно FORCED это похоже на Ваш notice.
Если он таки forced, то он явно выше всех остальных.
В реальности приходится использовать log4j или стандартный логгер жавы. Которые, странно, но не предусмотрели ничего для логирования «интересных случаев».
Я ж говорю, они дурные кривули.
Вы логеру кстати, что передаете строку или подготовленный объект ?
Обычно — форматную строку и аргументы.
Тут вспоминается один пример про то сколько объектов типа date в java можно создать на дохленькой 1Гц машинке. Кажись было около 750К.
Мой телепатический модуль отказывается это расшифровывать.
750K объектов в 1GB RAM? Какие-то слишком толстые объекты.
750K объектов в секунду на 1ГГц машине (не 1Гц, конечно)? Ну в среднем по больнице нормальная скорость, но не там, где считают наносекунды.
На этот случай есть старый добрый приём, помогающий в значительной части случаев. Лог ведётся в кольцевом буфере в памяти (если приложение любит падать — то в соседнем процессе, а то и на соседнем хосте). Пока всё нормально, ничего не пишется, но в случае замеченной проблемы скидывается весь буфер.
Почему-то все зациклены на текстовых лог-файлах,
Потому, что тема посвящена отладочным логам, а не контрольным или целевым. Рядом я расписывал различия. Нетекстовые структуры в отладочном логе это что-то совсем специфическое.
С другой стороны, и отладочные логи можно вести так:
(общий префикс) starting transaction for incoming request 498379837 from user vasya for /goods?id=2348
а можно так:
(общий префикс) %DB-TL-TRANS-START: starting transaction for incoming request; req_id=498379837 username=vasya product_id=2348
С каким-нибудь простым квотингом (например, url-like) можно не бояться появления сбивающих с толку символов в данных и при этом пользоваться общей стратегией типа «всё, что после последнего ’;’ - параметры, названные по фиксированным ключам»; а иерархия тегов позволит лёгкий автоматизированный анализ.
Если уже есть объект logger то можно туда запихнуть фильтр,
А данные к фильтру поступают как, уже отформатированной строкой или комбинацией fmt+args? (Пока что предполагаем контекст, что весь выход — текстовый)
Если второе — ok, для большинства случаев фильтрация по уровню дёшева. Если первое — как раз я и объяснял, что тогда нужна явная проверка.
Более того, даже во втором случае создание объекта LogRecord (питоновый logging) или аналога может быть дорогой операцией. Тут рядом несколько раз уже упоминались случаи, когда GC очень дорог.
В таких местах и создавать объект на строку лога — безумно дорого...
Зато отличная статья как для хабра:) Введение в тему, которое помогает понять легко поймать пару основных принципов и идей, факт проблематики и направление для дальнейшего гугления.
При этом, как положено, ещё с котиком завлекающей картинкой.
Как отметить ее старт и стоп, которые согласно этой публикации обязательно должны быть залогированы ? Старт таски — это ж не ошибка ? не. Поэтому INFO.
Поэтому notice. Если какой-то логгер не знает такого уровня — для реальной работы он не годен.
Потом на продакшин выкатили, пару багов пофиксили, ессна, в процессе разработки навернули всякого МОДНОГО ХЛАМА, который тормозит, поэтому обвинили в тормозах логирование, и перешли на ERROR.
Даже не warning, а сразу error? Тогда того, кто такое разрешил — метлой из профессии.
Решение: обязательно FORCED левел логирования.
Расшифруйте, пожалуйста.
Если имеется в виду, что этот forced это ещё один уровень, типа выше fatal, потому что пишется всегда и во всём — то это плохо уже тем, что фильтрация некоторого выходного потока/канала по принципу «>=error», которая может работать, например, на
* зажигание красной лампочки
* SMS дежурному инженеру
* механический счётчик проблем, который пишется ежечасно в бумажный журнал
* срочное заседание СНБО
* etc.
перестанет адекватно работать только потому, что кто-то решил, что поставить такой уровень проще, чем сделать по-умному.
www.loggly.com
“No more logging into individual machines.” То есть раутинг к центру отсох — и всё, данных больше нет?
От гейзенбагов синхронизации — да, могут не спасать. Но для них вообще нужны отдельные подходы.
Всё в основе правильно, но некоторые моменты желательно уточнить.
1. В вашем сообщении отсутствует принципиальное разделение логов на целевые, контрольные и отладочные. Если кому неизвестна терминология:
* целевые — описывающие штатное функционирование, которые должны на постоянной основе анализируются программами, и это входит в ТЗ; например, для httpd это access.log, для системы доступа юзеров — лог, по которому далее формируется акаунтинг;
* контрольные — для мониторинга основных характеристик и журналирования статистики работы; должны быть пригодны к автоматизированному анализу;
* отладочные — предназначенные для нерегулярного, вызванного проблемами, анализа людьми и специализированными скриптами.
Всё сказанное в сообщении, по сути, относится к отладочным логам и частично к контрольным (и то, регуляция уровня контрольных — нечасто полезно). Описанное неприменимо к целевому логу и к большинству задач контрольного лога.
2. Набор указанных уровней недостаточен для большинства интересных случаев. Как минимум, требуется notice (выше info, но ниже warning), debug, а для тяжёлых случаев и trace.
В частности, всё описанное как
Логи должны отражать все важные события. Например: запуск приложения, старт/стоп транзакций, успешный логин, возникновение ошибок и так далее.
разделяется на: запуск, останов, реконфигурация приложения и все периодические «5 секунд, полёт нормальный» — notice (и параллельно в контрольный лог); логин, отработка запроса в целом — info; старт/стоп транзакций — debug; ошибки — warning или error.
3. Вся линия log4xxx (log4j, log4cplus, logging в Python, etc.), насколько я видел, неверно сделана в плане уровня логов. Так как уровень принципиально ограничен самым логически высоким fatal, то этот fatal должен быть в основании шкалы; а группы уровней debug и trace должны допускать подробную грануляцию. Поэтому должно быть в числовом смысле fatal самым низким, а trace самым высоким, и диапазоном (не одно значение, а не менее 10 разных). У log4xxx — наоборот, что показывает, что их авторы сделали реализацию «на отцепись». Это кажется мелочью, но становится принципиальным для регулировки плотности заполнения диска:)
У нас, например, система уровней
*
*
*
*
*
*
*
* 31-INT_MAX:) — trace
сделана намеренно с избытком, и местами таки важно разделять уровни типа 11 и 14, или 35 и 40:)
4. Во многих случаях жизненно важно обеспечить раздельную регулировку уровней по профилям активности в рамках одного приложения. Если это нельзя сделать назначением уровня на «logger», то сколь-нибудь сложная диагностика превращается в кошмар начального grep’а среди десятков гигабайт.
Например, в системе с доступом по вебу выделяются примерно такие профили
* HTTP морда (начало, конец отработки запроса)
* доступ к базе (транзакции, ошибки, количество переданных данных)
* очереди и пулы асинхронного исполнения
* фоновые процессы
5. Система логгирования чего-то хоть как-то длительно работающего должна допускать реконфигурирование на ходу, хотя бы выставлением уровней по профилям (а то и направлений вывода, appenders в log4xxx).
Как не видимое с первого взгляда следствие, желательна регулировка уровней отдельно от конфигурации выходных каналов (appender’ов), что нарушается во всех известных мне «промышленных» библиотеках логгирования.
Как именно это регулируется — отдельный файл с таблицей уровней, управляющий интерфейс через сокет/RPC, etc. — выбирается по месту.
6. Конфигурирование уровней должно допускать проверку уровня в рантайме (а не, например, после того, как сообщение пробежало пару AMQP релеев). Само форматирование для какого-то уровня может быть избыточно дорогим. Если известно, что форматирование дорогое, то код вида
if (logger.enabled(LOG_DEBUG)) {
logger.debug(...)
}
может сохранить скорость работы там, где просто logger.debug(...) её убьёт в 0.
Как вариант, если есть препроцессор (в C/C++, Erlang, некоторых других), можно делать макры под конкретный заказ сборки (самая быстрая, самая подробная, промежуточные — в одном проекте у нас было 4 уровня).
7. Структура тегов строк логов большого приложения должна быть иерархической. (log4j с аналогами могут обеспечить это сохранением «имени» логгера. Но иногда этого недостаточно.)
8. Отдельная серьёзная тема — централизованный сбор логов разных источников и перераспределение на логгирующих хостах. Тут идут или средства типа Kafka от Apache, или что-то самописное (например, поверх 0MQ с адекватным назначением префиксов для лёгкой фильтрации).
Уф, кажется, всё:)
О! Вот Вы своей репликой чётко показали, за что именно я хочу автора Winsock разжаловать в говномёсы.
Это в Unix то, что подаётся в select() это дескрипторы уровня ядра, и они ничем не отличаются от таких же полученных от open(), pipe() и прочих.
В случае Windows — функции — аналоги libc в CRT отдают нечто из собственной таблицы трансляции, а внутри ведут хэндлы. А вот то, что выдаётся по socket() - это уже хэндл уровня соответствующего API, и ничего общего с уровнем CRT не имеет. Если Вы попытаетесь напустить на него, например, close(), получите фигу или вылет нафиг — поэтому в Winsock свой closesocket().
С другой стороны, эти хэндлы не такие же, как файловые — большинство API функций работы с ними отличаются:( И неудивительно — потому что они по сути есть ссылки на структуры, внутри которых ядерный хэндл — только одно из полей. Все API, которые должны работать с ними — «снимают» обёртку в виде этой структуры и дальше общаются с ядром уже через спрятанный внутри хэндл. Ну не бред?
select() есть и работает практически так же, хотя AFAIR ограчен 64 сокетами. Но он не интегрируется с обычными десктрипторами (это основное из того, почему я ругался на автора Winsock). На IOCP забахивается обобщённый event loop на все виды объектов. Ограничения — при этом нет свободы миграции между IOCP (в kevent, epoll, аналогах это делается тривиально, а тут — дзуськи, или я не знаю какого-то секретного хака), иногда она полезна (например, самый эффективный http сервер возникает, когда быстрые и медленные соединения разносятся по разным группам исполнителей)
Сокеты-то в ней, как, наверно, в любой реализации сети, асинхронные «внутри»; более того, в отличие от файлов, у сокетов нет проблем переключения между синхронным и асинхронным стилем. Хотя это и дорогой подход (на Kegel’овские 10K сокетов он уже даст дикий оверхед, всякие IOCP будут дешевле).
(Другой вопрос, что автора классического Winsock API надо разжаловать в говномёсы и не пускать больше никогда за клавиатуру — это такие, как он, приводят к тому, что MS ни с чем не совместим, и ещё и гордится этим.)
От такого лида — да, правильно поможет.