Pull to refresh

Comments 28

Пример крайне неудачный. FileLogger продвигает в явном виде антипаттерн, противоречащий 12 factor apps. А именно — логгирование должно производится только в консоль и никуда более.

Во-2, у вас один интерфейс и у него одна зависимость. Для этого нужен DI контейнер, серьёзно?

Как должен логировать в консоль, например, Windows Service?

Точно также, только при запуске службы перенаправить stdout из dev/null в системный журнал event log

Я собственно ни разу не против DI. И в контексте DI считаю вполне нормальным использовать ILogger, предоставляющий для ICalculator возможности логгирования.

Как именно можно перенаправить Windows Service StdOut в Event log при запуске службы, следуя принципам двенадцати факторов?
И почему кстати Event log предпочтительнее иных средств, например, тестовых файлов?

Элементарно. Запускать бинарник из процесса, который стартует (инсталирует, суспендит, закрывает) службу и выполняет в ней бинарник, при этом перехватывает stdout бинарника и пишет его в системный журнал

Я не говорил, что он предпочтительнее везде и всегда. Иногда в зависимости от задачи и обстоятельств предпочтительнее может быть что угодно — dev/null, консоль, файл, ELK. Но как правило для windows системный журнал — хороший выбор, потому что это стандартный и рекомендованный вендором системный компонент централизованного логгирования + фронтенд.
Элементарно. Запускать бинарник из процесса, который стартует (инсталирует, суспендит, закрывает) службу и выполняет в ней бинарник, при этом перехватывает stdout бинарника и пишет его в системный журнал

Это совсем не элементарно и потому вызывает сомнения в целесообразности.
Какую проблему решит такой подход по сравнению с изоляцией логики логирования классическими средствами модульности (абстракции, библиотеки)?
В проектах какой компании можно встретить реализацию такого подхода к Windows Service? Где-то можно почитать об опыте его использования? Ведь надёжное межпроцессное взаимодействие штука не дешёвая.

Код я привёл в другой ветке, он тривиальный. Там требуется ещё garcefull shutdown, но я понятия не имею как это реализуется в windows без сигналов unix.

Такой подход позволяет:
— при разработке и в рабочем окружении не используются сторонние сервисы и зависимости, связанные с логгированием
— разработчику не нужно заниматься маршрутизацией и хранением stdout, это делегируется внешним программам
— поскольку поток событий пишется в stdout гарантированно без буферизации, кеширования и прочих вещей, которые могут создавать накладные расходы, у разработчика есть гарантия, что логгирование не станет узким местом, не создаст доп. нагрузку на GC и в случае C# на асинхронный пул

«надёжное межпроцессное взаимодействие штука не дешёвая.» — это верно, но не в случае перехвата дочернего stdout родительским процессом, в этом случае всё действительно просто

«В проектах какой компании можно встретить реализацию такого подхода к Windows Service?» — не могу сказать. Много ли компаний вообще используют windows service для бизнес кода? не уверен, не видел таких ни разу. В основном для инфраструктурного и системного насколько я могу судить. Разумеется в системном и инфраструктурном программировании 12F подходит не всегда, там много старых гайдланов и различных древних хакерских практик, которые до сих пор в ходу. понятно, что при разработке и работе условного драйвера для видюхи нет практически ничего из того, что предполагает 12F
В 12 factor apps речь идёт не о консоли, конечно. Постулируется, что «Приложение двенадцати факторов никогда не занимается маршрутизацией и хранением своего потока вывода… Вместо этого каждый выполняющийся процесс записывает свой поток событий без буферизации в стандартный вывод stdout.»
Если с первой частью я согласен, в пределах её применимости, то вторая, на мой взгляд, ошибочна. В более-менее серьёзном (веб-) сервисе логи структурированные. Помимо текстового сообщения, каждая запись несет в себе дополнительные данные и метаданные. Простым выводом в stdout тут не отделаешься. Нужен промежуточный агент со своим интерфейсом, позволяющий приложению записать структурированное событие и передающий его среде исполнения.
Ну понятно же, что консоль — это и есть stdout в большинстве случаев.

== вторая, на мой взгляд, ошибочна.
== Простым выводом в stdout тут не отделаешься.

Текстовое сообщение в данном случае — это json с «дополнительными данными и метаданными», для которого ни какие специальные агенты не требуются, а достаточно простой обёртки над выводом в stdut. Инфраструктурное ПО берёт сообщение из stdout и перенаправляет в logstash (или Loki). Смысл постулата — приложение никогда не должно само писать в logstash, loki, или боже упаси напрямую в elasticsearch.

Нет, консоль — это не stdout. Хотя, действительно, чаще всего stdout перенаправляется на консоль, отождествлять их — это грубая ошибка. Консоль это инфраструктура, включающая в себя экранный буфер, c произвольным доступом, аттрибутами символов и буфер ввода, имеющие свой собственный API. Для приложения выводить на консоль и выводить в stdout — это две большие разницы.
По поводу «простой обёртки над выводом» — с фактом наличия этой обёртки мы уже определились. Если возражений о том, что у этой обёртки есть набор публичных методов aka API, нет, то у нас получается тот самый логгер, только, скажем, не FileLogger, а StdoutLogger. А дальше, до введения собственно интерфейса ILogger остаётся один шаг.
Почему нужен агент? — в реальности, среда выполнения и инфраструктура журналирования не тождественны, а в случае с Windows service, приведённом выше, такая инфраструктура журналирования, как описывается в манифесте 12 factor app, просто отсутствует. Вот мы и получаем, с одной стороны — ILogger, с другой — необходимость в промежуточном агенте. Контейнер зависимостей, динамично выстраеваемый под конкретную среду выполнения, хотя и не без серьёзных недостатков, имеет право на существование, как решение этой потребности. Правда, лично мне для .Net больше нравится Apache Log4Net.
Это ни какая не грубая ошибка, а нормальное отождествление наиболее распространённого случая. По умолчанию stdout для разработчика — это консоль практически всегда.
А дальше, до введения собственно интерфейса ILogger остаётся один шаг.
А я изначально ничего и не имел против ILogger
в случае с Windows service, приведённом выше, такая инфраструктура журналирования, как описывается в манифесте 12 factor app, просто отсутствует
Элементарно создаётся на пальцах. Докер. nssm.cc Наверняка есть и что-то ещё, просто вы не в курсе
Контейнер зависимостей, динамично выстраеваемый под конкретную среду выполнения, хотя и не без серьёзных недостатков, имеет право на существование, как решение этой потребности.
Нет. Логгер нужно передавать в каждую функцию/метод в качестве параметра, чтобы получить в сообщении предопределённый сверху стека вызовов набор ключ-значение
Это ни какая не грубая ошибка, а нормальное отождествление наиболее распространённого случая. По умолчанию stdout для разработчика — это консоль практически всегда.


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

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

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

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

Я так понимаю, это желание выдать частное, и спорное архитектурное решение за общий случай? Какие, простите, ключи и значения необходимо передавать в каждый метод в стеке, и почему их обязательно необходимо оборачивать в логгер?
явные проблемы в понимании архитектуры.
Это вообще не имеет значения. Называйте как хотите. Не надо навязывать другим своё мнение.
давайте посадим Windows service в докер-контейнер
Эти измышления не уместны здесь. У меня был контраргумент к вашему утверждению «такая инфраструктура журналирования, как описывается в манифесте 12 factor app, просто отсутствует». Очевидно это не верно — я вам показал почему. Вопрос целесообразности я не поднимал, не надо всё мешать в одну кучу. И понимаете вы его не правильно если что. Понятно же, что службы windows разработаны 20-30 лет назад по дремучим гайдлайнам, которые ни кто переделывать не собирается, ни гайдлайны, ни сами службы. Но я с эти и не спорил — не надо приписывать мне то, что у вас в голове. Разработка служб windows — это вообще маргинальная и узкоспециализированная ниша, интересная чуть более чем никому. Какая ниша — такая и инфраструктура, такой и уровень соответствия современным рекомендациям. Когда мне нужно запускать веб-сервис в виде службы windows, я напишу обычный веб-сервис и без проблем запущу его в виде службы и направлю stdout куда мне надо без посторонних «агентов» и докеров. Цена вопроса — ~15-20 строк банального кода. Обсуждать это, тем более об этом спорить — бессмысленно. Не умеете — ни кто вас не заставляет.
Какие, простите, ключи и значения необходимо передавать в каждый метод в стеке,
Любые. Прочитайте об общих понятиях структурного логгирования прежде чем задавать подобные вопросы.
и почему их обязательно необходимо оборачивать в логгер?
Потому что они относятся к логгированию и ни к чему более. Но опять таки ни кто вам не мешает предавать ключ-значение напрямую, без ILogger, или вообще не использовать коль вы не умеете в структурное логгирование.
Это вообще не имеет значения. Называйте как хотите. Не надо навязывать другим своё мнение.


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

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

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

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

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

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

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

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

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

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

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

Ну и напоследок добавлю: да, Windows services это очень старая инфраструктура. Ну а Azure Application Services, Azure Functions, etc.? Тоже объявим дремучими и маргинальными?
Вы имеете полное право с ним не соглашаться, поэтому ни о каком навязывании речи не идёт.
А давайте тогда я буду говорить «консоль», а вы не будете меня одёргивать.
Это, очевидно, верно,
Я привёл вам факты, которые опровергаю ваше утверждение.
Спасибо за диагноз, так сказать, по фотографии
При чём здесь диагноз?
тогда поясните критерии целесообразности вот этого
Поясню. У меня логии === коснсоль. И, наоборот, всё, что попадает в консоль, автоматически идёт в логи. При разработке я думаю не о том, как логгировать, а о том, что логгировать. Могу вообще не использовать ILogger, а просто выводить в консоль нужный текст. Решение о том, как и куда логгировать — по умолчанию в консоль (в 99 % случаев), в никуда, в файл, базу данных, logstash — принимается при запуске программы, а не в процессе разработки. При этом мне для логгирования наплевать, в каком окружении работает мой сервис, в amazon cloude или в виде службы windows — мне не нужно менять программу, чтобы адаптировать её под произвольный журнал.
Если это можно сделать в 15-20 строк кода — с интересном изучу. Опубликуете?
Зачем? Это элементарные вещи. Вы не можете запустить дочерний процесс или редиректнуть его stdout? Вам в SO тогда наверное, там этого много для любого ЯП
совершенно несложно привести конкретный пример.
погуглил за вас
логгер у нас уже хранит состояние, плюс поддерживает многопоточную запись. Уже есть сомнения в возможности " достаточно простой обёртки над выводом в stdut"
То есть любой конкурентный код у вас по определению не может быть простым? Ну пусть будет так — простой для меня и сложной для вас обёртки. В любом случае речи не шло о том, чтобы писать логгер самому, готовых решение более чем достаточно
Ну а Azure Application Services, Azure Functions, etc.? Тоже объявим дремучими и маргинальными?
Не знаю. На основании чего их следуете такими объявить? Вообще по отзывам админов/девопсов azure cloud — проприетарщина и отвратительное соотношение цена/качество, и не понятно кто его использует и зачем. Может некие «партнёры» по специальным «программам».
А давайте тогда я буду говорить «консоль», а вы не будете меня одёргивать.

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

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

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

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

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

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

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

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

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

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

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

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

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

play.golang.org/p/yreNlk9bpoM
Вы думаете исключительно о том, _как_ логгировать в поток вывода
Не можете разработать код, который пишет в консоль, и полагаете, что другие не могут? Я пишу всё в консоль и в принципе не задумываюсь о реализации логгирования. Каким образом записи из консоли попадают в итоге в журнал — мне плевать, это решается в момент запуска приложения с помощью инфраструктурного ПО. Если по каким то причинам инфраструктурного ПО не хватает (чего не бывает практически никогда), то я или другой разработчик его создают, ни каких проблем с этим нет. Вы воюете с мельницей, поскольку такой подход к логгированию используется чуть более чем везде. Докер, systemd, облачные сервисы amazon, google cloud, heroku — всё это умеет работать с консольным выводом и полностью соответствует всем рекомендациям 12f, и мне не нужно ничего изобретать.
Вам приходится изобретать способ обернуть своё консольное приложение так, чтобы оно выглядело как Windows service
Я не пишу windows service. Я пишу бизнес фичи в соответствии с гайдлайнами, частью которых является консоль как единственный журнал. Потребуется запускать бизнес фичи в виде windows service — ни каких проблем, это бесплатно. Я в 90% случае даже представления не имею, на какой платформе будет запускаться моё приложение и в какой источник оно будет логгировать.
наплевав при этом на производительность, отказоустойчивость, простоту обслуживания.
Производительность и безопасность коня в вакууме — смешно. Попробуйте аргументировать.
Зона ответственности приложения заканчивается на вызове методов ILogger.Log*whatever*. Что происходит с логами дальше — это уже не забота разработчика.
Да, именно так у меня и есть. Благодаря следованию принципам 12f мои приложения не содержат плотформенных зависимостей, связанных с логгированием. А вот у вас если приложение использует event log windows для логгирования, то оно ни при каких обстоятельствах не будет работать на google cloude. И наоборот — если логгирует в google cloude, то не запустится под windows.
ссылка не имеет абсолютно никакого отношения к вопросу

ссылка про структурное логгирование не имеет ни какого отношения к структурному логгированию? ну ну
правильная реализация многопоточности — это уже непростой код, а шапкозакидательство не свидетельство квалификации. Обычно, наоборот.
Скорее свидетельсво узковатого кругозора у вас. Вы наверное имеете ввиду, что одновременно правильная и простая реализация многопоточности — это не про C#. На C# нельзя просто залочить мьютексом shared mutable state и одидать что это заработает. Ну так я с этим и не спорил. К счастью, я пишу на Go, и мне не сотавляет труда поставить мьютекс там, где есть доступ к стейту, и радоваться жизни.
второй пример дискредитации фактов, которые не укладываются в стройную теорию манифеста
Понятия не имею про azure, но и ничего не имею против неё — мне она фиолетова. Но вы опять не разобрались в вопросе. Azure умеет в докер, следовательно полностью соответсвует 12f в части логгирования. Скорее всего умеет и без докера (но кто в здравом уме будет деплоить C# без докера), просто вы не в курсе (а мне не интересно)
Это _вы_ не можете, говорите за себя.

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

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

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

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

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

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

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

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

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

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

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

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

Как Вы там писали? — А! «Это _вы_ не разобрались, говорите за себя.». Azure это делеко не только Docker, и, к счастью, не страдает параноидальным желанием засунуть всё в стандартный вывод, за что ему и спасибо.
Усилий не потребовалось, всё тривиально. Для безопасного завершения процесса потребуется доп. протокол через stdin дочернего процесса например, поскольку windows не умеет в сигналы unix. Если не уверены, можете самостоятельно проделать простейшую гимнастику (go mod init; go run. prog.exe; см. системный журнал «my service») и убедиться, как это сделал я. Или смотреть код библиотек, например, этой — там всего лишь вызовы windows api

Структурное логгирование не имеет ни какого отношения к перенаправлению stdout. Оно реализуется библиотекой логгирования. В процессе разработки это просто вывод в консоль в формате logfmt — key=value, разделённые пробелами. В продакшене — json с добавлениями метки времени. Устанавливается в конфигурации запуска приложения.

«Принцип 12f имеет к этому весьма опосредованное отношение, интерфейсы не его авторы изобрели.» — интерфейсы и 12F — параллельные понятия.

«Мьютекс на каждую запись в логи в продакшн сервисе? Это Вы серьёзно, да? Ну и про С# конечно тоже повеселило, спасибо.» — ну а меня веселят ваши нервная реакция и синдром даннинга крюгера. В Go мьютексы бесплатны и не блокируют поток ос, поскольку все инструкции асинхронны. И да, защищать мьютексом в Go всё, что может использоваться конкурентно — это рекомендованные best practices
Если не уверены, можете самостоятельно проделать простейшую гимнастику


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

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

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

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

Ну и про парсить stdin в веб-сервисе — это уже полная бесмыслица и мартышкин труд.
«логи самой обёртки в event log не пишутся» — я и не собирался. зачем мне это делать? задача стояла перенаправить лог дочернего процесса а не основного

2 — да, я забыл вставить инструкцию, закрывающую запущенный сервис при выходе из main

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

5 — ничего страшного и тоже в данном случае не важно.

Да, для продакшена я бы написал интеграционные тесты, проверяющие запуск, перезапуск, остановку, запись в сист. журнал и проч. — и что?

По поводу того, что запись логов в конечный журнал может тормозить — естественно может, спасибо кэп. По этому маршрутизаторы журналов, такие как promtail, Logplex, Fluent и logstash, кешируют и буферизирут свой ввод. И на приложении, из которого маршрутизатор получает ввод, эти тормоза -внезапно! — ни коим образом не отражаются. Ошибка новичка в данном случае — это святая уверенность в том, что если новичок не может что-то сделать быстро и просто, то это в принципе не было реализовано до него

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

а само по себе использование служб виндовз в качестве веб сервисов — бесСмыслица (с двумя «с») и мартышкин труд.
«логи самой обёртки в 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.

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

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

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

и т.д. Но здесь, всё же, не занятия по правописанию, и, придираться к опечаткам в комментариях на Хабре — это несусветная глупость.
«А куда они тогда пишутся? Ведь обёртка эти сообщения создаёт. Значит, замысел их выводить тоже был» — они пишутся в консоль и более никуда. Это нормально для консольного приложения системного и инфраструктурного назначения. Почему это вас так напрягает? Я не ставил задачи перенаправить это в системный журнал

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

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


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

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


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

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

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

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


В браузере, например, есть консоль, но нет stdout.
Sign up to leave a comment.