Комментарии 31
Отображает стектрейс и фрагменты исходников, где эта ошибка произошла (при наличии исходников, конечно).
Не очень понятно, где при этом должны быть исходники?
При каждом оборачивании обязательно передавать дополнительный текст ошибки, что мне кажется некоторым оверхедом при написании/чтении кода.
Ну тут на любителя. Наверное, хорошо иметь возможность делать и так, и эдак.
Насчет и так и так, могу только согласиться. Пожалуй, надо добавить опциональным параметром.
Исходники должны быть в среде выполнения.
Нет, не должны. В Go сборка выполняется в статический бинарник, который можно запустить, даже если Go в системе вообще не установлен. Что уж говорить про исходники.
Про параметр — может быть, там сделать не строку, а сразу ...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-образ. Таким образом у вас вообще ничего, кроме бинарника в докере не будет :) Дальше останется только, управляя переменными окружения, настроить данный образ и всё. Ибо, ИМХО, не очень осмотрительно держать исходники возле бинарника на продукции, если этого можно не делать.
Думаю, что гораздо быстрее и проще исходники можно получить через сотрудника или бывшего сотрудника.
Можно код написать и так, что любой `ioutil.ReadFile()` будет опасен.
И очевидно, я не сравниваю, что лучше, иметь или не иметь сорсы на проде, а сравниваю, покрывают ли приобретаемые бенефиты дополняющие их недостатки (например, в виде описанной Вами истории, где на сервере завелся хакер с доступом в систему). Если не покрывают (как, вероятно, в Вашем случае, поскольку Вам хватает просто правильно обрабатывать ошибки), то определенно не зачем их там держать.
В моем опыте не было ситуаций, когда компания, в которой я работал, переживала бы за то, чтобы держать исходники на своем собственно сервере.
Я недавно на C# такое решил сделать: вместо стектрейса — показывать исходники, подсвечивать нужные строки, показывать коментарии, ревизии (+ автор, комментарий и линки на задачи в Jira) + еще немного «поиграв», получилось имена параметров методов с типами и значениями на момент возникновения исключения делать для всего стектрейса (кроме системного), но пока прототип, коллеги не особо оценили, мол а какая от этого польза..))) не был бы я таким «ленивым», объяснил бы доходчиво что это дает, но на мой взгляд тут подумать и все сам поймешь… Потихоньку доделаю рабочий вариант, была идея статейку написать, но врядли)
Буду признателен если кто-нибудь распишет плюсы и минусы этой идеи, самому совсем не хочется тратить на это время. Сама идея очень понравилась.
Не нашел (плохо читал?) как сделать Unwrap ошибке, чтобы узнать ее оригинальный тип/значение за интерфейсом error.
Согласен, в Go ошибки это не исключения. Если Вам удобнее обрабатывать тысячи if err != nil { return err }
каким-то другим способом — это Ваш выбор, конечно
В том и дело, что в Go ошибки — это не исключения и это правильная обработка значения err
приходится кстати, если обрабатывать как можно ближе к месту возникновения, а не пробрасывать наверх по стеку чуть ли не до main.
уверен, что в большинстве случаев этот оверхед ничтожен
Без бенчмарка ни в чем нельзя быть уверенным, увы.
err.Err
Где обрабатывать ошибки, я не навязываю, как собственно и написал. Описанный способ подойдет для ошибок, которые пробрасываются наверх и для тех людей, кто считает это приемлимым.
Бенчмарки на сравнение что с чем Вы предлагаете?
Хотя бы на количество времени на операцию. Например, как https://github.com/ansel1/merry#features
Unwrap()
и Error.Unwrap()
.youtu.be/lsBF58Q-DnY
github.com/pkg/errors
Таких, которые отображают сорсы, я не встречал.
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.` Если этого не достаточно, то наверное, Вам это просто не нужно и у Вас нет такой проблемы.
Я думаю, leftpad (привет, npm) тоже нет проблемы написать для себя, или math.Round (привет, го 1.9) – тем не менее, многие этим не занимаются (как и я, в частности).
2) При повторном оборачивании ошибки (например, на уровень выше), стектрейс затирается менее информативным.
Это верно. Нет нормального способа "добавить стек, если его ещё нет". Но всё же у вас неточность.
Стек скорее не затирается, а дополняется. Если внутри одной горутины, будет дублирование, которое можно при печати самой ошибки убирать, примеры есть внутри pkg/errors
, но если из разных горутин, то стеки будут различаться.
3) При каждом оборачивании обязательно передавать дополнительный текст ошибки, что мне кажется некоторым оверхедом при написании/чтении кода.
Есть WithMessage
, который добавляет только сообщение, а есть WithStack
, который добавляет только стек.
Повышаем информативность ошибок в Go – github.com/ztrue/tracerr