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

Комментарии 14

Разве такие потребности не решаются тем же прометеусом?
А у вас здесь кроме неподдерживаемого кода ещё и создание тредов руками (ещё и без try..catch, что может привести к краху всего процесса) и динамики непонятно зачем и это на первый взгляд только.
Ну и ещё вопросы — кто будет ваш тред останавливать, учитывая, что при завершении процесса в очереди могут быть ещё задачи?
и BlockingCollection был бы здесь более подходящим вариантом с его семафорами и GetConsumingEnumerable, а не Thread.Sleep в цикле как у вас.

А какие потребности решаются прометеусом? Хранение метрик, да решаются. Здесь я пишу как обложить код измерителями не нарушая его работу, а как хранить вопрос уже другой. На удаленных машинах(подразумевается desctop приложение) может и не быть доступа к серверу прометеуса, а померить что-то нужно, как вариант можно использовать sqlite базу, почему нет.

Неподдерживаемый код — ну что за инфантильные ярлыки? Ну почему же тредов руками? Первое — тред один. Второе — интересно узнать каким место вы создаете треды? Только не надо писать про Task, он нужен когда создается множество тредов через тредпул(под капотом) и с удобным управлением. Вот насчет try..catch, соглашусь не помешал бы, хотя у меня еще не было в этом месте исключений, но в принципе они возможны. Динамика понятно зачем нужна, чтобы отвязаться от типов, иногда это удобно, например, чтобы писать обработчики для уже существующих или произвольных logItem. Злоупотреблять динамикой не стоит, но иногда и чуть-чуть, где это сэкономит время и силы почему же нет?

Тред из-баграунд, остановится влсед за приложением. Нет цели собрать абсолютно все измерения, зачем? К тому же даже если остановить тред, в очереди останутся события, и что остановка изменит, зачем это?

BlockingCollection был бы здесь более подходящим вариантом

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

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


Только не надо писать про Task, он нужен когда создается множество тредов через тредпул(под капотом) и с удобным управлением

Отчего же не надо, когда тут самый подходящий случай? И тредпул как раз-таки не про множество тредов, а совсем наоборот чтобы треды не плодить.
И кстати, если бы использовали нормальную очередь с поддержкой асинхронного ожидания, то выделять тред вообще бы не пришлось.
Но если уж так надо было сделать всё синхронно, то можно выставить TaskCreationOptions.LongRunning, чтобы тредпул (но только если понадобится!) не стеснялся создать ещё один тред.


Извиняюсь, что несколько резко высказываюсь, с утра воду отключили.

Оп, извиняюсь, я тут имел ввиду AppMetrics и его аналоги.

Может быть, не могу сказать.
никому кроме вас он не нужен

Не следует говорить за всех)
лучше протестирован и постоянно обновляется/фиксятся баги

Вспоминается цитата):
Есть два способа разработки проекта приложения: сделать его настолько простым, чтобы было очевидно, что в нем нет недостатков, или сделать его таким сложным, чтобы в нем не было очевидных недостатков. Ч. Э. Р. Хоар (C. A. R. Hoare)

Отчего же не надо, когда тут самый подходящий случай? И тредпул как раз-таки не про множество тредов, а совсем наоборот чтобы треды не плодить.

Тут наверно можем долго спорить. Как я понимаю основная идея тредпула это ускорить создание потоков, типа кеширования для потоков. Ресурсы под поток выделяются достаточно долго, что легко проверить например создав 10к потоков в цикле. Тредпул на то и пул что содержит уже готовые потоки, которые переиспользуются для выполнения тех же тасков. Поэтому 10к тасков создаются быстро и достаточно быстро обрабатываются на уже готовых потоках. А если у меня 1 поток на все время жизни приложения, зачем же мне таск, хотя не исключаю что его можно использовать. Кстати с тасками и тредпулами тоже есть нюансы, некоторые потоки используются для числодробилок вычислений их создавать больше чем ядер смысла нет. Другие могут использоваться для ввода вывода и большую часть времени висят в блокировке, таких можно создавать почти неограниченно, цпу для них не основной ресурс. Некоторые типы потоков могут потреблять много памяти их количество нужно регулировать по доступной для процесса памяти. В этих случаях под разные задачи приходится писать кастомные тредпулы. В случае создания треда «руками», во всю эту механику не вмешиваемся.
если бы использовали нормальную очередь

За это спасибо, подумаю над этим, вполне возможно вы правы, стоит попробовать BlockingCollection.

Извиняюсь, что несколько резко высказываюсь, с утра воду отключили.

Понимаю вас, с утра не обнаружить в кране воду это жестко. Казалось бы 21 век, компьютеры, ракеты, а бесперебойную подачу воды реализовать не могут!
Кстати да, очень похоже. Нужно будет пощупать.
Однажды мне попало на поддержку весьма жирное и написанное не по феншую приложение, афтор которого бесследно исчез. Приложение начало сильно тормозить, а оно активно использовалось для решения бизнес задач. И мне пришлось экстремально быстро искать проблему, причем нужно было понять что происходит внутри весьма длинных методов. Тогда буквально за 20 минут и был написан почти этот логер, он помог решить проблему достаточно быстро. Потом я его немного причесал и стал много где использовать, в том числе и вместе с тем же Prometheus. Статью писал исключительно чтобы поделиться идеей, кто-то может столкнуться с похожей задачей, а кто-то может придумать как адаптировать решение для своих целей.
Несколько лет назад реализовал и поддерживаю нечто подобное, только гораздо более монструозное решение. Одновременно решает проблему логирования и профилирования.
Настраиваемые логеры, древовидная структура вызовов, замер времени выполнения операции, логирование ошибок, возможность замера времени выполнения без логирования (для ведения статистики) и тому подобное.
Читабельность логов повысилась кардинально. Обложенные логами методы пишут точку вход и выхода из операции, её уникальный номер. Очень помогает в многопоточном коде, избавляет от необходимости россыпи строк типа «Log.Debug(»Begin ...)" «Log.Debug(»End...)".
Есть предварительная договорённость с менеджментом по выводу этого кода в опенсорс с публикацией на гите и NuGet, но пока руки не доходят.
П.С.: В нашем решении асинхронности нет. После каждого изменения в этом коде делаю замеры студийным профайлером — оверхед на логирование минимальный, измеряется долями процента, а качества анализа логов и закрытия саппорт-тикетов повышается кардинально.
Пример вывода профайлера (периодически пишется в логи для выяснения боттлнеков при жалобах на производительность приложения):
Очень интересно, хотелось бы посмотреть. Поделитесь пожалуйста ссылкой если все же решитесь опубликовать.
Как только соберусь — обязательно статья на хабре будет. Можете подписаться, чтобы не пропустить.

Лично я для измерения кода предпочитаю пользоваться линейкой.




А если серьёзно, то в нашем проекте очень похожая структура для сбора статистики, только на Java:
try (var psr = new WatchScope(<...name...>)) { }.

1)Имхо использование using'а не по назначению не правильно… Еще бы в финализаторы позапихивать измерение метрик кода
2)Зачем писать свой логгер, если можно использовать какой-нибудь log4net, который может писать куда угодно и поддерживает параллельную запись в файл из разных потоков.
Простите, а где можно почитать о назначении директивы using и о том, где её можно использовать, а где нет?
using — это всего лишь синтаксический сахар, превращаемый компилятором в конструкцию:
try {… } finally { if (obj != null) obj.Dispose(); }
Поэтому не вижу ничего криминального в использовании using там, где это сокращает объём кода, особенно с C#8, который дал возможность упрощать using до одной строки.

Что касается второй части — никто не отменяет log4net. Просто обычные логгеры не умеют логировать время выполнения операций, поэтому есть смысл использовать их в связке с конструкцией, типа той, что предложена автором статьи. Логгер — это абстракция, и не имеет значения куда пишутся записи — файл, база, почта, веб-сервис. Смысл предложенной конструкции совсем не в этом.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий