Как стать автором
Обновить
1
0

Пользователь

Отправить сообщение

Со всем уважением к вашему проекту, но почему всё же "первые", если уже есть, например, WorkOutDoors?

За что Вы извиняетесь-то? :)
Вы, конечно, правы, не надо писать в windows event log миллионы сообщений, он для этого не предназначен. Для этого есть другие системы накопления логов. И разобираться с тем, что пишется в логи тоже нужно. Однако, нагрузка может быть вполне обоснованной. А потеря производительности при последовательной записи в stdout выражается не бинарным стостоянием (либо есть, либо нет), она варьируется в зависимости от нагрузки на веб сервис, и заметные потери могут проявиться уже при частичной загрузке потока. На мой взгляд, просто не надо к нему привязываться, и, не надо использовать такую вот обёртку вокруг него, которая выполняет операции ввода-вывода под мьютексом. Есть готовые библиотеки, в которых поборолись за масштабируемость и производительность. И прямые каналы записи в системы накопления логов быстрее, и, можно писать параллельно с нескольких потоков, и, не нужно сериализовать/восстанавливать данные лишний раз. Всё это можно сделать правильно, не привязываясь к конкретной среде исполнения.
они пишутся в консоль и более никуда. Это нормально для консольного приложения системного и инфраструктурного назначения. Почему это вас так напрягает? Я не ставил задачи перенаправить это в системный журнал


Да потому, что обёртка — это не консольное приложение, а windows service. А у windows services нет консоли :) Вы помните вообще, зачем Вы взялись её писать?
Хорошо, допустим, что не было замысла писать сообщения обёртки в event log. Тогда почему в режиме консольного приложения она как раз это и делает? Этот пример вообще Вы писали?

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


Снова переобуваемся на лету. Вы сказали дословно: «Когда мне нужно запускать веб-сервис в виде службы windows, я напишу обычный веб-сервис и без проблем запущу его в виде службы и направлю stdout куда мне надо без посторонних «агентов» и докеров. Цена вопроса — ~15-20 строк банального кода.». Речь идёт здесь не о примере, а именно о продукте. Вопрос про пример появился позже.

ровно стой же скоростью, с которой строка выводится в консоль при разработке, не больше и не меньше.

Разумеется! И это ни разу не быстро. И сидит под mutex, поэтому не масштабируется вширь вообще никак. Пока один поток пишет — все остальные ждут. Это как очередь на кассу с одним кассиром в магазине. Хоть миллион человек туда запусти — если кассир выпускает одного человека в минуту, с покупками оттуда за час выйдет ровно 60 человек.
«логи самой обёртки в event log не пишутся» — я и не собирался. зачем мне это делать?

А куда они тогда пишутся? Ведь обёртка эти сообщения создаёт. Значит, замысел их выводить тоже был. Или они там для красоты? :)
А вот эта реплика — "Если не уверены, можете самостоятельно проделать простейшую гимнастику (go mod init; go run. prog.exe; см. системный журнал «my service») и убедиться, как это сделал я" очевидно, относится вот к этому моему комментарию: куда пишутся логи самой обёртки тоже не очень понятно (ок, это может быть моё незнание golang, и они на самом деле тоже пишутся в eventLog, но я в этом не уверен)
Всё это обычное переобувание на лету.

неуместные придирки. Естественно для демонстрационного примера обработка ошибок и перезапуск сервиса меня не интересуют


Я просто напомню, с чего возник интерес к примеру. Конкретно, вот с этого Вашего утверждения: Когда мне нужно запускать веб-сервис в виде службы windows, я напишу обычный веб-сервис и без проблем запущу его в виде службы и направлю stdout куда мне надо без посторонних «агентов» и докеров. Цена вопроса — ~15-20 строк банального кода. . На проверку оказалось, что чудес на свете не бывает, что написать обёртку займёт отнюдь не 15-20 строк кода, а на пару порядков больше, да и времени на отладку уйдёт заметное количество. Приврали ради красного словца. Ну что же, бывает.

По поводу того, что запись логов в конечный журнал может тормозить — естественно может, спасибо кэп.

Ну что же опускаться до подмены сказанного собеседником на то, что удобно для себя? Напомню, речь не идёт о том, как _собираются_ логи с потока. А о том, как _сам сервис_ пишет их в поток вывода. Ваше предложение: достаточно простой обёртки над выводом в stdut… К счастью, я пишу на Go, и мне не сотавляет труда поставить мьютекс там, где есть доступ к стейту, и радоваться жизни. Ваше предложение однозначно понимается как устроить бутылочное горлышко, посадив запись в поток вывода под мьютекс. Именно в Вашей обёртке и будут тормоза.

а само по себе использование служб виндовз в качестве веб сервисов — бесСмыслица и мартышкин труд.

Заметьте, не я это предложил: Когда мне нужно запускать веб-сервис в виде службы windows, я напишу обычный веб-сервис и без проблем запущу его в виде службы и направлю stdout куда мне надо без посторонних «агентов» и докеров.
Если вынусть слово«веб» из этого тезиса, опять же, ничего не изменится. Парсить stdin в windows service, вместо того, чтобы принять callback от Service Control Manager — это бессмыслица, и мартышкин труд. Как и писать логи из windows service в поток вывода, потом городить обёртку, которая их будет перекладывать в event log.

бесСмыслица (с двумя «с»)

Вы хотите поиграть в игру про правописание? Это было бы несложно:

Ни какие, ни какая — пишется слитно.
Не уместны — тоже слитно.
Ни кто — снова, слитно.
логии — пишется с одной «и»

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


Раз это windows service, то пример был скомпилирован и установлен как windows service.
Баг №1 — интуиция меня не обманула. Нет, логи самой обёртки в event log не пишутся. Только обёрнутного приложения. Что интересно, если запускать с консоли, то да, логи обёртки тоже попадают в event log. Но мы же сервис тестируем.
Баг №2 — если обёртка аварийно завершает работу, обёрнутое приложение продолжает работать, все логи уходят в никуда
Баг №3 — после Бага №2, при попытке перезапустить сервис, запускается второй экземпляр оборачиваемого приложения.
Баг №4 — если обёрнутое приложение завершается, обёртка-сервис продолжает работать. Сервиса уже нет, но никто ни сном, ни духом, и у Windows шанса перезапустить сервис или поднять предупреждение нет.
Баг №5 — Если сообщение длинное, то оно в event log не пишется. Ошибок о сохранении сообщения в логе тоже не пишется. Длинные сообщения уходят в никуда.
Баг №6 нам уже известен — при остановке сервиса обёрнутое приложение аварийно завершается, со всеми вытекающими.
Про отсутствие хотя бы катерогий сообщений в обёртке я уже молчу.

Эти ошибки я нашёл за 10 минут экспериментов, и, они отнюдь не мелочи, они могут обернуться финансовыми и репутационными потерями для заказчика.

В Go мьютексы бесплатны и не блокируют поток ос, поскольку все инструкции асинхронны.

Какими бы бесплатными не были мьютексы, какими бы асинхронными не были инструкции, тот код, что защищен мьютексом, всегда выполняется только в одном экземпляре, последовательно. А под мьютексом у Вас — операция ввода-вывода, недешевая, надо сказать, операция. Очевидно, что за одну единицу времени больше запросов, чем количество раз, которое может исполниться код под мьютексом, сервис исполнить не сможет. А учитывая, что чаще всего на один запрос пишется несколько сообщений, можно смело уменьшать число запросов ещё на порядок. И решение это не масштабируется. Это обычное бутылочное горлышко — ошибка новичка.

Ну и про парсить stdin в веб-сервисе — это уже полная бесмыслица и мартышкин труд.
Это _вы_ не можете, говорите за себя.

Приветствую усилия по написанию примера. Получилось, правда, заметно больше, чем 15-20 строк, никаких структурированных логов (да и вообще всё валится в одну кучу), и это мы его ещё не тестировали. При этом мы потеряли часть функционала Windows Service — просто, потому, что консольное приложение так не может, с безопасным завершением сервиса по команде остановки есть вопросы, куда пишутся логи самой обёртки тоже не очень понятно (ок, это может быть моё незнание golang, и они на самом деле тоже пишутся в eventLog, но я в этом не уверен). Это так, на вскидку. И всё это лишь для того, чтобы выводить логи в консоль. Не мучайтесь! Возьмите для C# Log4Net. Вы получите всё то же самое, только не нужно будет изголяться с обязательным пропусканием логов через стандартный вывод.

Не можете разработать код, который пишет в консоль, и полагаете, что другие не могут?

Как Вы там выше писали? — «Это _вы_ не можете, говорите за себя.» :) Перенаправить логи в стандартный вывод дело нехитрое, только бесмыссленное, при наличии более эффективных и надёжных способов.

Я пишу всё в консоль и в принципе не задумываюсь о реализации логгирования.

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

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

Это просто смешно. Конечно же нет, он не используется везде. В области Вашей практики — возможно, но это не весь мир, и это не значит, что этот подход верный.

Да, именно так у меня и есть. Благодаря следованию принципам 12f мои приложения не содержат плотформенных зависимостей, связанных с логгированием.

Принцип 12f имеет к этому весьма опосредованное отношение, интерфейсы не его авторы изобрели. Скажем так, он предлагает делать это через выхлопную трубу.

На C# нельзя просто залочить мьютексом shared mutable state и одидать что это заработает.

Мьютекс на каждую запись в логи в продакшн сервисе? Это Вы серьёзно, да? Ну и про С# конечно тоже повеселило, спасибо.

Но вы опять не разобрались в вопросе. Azure умеет в докер, следовательно полностью соответсвует 12f в части логгирования.

Как Вы там писали? — А! «Это _вы_ не разобрались, говорите за себя.». Azure это делеко не только Docker, и, к счастью, не страдает параноидальным желанием засунуть всё в стандартный вывод, за что ему и спасибо.
А давайте тогда я буду говорить «консоль», а вы не будете меня одёргивать.

Давайте Вы будете называть поток вывода как Вам удобно, и не будете мне затыкать рот, когда я высказываю по этому поводу своё мнение?

При разработке я думаю не о том, как логгировать, а о том, что логгировать.

Это, очевидно, не так. Вы думаете исключительно о том, _как_ логгировать в поток вывода, и, именно поэтому Вам приходится изобретать способ обернуть своё консольное приложение так, чтобы оно выглядело как Windows service, наплевав при этом на производительность, отказоустойчивость, простоту обслуживания. И Вы прекрасно иллюстрируете, почему постулирование записи в поток вывода — это ошибка.
Зона ответственности приложения заканчивается на вызове методов ILogger.Log*whatever*. Что происходит с логами дальше — это уже не забота разработчика.

При этом мне для логгирования наплевать, в каком окружении работает мой сервис, в amazon cloude или в виде службы windows — мне не нужно менять программу, чтобы адаптировать её под произвольный журнал.

Запись логов в поток вывода не является необходимым условием для этого. Более того, Вам не наплевать — Вам приходится выкручиваться, чтобы приспособить среду выполнения к бесмысленному требованию.

Зачем? Это элементарные вещи.

Хорошо, всё понятно. Вы — не можете.

погуглил за вас

Спасибо, ссылка не имеет абсолютно никакого отношения к вопросу, и примера у Вас нет. Кстати, Вы заметили, как ловко автор заметает под ковёр вопрос конвертации даты? :)

То есть любой конкурентный код у вас по определению не может быть простым? Ну пусть будет так — простой для меня и сложной для вас обёртки.

Безусловно, правильная реализация многопоточности — это уже непростой код, а шапкозакидательство не свидетельство квалификации. Обычно, наоборот.

Не знаю… Вообще по отзывам админов/девопсов azure cloud — проприетарщина и отвратительное соотношение цена/качество, и не понятно кто его использует и зачем

Это второй пример дискредитации фактов, которые не укладываются в стройную теорию манифеста. Ну и не надо тогда претендовать на всеобъемлющесть, и пропихивать guidelines для частного случая везде, где только можно.
Это вообще не имеет значения. Называйте как хотите. Не надо навязывать другим своё мнение.


Это публичный форум, я высказываю свое мнение, и имею на это право. Вы имеете полное право с ним не соглашаться, поэтому ни о каком навязывании речи не идёт.

Очевидно это не верно

Это, очевидно, верно, и, именно поэтому потребовалось втащить в дискуссию Docker. И Вы же с этим согласны: «Какая ниша — такая и инфраструктура, такой и уровень соответствия современным рекомендациям».

Вопрос целесообразности я не поднимал, не надо всё мешать в одну кучу. И понимаете вы его не правильно если что.

Спасибо за диагноз, так сказать, по фотографии, давайте Вы уж тогда поясните критерии целесообразности вот этого: «Запускать бинарник из процесса, который стартует службу и выполняет в ней бинарник, при этом перехватывает stdout бинарника и пишет его в системный журнал», и вот этого в контексте Windows service: Элементарно создаётся на пальцах. Докер. nssm.cc .

Когда мне нужно запускать веб-сервис в виде службы windows, я напишу обычный веб-сервис и без проблем запущу его в виде службы и направлю stdout куда мне надо без посторонних «агентов» и докеров. Цена вопроса — ~15-20 строк банального кода.

Научиться чему-то новому — всегда полезно, серьёзно. Если это можно сделать в 15-20 строк кода — с интересном изучу. Опубликуете?

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

Это уход от ответа. Если Вы разбираетесь в этом хорошо, совершенно несложно привести конкретный пример.

Потому что они относятся к логгированию и ни к чему более. Но опять таки ни кто вам не мешает предавать ключ-значение напрямую, без ILogger, или вообще не использовать коль вы не умеете в структурное логгирование.

Давайте перейдём от диагнозов по фотографии к конкретным примерам.
Кстати, логгер у нас уже хранит состояние, плюс поддерживает многопоточную запись. Уже есть сомнения в возможности " достаточно простой обёртки над выводом в stdut"

Ну и напоследок добавлю: да, Windows services это очень старая инфраструктура. Ну а Azure Application Services, Azure Functions, etc.? Тоже объявим дремучими и маргинальными?
Это ни какая не грубая ошибка, а нормальное отождествление наиболее распространённого случая. По умолчанию stdout для разработчика — это консоль практически всегда.


Если разработчик оговорился — это ещё можно понять, но если такое отождествление нормально, это явные проблемы в понимании архитектуры.

Элементарно создаётся на пальцах. Докер. nssm.cc Наверняка есть и что-то ещё, просто вы не в курсе

Да, конечно, давайте посадим Windows service в докер-контейнер, со всеми его накладными расходами, и побъёмся над тем, чтобы обеспечить нужное поведение. Есть такая штука — целесообразность применения — наверное, Вы просто не в курсе.
А теперь давайте взглянем с точки зрения манифеста 12. Среда исполнения Windows service — это таки Windows, со своим, особым взаимодействием с сервисами. То, что Вы предлагаете — это вкрутить ещё одну прослойку между сервисом и средой исполнения так, чтобы приложение можно было уложить в прокрустово ложе манифеста. Ну будет у Вас Docker этим самым агентом. Всё равно ничего не изменится.

Нет. Логгер нужно передавать в каждую функцию/метод в качестве параметра, чтобы получить в сообщении предопределённый сверху стека вызовов набор ключ-значение

Я так понимаю, это желание выдать частное, и спорное архитектурное решение за общий случай? Какие, простите, ключи и значения необходимо передавать в каждый метод в стеке, и почему их обязательно необходимо оборачивать в логгер?
<промахнулся с веткой>
Нет, консоль — это не stdout. Хотя, действительно, чаще всего stdout перенаправляется на консоль, отождествлять их — это грубая ошибка. Консоль это инфраструктура, включающая в себя экранный буфер, c произвольным доступом, аттрибутами символов и буфер ввода, имеющие свой собственный API. Для приложения выводить на консоль и выводить в stdout — это две большие разницы.
По поводу «простой обёртки над выводом» — с фактом наличия этой обёртки мы уже определились. Если возражений о том, что у этой обёртки есть набор публичных методов aka API, нет, то у нас получается тот самый логгер, только, скажем, не FileLogger, а StdoutLogger. А дальше, до введения собственно интерфейса ILogger остаётся один шаг.
Почему нужен агент? — в реальности, среда выполнения и инфраструктура журналирования не тождественны, а в случае с Windows service, приведённом выше, такая инфраструктура журналирования, как описывается в манифесте 12 factor app, просто отсутствует. Вот мы и получаем, с одной стороны — ILogger, с другой — необходимость в промежуточном агенте. Контейнер зависимостей, динамично выстраеваемый под конкретную среду выполнения, хотя и не без серьёзных недостатков, имеет право на существование, как решение этой потребности. Правда, лично мне для .Net больше нравится Apache Log4Net.
В 12 factor apps речь идёт не о консоли, конечно. Постулируется, что «Приложение двенадцати факторов никогда не занимается маршрутизацией и хранением своего потока вывода… Вместо этого каждый выполняющийся процесс записывает свой поток событий без буферизации в стандартный вывод stdout.»
Если с первой частью я согласен, в пределах её применимости, то вторая, на мой взгляд, ошибочна. В более-менее серьёзном (веб-) сервисе логи структурированные. Помимо текстового сообщения, каждая запись несет в себе дополнительные данные и метаданные. Простым выводом в stdout тут не отделаешься. Нужен промежуточный агент со своим интерфейсом, позволяющий приложению записать структурированное событие и передающий его среде исполнения.
Ёмкость батареи в новом Pro 13: 54.5 Вт*ч, в старом Surface Book — 70 Вт*ч, в новом Surface Book i7 w/Performance Base — предположительно 90 Вт*ч.

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность