-
-
Notifications
You must be signed in to change notification settings - Fork 940
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace DiagnosticAbstration with Microsoft.Extensions.Logging.Abstractions #1509
Conversation
I think it's the right way to go. The static init seems reasonable given the prior art in other libraries. I don't think the source generator is necessary (definitely tedious). Wrt the new dependency, we can always merge after the next release (hopefully soon) so there is not a big wave of dependencies in one release |
generate the hex string once instead of every log call and optimize ToHex().
I just realized that this PR actually introduces new So I optimized this to only call |
Co-authored-by: Rob Hague <[email protected]>
It looks good but I think the 'info' level is too verbose. I don't think we need an info log for each packet we send or receive, it creates a lot of logs for a simple connect+download test Would you mind reviewing the logs/levels and paring them back where it seems sensible? I know everything was already 'info', but it was only in debug builds and not shipped in the package For reference, packet send/receive logs are only visible under |
You're right, I hadn't really thought about the levels. I made the following changes:
Obviously all up for debate, feel free to suggest or make changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, all seems sensible, I just tweaked a bit
{ | ||
_logger.LogDebug("[{SessionId}] Sending message '{MessageType}' to server: '{Message}'.", SessionIdHex, message.GetType().Name, message); | ||
_logger.LogTrace("[{SessionId}] Sending message {MessageName}({MessageNumber}) to server: '{Message}'.", SessionIdHex, message.MessageName, message.MessageNumber, message.ToString()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed it to output e.g. "Sending message SSH_MSG_NEWKEYS(21)" as it is helpful to see the number as well. It is a bit duplicative atm because most messages include the message name in the ToString
also I added explicit ToString
on the message in case e.g. a json logger would dump all the properties of the message. trying to strike a balance between useful information and private session information
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, wondering if logger.BeginScope would have a valid use for tagging the SessionId to logs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a scope for SessionId would make sense. A logging scope is based on an AsyncLocal though, so the BeginScope would have to be called in quite a few places.
This replaces the
DiagnosticAbstraction
withMicrosoft.Extensions.Logging.Abstractions
and allows consuming applications to pass their ownILoggerFactory
to SSH.NET.I don't expect this to be merged as is since there are a few things worth discussing:
Why do this?
Because it is the de-facto standard for modern and structured logging in .NET and allows consuming applications to easily integrate SSH.NET into their own logging. This also means users can more easily provide log messages in issues.
Also the currently used Trace API is pretty much considered obsolete.
Injecting ILoggerFactory vs static instance
The imho best way to implement this would be to add an
ILoggerFactory
to the public constructors. The problem is that passing this through all the constructors and down to all the layers is quite a lot of work. I actually tried this and finally gave up when I realized that the logging inKeyExchange.cs
meant that theConnectionInfo
constructors would also need anILoggerFactory
(because of theKeyExchangeAlgorithms
dictionary).So I opted for a static configuration class, similiar how Npgsql handles this. Imho this is "good enough" since having multiple
ILoggerFactory
instances in an application sounds like quite a niche use case.Applications simply have to call
SshNetLoggingConfiguration.InitializeLogging(loggerFactory);
before using SSH.NET.Compile-time logging source generation
While this implementation already allocates less than the old one (because it doesn't create the full string unless logging is enabled), things could be further improved with the LoggerMessage attribute. This would mean even better performance, but it also means writing a method for every single log message, which can be quite tedious. I would be fine with doing this, but decided to not bother unless it is decided to use it.
There are also quite a few unneccessary allocation because of the usage of
Session.ToHex()
. I didn't change this here since it could be optimized separately (even without this PR being merged).New dependency
This obviously adds a new dependency to
Microsoft.Extensions.Logging.Abstractions
to SSH.NET (the.Logging
andConsole
packages are only for the tests) . Imho this is not really an issue. This library is as minimal as it gets and most applications already pull this is in anyway, either directly or by another dependency needing it (ASP.NET Core requires it for example).