Привет, Хабр! Я Полина, продакт платформы «Своё вино» в РСХБ — цифровой платформы, которая объединяет производителей вина, потребителей, сомелье, критиков и всех любителей российского вина. Когда гость на дегустации говорит «С вином что-то не так», я слышу примерно то же, что тимлид в пятничном сообщении «У нас все упало». В целом посыл понятен, но информации ноль. Когда гость на дегустации говорит «С вином что-то не так», я слышу примерно то же, что тимлид в пятничном сообщении «У нас все упало». В целом посыл понятен, но информации ноль.
Я сомелье, и чем дольше смотрю, как коллеги из IT пишут тикеты, тем сильнее ощущение, что мы давно занимаемся одним делом: выясняем, почему система повела себя не так, как ожидалось, не имея доступа к исходникам. Откатить бочку к прошлому коммиту нельзя. Посмотреть diff погоды за август тоже.
Давайте разбираться, как устроен хороший баг-репорт на бутылку, какие коды ответа бывают у вина и почему самый известный винный дефект ведет себя как баг, который заодно отключает логирование.

Пробный глоток — это дымовой тест
В ресторане сомелье показывает бутылку с этикеткой, открывает ее и наливает вам немного вина на донышко бокала. Многие уверены, что сейчас их спрашивают «нравится?». Вопрос на самом деле другой: «Бутылка исправна?»
Показ этикетки — проверка версии: то ли вино, тот ли год. Пробный глоток как дымовой тест, он же smoke test: система запустилась, ничего не горит, посторонних запахов нет. Проверять, подходит ли вам стиль, на этом этапе поздновато: это вопрос к этапу сбора требований, то есть к разговору до заказа.
Формально бутылку меняют, если она неисправна. Многие рестораны идут навстречу и тогда, когда гостю просто не понравилось, но это жест гостеприимства, а не багфикс. Это как разница между хотфиксом и «ладно, сделаем, раз клиент очень просит».
Знак вопроса, который стоит выучить
В британской школе WSET (Wine & Spirit Education Trust, «Образовательный фонд вина и крепкого алкоголя»), которая с 1969 года выдает дипломы о винном образовании больше чем в 70 странах, есть Systematic Approach to Tasting, то есть «системный подход к дегустации»: дегустационная карта с жестким порядком: внешний вид, аромат, вкус, выводы. В ней есть деталь, которую я показываю всем, кто пишет тикеты.
Первый пункт в разделе аромата — состояние вина:
Condition: clean – unclean (faulty?)
В разделе внешнего вида то же самое:
Clarity: clear – hazy (faulty?)
Смотрите на скобки. «Мутное» — наблюдение. «Дефектное?» — гипотеза, причем со знаком вопроса. Мутность не обязательно брак: ее часто можно встретить в петнатах и нефильтрованных винах. А странный аромат может оказаться замыслом винодела.
Гайдлайны Mozilla по баг-репортам говорят то же самое своими словами: заголовок описывает проблему, а не предполагаемое решение, фактический результат пишется отдельно от ожидаемого, а несколько проблем — это несколько отчетов.
Переводим на винный:
Как говорят |
Как полезнее |
«Тут пробка» |
«Устойчивый запах мокрого картона и подвала, фруктовость почти не читается» |
«Вино умерло» |
«Аромат слабый, во вкусе мало свежести, послевкусие короткое. Возможно, вино прошло свой пик?» |
«Вино кислое» |
«Кислотность высокая, а фрукта и тела не хватает, чтобы ее уравновесить» |
«Невкусно» |
«Вино чистое, но мне не подходит такая сладость» |
«Приложение сломалось» |
«При импорте CSV с пустым полем email сервер отвечает 500» |
Предпоследняя строка вообще не баг, а неверно собранные требования. Высокая кислотность тоже сама по себе не дефект: для рислинга или классического шампанского это несущая конструкция.
Коды ответа бутылки
Раз уж мы здесь все немного «мамкины программисты», как было в известном меме, разложим винные «неисправности» по классам HTTP. Классификация шуточная, но границу между «проблемой клиента» и «проблемой сервера» я провела довольно точно.
2xx: все в порядке, просто выглядит подозрительно
200 OK — винный камень. Прозрачные кристаллы на дне бокала или на пробке, похожие на сахар или, что пугает сильнее, на битое стекло. Это соли винной кислоты, они выпадают на холоде и совершенно безвредны. Рекордсмен по числу ложных тикетов.
200 OK — муть в петнате или нефильтрованном вине. Петнат (petillant naturel) разливают по бутылкам раньше, чем брожение закончилось, и доигрывает он уже в бутылке. Дрожжевой осадок при этом остается внутри, поэтому вино мутноватое. Нефильтрованные вина мутнеют по другой причине: их намеренно не прогоняют через фильтр, чтобы сохранить текстуру и аромат. И в том и в другом случае муть — часть задумки, а не поломка. Хорошо, если на этикетке об этом написано прямо.
200 OK — окислительные ноты в хересе. Тона ореха и печеного яблока для молодого совиньон блана — дефект, а для хересов или «желтого вина» из Жюры ( визитная карточка винодельческого региона на востоке Франции Vin Jaune) — паспортная характеристика. Один и тот же лог значит разное в зависимости от продукта.
4xx: проблема на стороне клиента
400 Bad Request. «Принесите что-нибудь хорошее». Без бюджета и описания стиля запрос не парсится. Без четкого ТЗ результат… Сами знаете.
409 Conflict. Вино и еда не подружились. Артишоки делают следующий глоток странно сладковатым, острое усиливает ощущение спирта, а десерт слаще вина превращает его в кислую воду.
421 Misdirected Request. Вы вдыхаете аромат не вина, а парфюм соседа, трюфельное масло с соседней тарелки или шкаф, в котором хранили бокал.
422 Unprocessable Content. Запрос корректный, но обработать его нельзя: красное подали теплым, как чай, а белое настолько ледяным, что аромата нет вовсе.
429 Too Many Requests. Сороковой образец на профессиональной дегустации. Рецепторы устают, и все начинает казаться одинаково терпким и кисловатым. Retry-After: вода, крекеры, пауза, хлебушек. Дали рецепторам отдохнуть и пошли дегустировать дальше.
5xx: проблема на стороне сервера
Сервер здесь — все, что случилось с вином до того, как оно попало на ваш стол: виноградник, винодельня, укупорка, склад, логистика.
500 Internal Server Error — дефекты производства. Летучая кислотность: вино пахнет уксусом и жидкостью для снятия лака, это уксусная кислота и этилацетат. Бретт (дрожжи Brettanomyces) дает ноты скотного двора и лейкопластыря. Про бретт, кстати, иногда спорят с интенсивностью табов против пробелов: в малых дозах часть профессионалов называет его сложностью. Но, на мой вкус, это брак.
500 — «вкус света». Белое, розовое или игристое вино в прозрачной бутылке, постоявшее на свету, может начать пахнуть вареной капустой, чесноком или тухлым яйцом. Свет поглощает рибофлавин (витамин B2, его оставляют в вине дрожжи), и тот окисляет аминокислоту метионин до летучих соединений серы. Никакой ошибки винодела при этом может и не быть: баг прекрасно воспроизводится на полке магазина под лампами.
503 Service Unavailable — редукция и «закрытое» вино. Серные запахи — тухлое яйцо, резина, спичка. Если они легкие, часто уходят после аэрации: тот редкий случай, когда перезапуск (читай: декантер или аэратор) действительно помогает. Не ушли — значит, это был 500. Сюда же попадут и некоторые молодые вина, которые сразу после открытия почти не пахнут: в заголовке честно написано Retry-After, откройте бутылку и подождите минут 15–20.
507 Insufficient Storage — термическое повреждение. Бутылку держали в жаре: ароматы варенья и компота, пробка приподнята, на горлышке подтеки. Хранилище не справилось. Заметили такую бутылку в магазине — не берите.
410 Gone — вино перестояло. Оно пережило свой срок поддержки: фрукт выцвел, свежести не осталось, вкус плоский и уставший.
502 Bad Gateway — пробковый дефект. Пробка — буквально шлюз между вином и внешним миром. Про этот код поговорим подробно, потому что это, пожалуй, лучший баг винной индустрии.
502: баг, который отключает логирование
Пробковый дефект чаще всего вызывает 2,4,6-трихлоранизол, он же TCA. Пахнет мокрым картоном, сырым подвалом, плесенью, иногда мокрой собакой (не спрашивайте, откуда я это знаю). Но интереснее всего то, как он работает.
Начнем с порога чувствительности. TCA становится заметен в вине при концентрациях порядка 1–4 нанограммов на литр, в белых и игристых порог обычно ниже. Прикинем: олимпийский бассейн — это не меньше 2,5 млн литров. Чтобы весь этот объем, будь он наполнен вином, начал пахнуть подвалом на уровне 2 нг/л, хватит около 5 миллиграммов TCA. Это меньше, чем весит одно рисовое зерно!
Еще интереснее механизм. Долго считалось, что TCA просто добавляет неприятный запах. В 2013 году исследователи из Университета Осаки опубликовали работу в журнале PNAS (Proceedings of the National Academy of Sciences of the USA — «Труды Национальной академии наук США», один из самых цитируемых научных журналов мира). Они показали: TCA не вызывает собственного отклика рецепторов, а подавляет ионные каналы в обонятельных клетках, причем эффект заметен при аттомолярных концентрациях — это 10⁻¹⁸ моля на литр, примерно в миллион раз меньше той концентрации, при которой мы вообще улавливаем запах TCA в вине. Иначе говоря, он не столько пишет ошибку в лог, сколько глушит сам логгер. Фрукт и цветы из вина никуда не делись — вы просто хуже их чувствуете.
Отсюда главная ловушка — маскировка. При слабом загрязнении запаха подвала может не быть вообще, вино просто кажется плоским и скучным. Гость решает, что вино «так себе», а перед ним 502, замаскированный под 204 No Content. Поэтому сравнить со второй бутылкой того же вина и того же года — самый надежный способ поймать такой баг прямо за столом.
Причем root cause не всегда в шлюзе: TCA и родственные соединения образуются, когда плесневые грибы перерабатывают хлорфенолы, а те встречаются не только в пробке, но и в древесине и других материалах винодельни. Классика: всю вину свалили на gateway, а проблема сидела в upstream.
А вот насколько часто это случается, сказать сложно: данные расходятся. Американский Cork Quality Council публикует результаты аудита входящих партий пробки: по данным на март 2023 года, 99% проверенных проб показывали выделяемый TCA ниже 1 нг/л. Родственный Natural Cork Council в последнем отчете приводит 99,4% на 25 тысяч анализов за год. Американский винный обозреватель Шон Салливан много лет ведет собственную статистику: на его профессиональных дегустациях 2023 года дефект нашелся у 2,6% вин под натуральной пробкой. Любой, кто работал с метриками, узнает ситуацию: считают разные люди, разными методами и с разными интересами.
Шаблон: баг-репорт на бутылку
Официанту YAML отправлять не нужно. Но как мысленная модель работает отлично.
Summary: Затхлый аромат, фрукт приглушен — [вино, год] Environment: Вино: [производитель, название, год урожая] Укупорка: [натуральная пробка / техническая / винтовая крышка] Открыто: [когда, сколько минут назад] Температура: [примерно] Бокал: [чистый, без запаха шкафа и моющего средства] Окружение: [парфюм, свечи, острая еда рядом — есть / нет] Steps to reproduce: 1. Налить около 50 мл в чистый бокал. 2. Вдохнуть аромат, не вращая. 3. Покрутить бокал 5–10 секунд, вдохнуть аромат снова. 4. Попробовать. 5. Налить во второй чистый бокал, повторить. 6. Если возможно,открыть вторую бутылку того же вина. Expected: чистый аромат, фрукт соответствует стилю. Actual: затхлый запах мокрого картона; во вкусе фрукт слабый, послевкусие короткое. Reproducibility: [оба бокала / только один / вторая бутылка чистая] Attachments: [фото этикетки и пробки]
Больше всего подсказок нам дает строка Reproducibility. Если посторонний запах есть во всех бокалах из одной бутылки, а вторая бутылка чистая, дело почти наверняка в конкретном экземпляре. Если он появился только в одном бокале, проверьте сам бокал. А если его воспроизводит каждая бутылка, то проблема либо серьезнее, чем казалось, либо это вовсе не дефект, а стиль, и тогда переписывать стоит уже Expected.
Статусы закрытия
Резолюции из Bugzilla ложатся на ресторанную практику почти без перевода:
FIXED — принесли новую бутылку, она чистая.
WORKSFORME — сомелье попробовал и дефекта не нашел. Не повод для конфликта: чувствительность к TCA у людей очень разная, и кто-то из вас двоих просто лучше откалиброван.
INVALID — это винный камень, задуманный стиль или полусладкое, которое заказали сами, хотя ждали сухое.
DUPLICATE — соседний стол уже пожаловался на это же вино.
WONTFIX — вино купили для коллекции и открыли через много лет, а в нем пробковый дефект. Выдержка тут ни при чем: баг был заложен еще при укупорке и просто ждал своего часа. Он подтвержден, но чинить его некому, а второй такой бутылки нет.
QA-дегустация для команды
Если хочется тимбилдинга, попробуйте слепую дегустацию с баг-репортами. Алкоголь не обязателен: чай, кофе, соки и безалкогольное вино подходят не хуже.
Поставьте пять-шесть напитков, закройте этикетки фольгой, раздайте карточки с одинаковыми полями.
Первый круг — только наблюдения: цвет, интенсивность аромата, сладость, кислотность, горечь, послевкусие. Угадывать сорт, цену и производителя не нужно.
Один напиток ведущий заранее «ломает»: зеленый чай, заваренный кипятком, выдохшаяся газировка, сок, разбавленный водой, кофе, простоявший час на подогреве — любая интересная «дичь».
Участники пишут на него баг-репорт по шаблону выше.
Лучшим считается репорт, по которому другой участник сможет воспроизвести поломку.
Если кто-то в итоге закроет тикет на чай со статусом 418 I'm a teapot, значит, все прошло правильно.
Хороший баг-репорт и хорошая дегустационная заметка устроены одинаково: наблюдение отдельно, гипотеза отдельно и со знаком вопроса, окружение описано, воспроизводимость проверена. И то и другое — приглашение разобраться вместе, что же случилось.
Если вино кажется странным, знать слово «трихлоранизол» необязательно. Честно признаюсь: за всю практику я слышала его на дегустациях всего пару раз, и то от химиков-технологов. Достаточно сказать, что вы чувствуете, чего ожидали и повторяется ли это во втором бокале. Дальше в дело вступает сомелье, так же, как разработчик, когда у него на руках нормальный тикет.
Хороший тикет ценят так же, как хорошее вино: за чистоту, ясность и долгое послевкусие. То есть за то, что по нему можно работать и через неделю, и через месяц.
Какой код ответа вы бы присвоили кофе из офисной кофемашины? Делитесь в комментариях своими баг-репортами на вино, кофе и чай.