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

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

Отображает стектрейс и фрагменты исходников, где эта ошибка произошла (при наличии исходников, конечно).


Не очень понятно, где при этом должны быть исходники?

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


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

Нет, не должны. В Go сборка выполняется в статический бинарник, который можно запустить, даже если Go в системе вообще не установлен. Что уж говорить про исходники.

«Должны» я говорю в контексте того, что Вы хотите их отображать. Если достаточно стектрейса, то исходники не нужны.
Все-таки непонятно про исходники — они должны быть рядом с исполняемым файлом или же в GOPATH?

Про параметр — может быть, там сделать не строку, а сразу ...inteface{}?
В стектрейсе будет абсолютный путь до файла, где он был во время сборки. Там его будет искать этот пакет.
У меня есть план сделать, чтобы можно было подменять путь до $GOPATH, но пока не сделал.

Про парметр, как мне кажется, должны поддерживаться такие сценарии использования:
tracerr.Wrap(err)
tracerr.Wrap(err, "some info")
tracerr.Wrap(err, "some info: %#v %#v", param1, param2)


Как я понимаю, Вы имеете ввиду так?
tracerr.Wrap(err, param1)
В стектрейсе будет абсолютный путь до файла, где он был во время сборки


Ну, в принципе, я уже вплотную подхожу к идее собирать содержимое контейнеров по месту развертывания… :)

Насчет параметров я имею ввиду так:

tracerr.Wrap(err, "some info", info1, info2...)


Т.е. функция Error() должна это все как-то универсально соединять, чтобы не мучиться уже с форматированием типа «some info: %#v %#v», а то каждый раз думаешь, как же это сформулировать…
Я думаю, я понял суть, спасибо за пояснение)
Выше я описал привычное для Sprintf поведение, но по идее можно сделать разные методы.
Ну, в принципе, я уже вплотную подхожу к идее собирать содержимое контейнеров по месту развертывания… :)


Какой в этом бенефит? ИМХО, самое классное — это собрать в pipeline во время ci, и потом только бинарник положить в `FROM scratch` docker-образ. Таким образом у вас вообще ничего, кроме бинарника в докере не будет :) Дальше останется только, управляя переменными окружения, настроить данный образ и всё. Ибо, ИМХО, не очень осмотрительно держать исходники возле бинарника на продукции, если этого можно не делать.
Чем это чревато (почему не осмотрительно)?
Ну, теоретически при проникновении в вашу инфраструктуру злоумышленника, вы можете получить утечку исходников, что в свою очередь может открыть дальнейшие векторы атаки (хотя, конечно, куда уж хуже, но тем не менее). Так зачем ему давать эту (хоть и весьма гипотетическую) возможность? А в случае других неосмотрительностей (конкретно при использовании вашей библиотеки) злоумышленник может получить больше внутренней информации об ошибках: много раз видел, как разработчики допускают отображение стек-трейса при возникновении ошибки в ответе от http-сервера. Все это с точки зрения безопасности весьма плохо. Чем меньше находится лишнего на продакшне, тем лучше.
Чем меньше, тем лучше – согласен. Неосмотрительно – не согласен. Большая часть сайтов, любого масштаба, написана на интерпритируемых языках и, подозреваю, исходники вполне есть на проде.
Думаю, что гораздо быстрее и проще исходники можно получить через сотрудника или бывшего сотрудника.
Можно код написать и так, что любой `ioutil.ReadFile()` будет опасен.

И очевидно, я не сравниваю, что лучше, иметь или не иметь сорсы на проде, а сравниваю, покрывают ли приобретаемые бенефиты дополняющие их недостатки (например, в виде описанной Вами истории, где на сервере завелся хакер с доступом в систему). Если не покрывают (как, вероятно, в Вашем случае, поскольку Вам хватает просто правильно обрабатывать ошибки), то определенно не зачем их там держать.
В моем опыте не было ситуаций, когда компания, в которой я работал, переживала бы за то, чтобы держать исходники на своем собственно сервере.
на своем собственно сервере

Если сервер действительно свой, и вот он стоит, можно подойти потрогать руками, то гипотетически это один уровень угрозы, а если это сервер в дата-центре, инстанс в AWS, etc — словом, у вас/компании нет физического доступа к серверу — совсем другой.

Спасибо, интересная статья!
Я недавно на C# такое решил сделать: вместо стектрейса — показывать исходники, подсвечивать нужные строки, показывать коментарии, ревизии (+ автор, комментарий и линки на задачи в Jira) + еще немного «поиграв», получилось имена параметров методов с типами и значениями на момент возникновения исключения делать для всего стектрейса (кроме системного), но пока прототип, коллеги не особо оценили, мол а какая от этого польза..))) не был бы я таким «ленивым», объяснил бы доходчиво что это дает, но на мой взгляд тут подумать и все сам поймешь… Потихоньку доделаю рабочий вариант, была идея статейку написать, но врядли)
Буду признателен если кто-нибудь распишет плюсы и минусы этой идеи, самому совсем не хочется тратить на это время. Сама идея очень понравилась.
Пилите статью!
Возможно, прозвучит не убедительно, но времени пока нет даже прототип доделать, не то что статью… Да и статьи ни разу не писал, заминусуют, расстроюсь..))
Дорогу осилит идущий ;)

Не нашел (плохо читал?) как сделать Unwrap ошибке, чтобы узнать ее оригинальный тип/значение за интерфейсом error.


Согласен, в Go ошибки это не исключения. Если Вам удобнее обрабатывать тысячи if err != nil { return err } каким-то другим способом — это Ваш выбор, конечно

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


уверен, что в большинстве случаев этот оверхед ничтожен

Без бенчмарка ни в чем нельзя быть уверенным, увы.

Тут не описывал, но можно получить оригинальную ошибку без стектрейса так: err.Err

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

Бенчмарки на сравнение что с чем Вы предлагаете?
Спасибо, попробую добавить.
Добавлены Unwrap() и Error.Unwrap().
известный в узких кругах Dave Cheney такую библиотеку сделал уже несколько лет назад и даже дал по ней выступление:
youtu.be/lsBF58Q-DnY
github.com/pkg/errors
Оличная библиотека, я написал, почему она мне не подошла, спасибо, что дочитали до конца.
FYI В будущих версиях Go собираются решить проблему отсутствия стек-трейсов. Proposal: Go 2 Error Inspection
Таких библиотек весьма много на самом деле. Нет проблем для себя это написать. Я вот тоже как-то делал: github.com/go-extras/kasoro (да, она попримитивнее, но и сделана была только для себя). Но в конечном итоге использую её только в случае каких-то трудноуловимых ошибок. В обычное время, как тут уже писали выше, своевременная обработка ошибки возле места её возникновения решает большинство проблем.
«Таких» это каких, которые отображают стектрейс и сорсы? Библиотека по ссылке, насколько я понимаю, может только стектрейс. Да, «таких» которые умею стектрейс полно, я не претендую на новизну)
Таких, которые отображают сорсы, я не встречал.
Ну, имхо, главное — это стектрейс, а сорсы — это так, хотя и любопытная, но плюшечка. Да, её вы позиционируете, как основное преимущество библиотеки, но лично я в нем особого смысла не вижу — ведь если дебаг ведется рядом с исходниками, то там можно всегда подноценно отдебагать с брейкпоинтами в нужных местах. А если софт расположен на сервере, то зачем там иметь исходники?

P.S. Вы не воспринимайте, если что, как обиду или что-то личное. Я пытаюсь понять use-case, где действительно была бы нужна возможность показать исходники.
Я не воспринимаю как обиду, спасибо, что уделили время и поделились своими мыслями.

Мне лично сорсы помогают добавить контекста к эррор-репорту, тем самым ускорить процесс понимания того, что пошло не так. Я допускаю, что не только мне одному. Если кому-то удобно получить стек трейс, затем идти по файлам, чтобы понять контекст, то pkg/errors подойдет гораздо лучше, я думаю.

Касательно юз-кейсов на проде, все то же самое – это добавляет контекста к ошибкам, не требует открывать код во многих случаях вообще, чтобы понять, в чем корень. Предлагаю посмотреть такие продукты, как: Sentry и Elastic APM. Они оба используют сорсы в стектрейсах, показывают сорсы и стектрейсы в ошибках, имеют овер 9000 поклонников, и указывают на своих сайтах сорсы в ошибках, как классную фичу: `Sentry shows your source code right in the stacktrace, so you don’t need to find it yourself.` Если этого не достаточно, то наверное, Вам это просто не нужно и у Вас нет такой проблемы.
То что нет проблем для себя это написать – у меня вот есть проблема писать для себя это каждый раз. Но нет проблемы написать 1 раз для себя и других.
Я думаю, leftpad (привет, npm) тоже нет проблемы написать для себя, или math.Round (привет, го 1.9) – тем не менее, многие этим не занимаются (как и я, в частности).
2) При повторном оборачивании ошибки (например, на уровень выше), стектрейс затирается менее информативным.

Это верно. Нет нормального способа "добавить стек, если его ещё нет". Но всё же у вас неточность.


Стек скорее не затирается, а дополняется. Если внутри одной горутины, будет дублирование, которое можно при печати самой ошибки убирать, примеры есть внутри pkg/errors, но если из разных горутин, то стеки будут различаться.


3) При каждом оборачивании обязательно передавать дополнительный текст ошибки, что мне кажется некоторым оверхедом при написании/чтении кода.

Есть WithMessage, который добавляет только сообщение, а есть WithStack, который добавляет только стек.

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории