You are doing .NET logging wrong. Let's fix it

You are doing .NET logging wrong. Let's fix it

Nick Chapsas

2 года назад

169,807 Просмотров

Ссылки и html тэги не поддерживаются


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

Nick Chapsas
Nick Chapsas - 06.01.2022 23:07

For those wondering, LoggerMessage.Define was left out intentionally because it's its own video coming soon-ish.

Ответить
Zephyr
Zephyr - 25.09.2023 20:32

Very helpful video. Thanks Nick!

Ответить
andreas gkizis
andreas gkizis - 04.07.2023 19:04

Amazing explanation, even I as a noob feel i got the gist of it
Thanks a ton again, cheers

Ответить
Andre Unsal
Andre Unsal - 06.06.2023 16:39

It would be great if you specified the decision developers need to make when implementing logging on an API, vs. a Server sln, vs. a Wasm sln etc.

Ответить
58yo Dota Player
58yo Dota Player - 25.05.2023 17:02

how do you implement dependency injection of ILogger into DurableTask.Core orchestrations and task activities?

Ответить
DAoC Nostalgia
DAoC Nostalgia - 22.04.2023 18:43

I think string interpulation works differently now, I’ve seen it turned into numbered templates as well as an object array

Ответить
Sultonbek Rakhimov
Sultonbek Rakhimov - 23.03.2023 00:15

Great video!

Ответить
Steve Haine
Steve Haine - 19.02.2023 21:10

Really intresting! This is something we have been dicussing in my work place projects. Before viewing this video we settled on using extension methods (IfTrace,IfDebug,IfInfo) and Null-conditional to implment single line logging: _logger?.IfDebug()?.Debug("Test message is: {0}, message); I would value your thoughts on this approach.

Ответить
Alexander Nava
Alexander Nava - 19.02.2023 15:19

I am using the Roslyn Analyzer to just insert the if statements around my log methods. So I don't have to have an adapter, and so stack traces are cleaner.

Ответить
Marshall Penn
Marshall Penn - 03.02.2023 15:43

"your going to be blinded in 3,2,1 now!" Ha ha ha

Ответить
lex Tr3
lex Tr3 - 31.01.2023 00:13

Is this still relevant currently? Kinda stupid if ms still havent optimize this in the box

Ответить
ThugLifeModafocah
ThugLifeModafocah - 31.12.2022 01:48

That's bad. Really bad. I just don't even remember how to use parameter approach instead of the modern string interpolation. Sad about this.

Ответить
NotACat
NotACat - 01.12.2022 03:37

Awesome video, but you doing logging wrong. All ms extenstions bullshit is bullshit and slow. Why? Because it doing wrong. Why? Because it pretend to general solution but actually can handle only stupid web app scenarios where speed is not a factor at all. Effective logging never can be done via virtual call. Period.

Ответить
Bartłomiej Ciurla
Bartłomiej Ciurla - 28.11.2022 15:47

Great video. Thanks!

Ответить
Kuba
Kuba - 20.11.2022 12:40

out of infinte possibilities of numbers in the spectrum he chooses 69 and 420, you got my respect @NickChapsas

Ответить
Willy Barankin
Willy Barankin - 16.11.2022 11:41

Wandering why microsoft didn't place generic overloads right in ILogger. "Six parameters is enough for all! If you want more use unoptimised LogInfoWeird with params array"

Ответить
Anup Prabhu
Anup Prabhu - 10.09.2022 10:34

Thanks

Ответить
Sagar Chowdhury
Sagar Chowdhury - 31.08.2022 21:49

Hi Nick it's a great video. Do you have any source code where you broadly used Serilog. I want to implement Serilog in my learning project.

Ответить
Dave B
Dave B - 28.08.2022 05:04

Hey Nick, really appreciate your work.

Doing some reading and StackOverflow tells me that string interpolation turns into string.Format() at run time, therefore shouldn't performance be the same between the two?

Thanks.

Ответить
Sm WnL
Sm WnL - 26.07.2022 07:19

Thanks

Ответить
Ayoub Dkhissi
Ayoub Dkhissi - 13.07.2022 19:39

This is very important, specially in production!! thank you!

Ответить
Raman
Raman - 12.07.2022 12:23

You sad not use string interpolation via _loger.LogInformation( $" xxx {parameter} yyy ") in loggin because string will be allocated every time.
Was it fixed in C# 10 and CORE 6.0 ?

Ответить
sebastian rafalko
sebastian rafalko - 15.06.2022 00:11

Dziękujemy.

Ответить
nolan collet
nolan collet - 13.06.2022 15:50

123K Subs.. :)

Ответить
Mikarsoft Official
Mikarsoft Official - 13.06.2022 13:25

ωραίος!

Ответить
Max Bradley
Max Bradley - 10.06.2022 01:14

Interesting video. However I'm not sure I understood your point about using the generic arguments vs the params array. In these two cases both loggers had an if enabled check around them and the params one took 4ns and the generics one took 9ns. You said that this time difference does not matter (sure its tiny) and that the fact the generics one did not use memory makes up for this. However the params one did not use memory either. So as the params one was faster, why is it not preferred?

Ответить
Rpc Technology
Rpc Technology - 08.06.2022 11:24

Whats this obssession with the 69 number 😂👍

Ответить
Manuel Eduardo Gonzalez
Manuel Eduardo Gonzalez - 01.06.2022 05:33

I always thought that logging, as is a I/O task (when saving to a file or a db), it would be better to perform it on a different thread. Something simple like Task.Parallel(DoLog()), that way the execution flow will continue and it's not waiting for the I/O task to be complete.

Ответить
lordofentropy
lordofentropy - 31.05.2022 23:57

"Throw in a couple random things..." uses 69 and 420 "random" indeed. 😆

Ответить
Tom WoB
Tom WoB - 22.05.2022 11:08

Great stuff Nick. But why is this not already build-in in the .NET Logger Class??? 🧐

Ответить
Todor Todorov
Todor Todorov - 17.05.2022 10:15

69 and 420 😎

Ответить
Gabriel Silva Moreira
Gabriel Silva Moreira - 16.03.2022 17:47

i don't do logging hahahaha

Ответить
Anders Nielsen
Anders Nielsen - 14.03.2022 19:22

Upvote for double blind Nick Chapsas! Long days in the office? Remember to take care of yourself!

Ответить
Arnþór Hjaltason
Arnþór Hjaltason - 10.03.2022 19:12

One problem with your demonstration here, you don't account for optimization.
If you build a for-loop that only has if false in it, it will simply get optimized away, this is why you some things like 100000 faster execution with the if.
This is a situation that is almost impossible to encounter since when would you log a variable that is created in the logger call.
To fix this assign the variable before you do the check for the log level, this would simulate your original case from the Controller.

But other than that a very good video, was very surprised moving from Serilog to Log4net that this was not implemented.
Good usage of dotTrace as well.

Ответить
Rolf
Rolf - 03.03.2022 23:11

Can you make a video like "evolution of how to declare a property"?
I would like to show my colleagues all the ways they have available to declare a property.

Ответить
Jón Hjörtur Brjánsson
Jón Hjörtur Brjánsson - 20.02.2022 02:52

I'm not doing .NET logging at all!

Ответить
Wasmannia Auropunctata
Wasmannia Auropunctata - 31.01.2022 18:52

Thanks! This is great stuff. Also, I kind of like your choice of numbers..

Ответить
Gray Beland
Gray Beland - 28.01.2022 17:18

If your benchmark is pure logging calls it distorts the impact of logging. In a real world app that actually does work and if the logging is 0.5% performance hit - do we care?

Ответить
Arthur Guerra
Arthur Guerra - 27.01.2022 00:11

"So, lets just have a couple of random things over here"... adds "69" and "420"... nice to know I'm not alone lol

Ответить
Jay Wren
Jay Wren - 22.01.2022 22:30

Which logging library is this? Seems like a good reason to use a better logging library with better method overloads which pass without that dynamic array, at least for majority use cases.

Ответить
Peter Riesz
Peter Riesz - 21.01.2022 15:30

Apart from the performance gain templates allows logging providers to implement semantic or structured logging. We use sentry to capture warnings and errors. It will create tags for each of the arguments. It also uses the message tempate without all the noise from the arguments to group the logs. It makes the logs much easier to navigate.

Ответить
IsSeMi
IsSeMi - 21.01.2022 11:20

Thank you for the video. I've never thought the built-in logger is so inefficient.

Ответить
Filip Vestergaard
Filip Vestergaard - 21.01.2022 09:44

Do you know if the time measured in the benchmark is including the time used for garbage collection?

Ответить
fabio lonegro
fabio lonegro - 21.01.2022 01:40

Hey Nick, good material as always.

Coming back to the actual performances, I think you may try something like (sorry for the formatting, I didn't use an IDE 😊):



public class LoggerAdapterImproved<T> : ILoggerAdapter<T>
{

private readonly Action<string> _logAction0;
private readonly Action<string, string> _logAction1;
private readonly ILogger<T> _logger;

public LoggerAdapterImproved(ILogger<T> logger)
{
_logger = logger;
if (logger.IsEnabled(LogLevel.Information))
{
_logAction0 = _ => _logger.LogInformation(_);
_logAction1 = (_, __) => _logger.LogInformation(_, __);
}
else
{
_logAction0 = _ => { };
_logAction1 = (_, __) => { };
}

}

public void LogInformation(string message)
=> _logAction0(message);

public void LogInformation(string message, string replace1)
=> _logAction1(message, replace1);
}

Clearly, it doesn't take into account the possibility of changing the log level at runtime, but I usually prefer an 'immutable' approach.

With this setup constantly get a 3.5x faster implementation, still preserving the testability.

Keep going and send a hug to my friend Stefano G 😉

Ответить