Здравствуйте, Sharov, Вы писали: S>Т.е. в яве она пытается зачем-то вычислить $"{some_expr}" при том, что some expr это просто строка? Если да, тогда S>все ясно и это очень странно. В шарпе это тоже возможно, но явно $"{fn()}". S>Вопрос -- а как они в яве тогда отличают обычные строки от необычных, анализируют что-то? S>Как они понимают, что тут надо просто подставить значение, а тут надо jndi чего-то там?
Всё просто: в java никакой интерполяции нет. Поэтому библиотекам типа log4j2 приходится велосипедить свою интерполяцию.
А в неё приходит просто строка — и хрен её знает, какие части строки приехали от разработчика, а какие — от пользователя.
S>Это как? Интерполяция -- это подстановка вычисления в строку.
Ну вот так. В C# сначала будет делаться интерполяция, а потом — конкатенация. А в java — наоборот: сначала конкатенация, а интерполяция — уже потом.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Sharov, Вы писали: S>>Т.е. в яве она пытается зачем-то вычислить $"{some_expr}" при том, что some expr это просто строка? Если да, тогда S>>все ясно и это очень странно. В шарпе это тоже возможно, но явно $"{fn()}". S>>Вопрос -- а как они в яве тогда отличают обычные строки от необычных, анализируют что-то? S>>Как они понимают, что тут надо просто подставить значение, а тут надо jndi чего-то там? S>Всё просто: в java никакой интерполяции нет. Поэтому библиотекам типа log4j2 приходится велосипедить свою интерполяцию. S>А в неё приходит просто строка — и хрен её знает, какие части строки приехали от разработчика, а какие — от пользователя.
Теперь все понятно, а то я думал, что там нечто похожее на шарп, а это просто библиотека. Т.е. без
поддержки компилятора.
Здравствуйте, ·, Вы писали: S>>Ну, при должной обработке в логе так и будет someStuff.RequestId, someStuff.State. ·>У меня в уме какое-то разделение — логи должны быть для людей с ролью поддержки, т.е. их явно формируешь для читабельности. Экспозить имена локальных переменных, которые для читабельности кода, люди с ролью программиста — так себе... Другими словами, логи должны описывать что делается, а не как. Притом, когда я рефакторю код, обычно логгирование оставляю неизменным.
Конкретно в этом примере используется структурное логгирование. Там вся идея — как раз в том, чтобы одновременно иметь машино- и человеко-читаемые логи. Имена переменных там вообще человеку не нужны.
Они нужны той читалке, которая на основе шаблона и данных на лету сформирует строку, которую прочтёт человек (если ему надо).
А структурированное представление позволяет делать всякие модные вещи типа кибаны, которая умеет фильтровать логи по их данным.
S>>Если второе, то как logback решает проблему безопасности? ·>В самой идее интерполяции, точнее в дизайне "фичи" сделать её рекурсивной. Сейчас поигрался, т.е. log.info("Hello {}", "abc${env:VALUE}efg"), где VALUE=123${env:VALUE2}456, VALUE2=XYZ будет раскрывать ${} до конца: ·>
·>Т.е. как я понял, кому-то это показалось гениальной супер-полезной фичей... и никто не подумал, что это хрень какая-то, да ещё и дырища... ·>Если подумать... как вообще кому-то в голову такое могло прийти <10 лет назад??! И это в ИТ-индустрии наученной SQL-инъекциями... ·>Одно оправдывает. Этот подход часто используется в конфигурационных файлах и там оно действительно полезно. Но конфиги — таки доверяемый код. Короче, запилили фичу "как у всех" не подумав.
Вот реально реальный пинцет.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>·>У меня в уме какое-то разделение — логи должны быть для людей с ролью поддержки, т.е. их явно формируешь для читабельности. Экспозить имена локальных переменных, которые для читабельности кода, люди с ролью программиста — так себе... Другими словами, логи должны описывать что делается, а не как. Притом, когда я рефакторю код, обычно логгирование оставляю неизменным. S>Конкретно в этом примере используется структурное логгирование. Там вся идея — как раз в том, чтобы одновременно иметь машино- и человеко-читаемые логи. Имена переменных там вообще человеку не нужны. S>Они нужны той читалке, которая на основе шаблона и данных на лету сформирует строку, которую прочтёт человек (если ему надо). S>А структурированное представление позволяет делать всякие модные вещи типа кибаны, которая умеет фильтровать логи по их данным.
Это понятно. Я имею в виду, что писать в логи имена локальных переменных/полей класса — сомнительная фича. Т.е. кишки конкретной реализации выползают наружу во внешние системы. Лучше явно формировать логгируемую структуру отдельно, с явно заданным именованием полей. Иначе небольшой рефакторинг переименования локальной переменной вдруг внезапно ломает какой-нибудь отчёт в кибане.
S>·>Одно оправдывает. Этот подход часто используется в конфигурационных файлах и там оно действительно полезно. Но конфиги — таки доверяемый код. Короче, запилили фичу "как у всех" не подумав. S>Вот реально реальный пинцет.
Угу. Более того, тут целый набор пинцетов. Вроде каждая из "фич" не такая уж идиотская, а комбинация всего вместе привела к легко эксплуатируемому RCE.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, netch80, Вы писали:
N>ещё и форматтеры могут иметь специфику в зависимости от стиля назначения. N>Подход в твоём примере выполняет форматирование (интерполяцию) всегда
Поэтому в шарпе до 10 версии интерполяция в выводе в лог крайне не рекомендуется (и есть анализаторы, которые это ловят). Там немного другая история используется, немного докрученный string.format
logger.LogTrace("Processing the message: '{message}'", request.Message);
Но тут тоже есть проблема — парсинг, который для трейса тоже неприемлемо долгий. Поэтому там унутре неонка кеш с лимитированной длиной. Покуда у тебя сами шаблончики только в коде — все прекрасно. А вот если ты и шаблончики генерируешь динамически — кешик быстро переполняется. Чтобы этого избежать есть другой костыль:
_message = LogMessage.DefineTrace<Message>("Processing the message: '{message}'");
...
_message(request.Message);
Ну и, наконец, в последнем шарпе задачку парсинга и создания специализированной версии логгера можно поручить компилятору, тогда просто пишешь как у Синклера в примере, а дальше оно все само разгребает на основании типов в методах логгера.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>·>У меня в уме какое-то разделение — логи должны быть для людей с ролью поддержки НС>Во всех видимых мною облачных проектах логи читали и разработчики, и тестеры, и девопсы, и поддержка.
Разработчики/етс тоже могут исполнять роль поддержки.
Я имел в виду, что логи пишутся для других людей, которые их будут читать и нередко они не знают о коде. Поэтому логи в первую очередь надо оформлять для людей, а не тупо вываливать дампы кода, интересные только разработчикам.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
НС>>Во всех видимых мною облачных проектах логи читали и разработчики, и тестеры, и девопсы, и поддержка. ·>Разработчики/етс тоже могут исполнять роль поддержки.
И? Как из этого следует бесполезность имен переменных? Разработчик при просмотре логов мгновенно забывает про свой код?
·>Я имел в виду, что логи пишутся для других людей, которые их будут читать и нередко они не знают о коде.
Ну так не надо называть переменные x y z (и var в шарпе это активно стимулирует), тогда и польза от их имен будет не только разработчикам.
И еще один момент — не стоит рассматривать все эти вещи в отрыве от structured logging. А для него нужны имена полей. И в качестве таковых отлично подходят названия локальных переменных. И если принять за правило такое равенство, то код очень существенно сокращается и упрощается убиранием лишних сущностей.
·> Поэтому логи в первую очередь надо оформлять для людей, а не тупо вываливать дампы кода, интересные только разработчикам.
Еще раз — присутствие имен переменных вовсе не означает "тупо вываливать дампы кода".
Здравствуйте, Sharov, Вы писали:
S>На сколько я понимаю, причина тут совсем не в интерполяции, а в lookup и jndi. Т.е. множество случаев срабатывает,
Нет, причина тут в том, что, во-первых, они за каким то фигом решили позволить слишком много делать в форматной строке, включая обращения к внешним ресурсам (скорее всего по причине реюза предназначенной для другого библиотеки, где подобная фича была вполне к месту), а затем еще и применили эту фичу к динамическим параметрам. Вот наложение этих двух неудачных решений и привело к феерической дыре.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>>Во всех видимых мною облачных проектах логи читали и разработчики, и тестеры, и девопсы, и поддержка. НС>·>Разработчики/етс тоже могут исполнять роль поддержки. НС>И? Как из этого следует бесполезность имен переменных? Разработчик при просмотре логов мгновенно забывает про свой код?
В процессе разработки лично я редко читаю логи, слишком сложно. Тесты же есть. Дебаггер, на крайняк.
Так что смотрю логи я обычно где-то в проде когда-то через год. А код с которым не работаю я забываю за считанные недели.
НС>·>Я имел в виду, что логи пишутся для других людей, которые их будут читать и нередко они не знают о коде. НС>Ну так не надо называть переменные x y z (и var в шарпе это активно стимулирует), тогда и польза от их имен будет не только разработчикам.
Я, как разработчик, называю переменные так как мне, разработчику, удобно в данном конкретном блоке кода. А не так как должно быть понятно тестерам, девопсам, мне-через-год.
НС>И еще один момент — не стоит рассматривать все эти вещи в отрыве от structured logging. А для него нужны имена полей. И в качестве таковых отлично подходят названия локальных переменных. И если принять за правило такое равенство, то код очень существенно сокращается и упрощается убиранием лишних сущностей.
Нет, не подходят локальные переменные. Локальные переменные про то, _как_ код что-то делает. А логи про то, _что_ код делает. И никого, кроме разработчиков, локальные переменные не должны беспокоить.
С>·> Поэтому логи в первую очередь надо оформлять для людей, а не тупо вываливать дампы кода, интересные только разработчикам. НС>Еще раз — присутствие имен переменных вовсе не означает "тупо вываливать дампы кода".
Именно оно. Локальные переменные это проблема конкретного блока кода, и не обязательно это показывать тестерам-девопсам.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
НС>>И? Как из этого следует бесполезность имен переменных? Разработчик при просмотре логов мгновенно забывает про свой код? ·>В процессе разработки лично я редко читаю логи, слишком сложно.
Ну лично ты может и так, а мой опыт говорит, что бывает и по другому.
·> Тесты же есть. Дебаггер, на крайняк.
Тесты все не ловят. А в дебагере надо проблему еще и воспроизвести. Поэтому, когда что то случается на проде, все начинается с логов. А потом уже тесты с дебагером.
·>Я, как разработчик, называю переменные так как мне, разработчику, удобно в данном конкретном блоке кода.
Ты один владеешь кодом? Если нет, то называть надо не как тебе удобно, а как понятнее для тех кто твой код будет читать.
НС>>И еще один момент — не стоит рассматривать все эти вещи в отрыве от structured logging. А для него нужны имена полей. И в качестве таковых отлично подходят названия локальных переменных. И если принять за правило такое равенство, то код очень существенно сокращается и упрощается убиранием лишних сущностей. ·>Нет, не подходят локальные переменные. Локальные переменные про то, _как_ код что-то делает. А логи про то, _что_ код делает.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>>И? Как из этого следует бесполезность имен переменных? Разработчик при просмотре логов мгновенно забывает про свой код? НС>·>В процессе разработки лично я редко читаю логи, слишком сложно. НС>Ну лично ты может и так, а мой опыт говорит, что бывает и по другому.
Даже если у тебя отличная память... тут же возникает тот же вопрос: Ты один владеешь кодом?
НС>·> Тесты же есть. Дебаггер, на крайняк. НС>Тесты все не ловят.
Причём тут это? Мы тут вроде говорим логи vs тесты. Логи что-ли всё ловят?! По моему опыту тесты ловят больше.
НС>А в дебагере надо проблему еще и воспроизвести.
Я стремлюсь к тому, чтобы можно было воспроизвести проблему путём копипасты данных из логов в тест. И тест уже дебажим.
НС>Поэтому, когда что то случается на проде, все начинается с логов. А потом уже тесты с дебагером.
У меня, как правило, на проде что-то случается непонятное когда код уже благополучно написан и забыт.
НС>·>Я, как разработчик, называю переменные так как мне, разработчику, удобно в данном конкретном блоке кода. НС>Ты один владеешь кодом? Если нет, то называть надо не как тебе удобно, а как понятнее для тех кто твой код будет читать.
Я как раз и намекаю на то, что кодом владеют разработчики. Они и будут читать и беспокоиться о именовании локальных переменных. А логи читают тестеры-девопсы, им пофиг на локальные переменные и то как устроен код.
НС>>>И еще один момент — не стоит рассматривать все эти вещи в отрыве от structured logging. А для него нужны имена полей. И в качестве таковых отлично подходят названия локальных переменных. И если принять за правило такое равенство, то код очень существенно сокращается и упрощается убиранием лишних сущностей. НС>·>Нет, не подходят локальные переменные. Локальные переменные про то, _как_ код что-то делает. А логи про то, _что_ код делает. НС>Можно примеры? А то понять тебя сложно о чем ты.
Вот такой псевдокод с захватом структуры с именем переменной в логгере:
var orderId = orderRequest.orderId;
var order = loadOrder(orderId);
log.info($"Processing {orderId}"); //вроде красиво, да.
doThis(order);
doThat(order);
порефакторили немного, стало
var orderInfoWrapper = loadOrderWithInfo(orderRequest);
log.info($"Processing {orderInfoWrapper.order.id}"); //wtf?!
doThis(orderInfoWrapper);
doThat(orderInfoWrapper);
Ведь девопспам пофиг как у меня устроен код, как и когда я, как разработчик, хочу его рефакторить. Им главное возможность поискать логи по данному order id вне зависимости от действий разработчиков. В этом и основная цель структурного логгирования.
Здравствуйте, ·, Вы писали:
НС>>Ну лично ты может и так, а мой опыт говорит, что бывает и по другому. ·>Даже если у тебя отличная память... тут же возникает тот же вопрос: Ты один владеешь кодом?
Нет.
НС>>·> Тесты же есть. Дебаггер, на крайняк. НС>>Тесты все не ловят. ·>Причём тут это?
При том что иногда проблемы вылазят на проде.
·>Мы тут вроде говорим логи vs тесты.
Разве?
·> Логи что-ли всё ловят?!
А они должны ловить все?
НС>>А в дебагере надо проблему еще и воспроизвести. ·>Я стремлюсь к тому, чтобы можно было воспроизвести проблему путём копипасты данных из логов в тест.
Т.е. подробная инфа, включая имена локальных переменных в логах таки нужна?
НС>>Ты один владеешь кодом? Если нет, то называть надо не как тебе удобно, а как понятнее для тех кто твой код будет читать. ·>Я как раз и намекаю на то, что кодом владеют разработчики. Они и будут читать и беспокоиться о именовании локальных переменных.
И почему вдруг у них имена будут такими, что не подходят для названий полей в логе?
·>log.info($"Processing {orderInfoWrapper.order.id}"); //wtf?!
Ну и зачем убирать локальную переменную?
·>Лучше писать ·>
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>>>Ну лично ты может и так, а мой опыт говорит, что бывает и по другому. НС>·>Даже если у тебя отличная память... тут же возникает тот же вопрос: Ты один владеешь кодом? НС>Нет.
Т.е. когда ты читаешь логи чужого кода, имена локальных переменных тебя не должны волновать. Ты их всё равно не знаешь.
НС>·>Причём тут это? НС>При том что иногда проблемы вылазят на проде.
И чем тебе локальные переменные помогут?
НС>·>Мы тут вроде говорим логи vs тесты. НС>Разве?
Да. Напомню контекст: "В процессе разработки лично я редко читаю логи, слишком сложно. Тесты же есть.". А ты о чём говоришь?
НС>·> Логи что-ли всё ловят?! НС>А они должны ловить все?
Нет. Как и тесты. К чему ты тогда вопрос-то задавал?
НС>>>А в дебагере надо проблему еще и воспроизвести. НС>·>Я стремлюсь к тому, чтобы можно было воспроизвести проблему путём копипасты данных из логов в тест. НС>Т.е. подробная инфа, включая имена локальных переменных в логах таки нужна?
Инфа нужна. Локальные переменные прод кода не нужны. Их и в коде теста нет и быть не может.
НС>>>Ты один владеешь кодом? Если нет, то называть надо не как тебе удобно, а как понятнее для тех кто твой код будет читать. НС>·>Я как раз и намекаю на то, что кодом владеют разработчики. Они и будут читать и беспокоиться о именовании локальных переменных. НС>И почему вдруг у них имена будут такими, что не подходят для названий полей в логе?
Потому что могут. Почему они непременно обязаны быть подходящими?
НС>·>log.info($"Processing {orderInfoWrapper.order.id}"); //wtf?! НС>Ну и зачем убирать локальную переменную?
Специально оставить её чисто для лога? И как ты защитишь её от рефакторинга переименования, например? Я ведь это не вручную мог сделать, а натравить IDE поменять мне всё. Т.е. код слегка порефакторил и незаметно поломал отчёт у девопсов. Гы.
НС>·>Лучше писать НС>·>
НС>Чем лучше то? По мне так хуже и сильно.
Тем, что явно. "orderId" это имя поля во внешней системе, изменение которого имеет последствия, а не локальная переменная.
Более того внезапно можно структуры шарить и комбинировать и передавать между частями кода:
var orderLogParam = logParam("orderId", orderInfoWrapper.order.id);
...
var userLogParam = logParam("userId", user.id);
...
log.info("Order cancelled by user", orderLogParam, userLogParam);
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
НС>>Нет. ·>Т.е. когда ты читаешь логи чужого кода, имена локальных переменных тебя не должны волновать.
Почему? В нашем коде они вполне осмысленны и понятны даже если сам код я не видел. Это не говоря уж о том, что мне, по долгу работы, приходится смотреть большую часть кода. Но даже если я его не видел — я ведь могу, для первичной диагностики, залезть в реп и поглядеть.
А вот ты какое то окукливание разработчиков тут описываешь, вроде сферического коня в вакууме. Типа работают они ночью в темной комнате, и даже маленького лучика из под двери не пробивается.
НС>>·>Причём тут это? НС>>При том что иногда проблемы вылазят на проде. ·>И чем тебе локальные переменные помогут?
Например я могу увидеть какое то странное значение у них, а потом поиском по этому конкретному значению понять откуда оно взялось и не повторялось ли еще до этого.
НС>>·> Логи что-ли всё ловят?! НС>>А они должны ловить все? ·>Нет. Как и тесты. К чему ты тогда вопрос-то задавал?
Я же уже ответил. То что пропустили тесты вылазит на проде. И вот тут то ты начинаешь читать логи.
НС>>И почему вдруг у них имена будут такими, что не подходят для названий полей в логе? ·>Потому что могут.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[3]: Java безопасна, не то, что Си и C++ говорили...
Здравствуйте, netch80, Вы писали:
N>Ну так SQL injection известно в первую очередь из "безопасного" PHP.
А где его безопасным объявляли, если не секрет? Ну и ты лукавишь, когда пишешь про ПХП: ему просто так повезло — стать самым распространенным языком для сайтов в те времена, когда не было ни хороших практик, ни библиотек для изоляции пользовательских параметров. Займи его место любой другой — и те же проблемы ловили бы в нем.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.