Skip to content

convert SC loggers to ILogger #5000

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

Open
wants to merge 62 commits into
base: master
Choose a base branch
from
Open

Conversation

PhilBastian
Copy link
Contributor

No description provided.

@PhilBastian PhilBastian self-assigned this Jun 9, 2025
@PhilBastian PhilBastian changed the title convert audit loggers to ILogger convert SC loggers to ILogger Jun 18, 2025
PhilBastian and others added 15 commits June 19, 2025 09:24
…nder

# Conflicts:
#	src/ServiceControl.Infrastructure/LoggingSettings.cs
* convert SC transports from NServiceBus.Logging to Microsoft.Extensions.Logging

* remove signedassembly requirement so that infrastructure can be imported

* revert previous change and instead propogate signing back to servicecontrol.infrastructure

* fix signature of customisation classes that are dynamically created

* add ilogger to test services and remove direct construction with logger

* get tests to use ilogger

* Switch to .NET logging

* Work in progress

* Remove test code

* Improve logging format for storage space details

* Properly shutdown NLog in Program.cs

* Remove Seq logging and prepare for .NET logging migration

* Update LogLevel format

* Update LogLevel format in logging settings

* enable adding test logging provider as part of loggerutils and create framework for settings driven logger selection

* add ability to select logging provider from config

* handle setting not existing

* change logmanager logger factory to the standard one now used by the rest of SC

* ensure logger for transport tests

* domain events and persister loggers

* set default to nlog and pass loglevel to test context

* replace logmanager usage in persistence

* cleanup remaining references to LogManager

* missing files from last checkin

* fix different dependency version test failure

* move loggerutil setup before first static logger usage

* fix different dependency version test failure

---------

Co-authored-by: JasonTaylorDev <hello@jasontaylor.dev>
@PhilBastian PhilBastian requested a review from ramonsmits June 24, 2025 07:12
Copy link
Member

@ramonsmits ramonsmits left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job!

Some questions:

  • Why not OpenTelemetry OLTP exporter? I think this is even supported by Seq.
  • Ensure all loggers/providers are always flushed in finally
  • I think a bootstrap logger that is based on logging extensions would make sense.
  • As a lot of init is done only in "commands" where a hostbuilder is created any logger lifetimes there could be ended when that host instance gets disposed. If Seq/NLog its initialized and passed this can't result in lifetime issues
  • Seems that some log statements can benefit from logger scopes like OnMessagein the ingestioners, custom checks, etc. but maybe that that should not be part of this PR as its already HUGE
  • Do a search on ." as I saw many messages ending in .

@@ -44,15 +45,20 @@ public Task Invoke(ITransportReceiveContext context, Func<ITransportReceiveConte
{
context.Message.Headers.TryGetValue(Headers.MessageId, out var originalMessageId);
context.Message.Headers.TryGetValue(Headers.EnclosedMessageTypes, out var enclosedMessageTypes);
log.Debug($"Discarding message '{context.Message.MessageId}'({originalMessageId ?? string.Empty}) because it's session id is '{session}' instead of '{currentSession}' Message Types: {enclosedMessageTypes}.");
var logger = LoggerUtil.CreateStaticLogger<DiscardMessagesBehavior>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use the serviceprovider to resolve a logger?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this class is only used by tests and is always newed up, not resolved from the container

public override async Task<CheckResult> PerformCheck(CancellationToken cancellationToken = default)
{
var (isHighDirty, dirtyMemory) = await memoryInformationRetriever.GetMemoryInformation(cancellationToken);

Log.Debug($"RavenDB dirty memory value: {dirtyMemory}.");
logger.LogDebug("RavenDB dirty memory value: {DirtyMemory}.", dirtyMemory);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is I think a timer/schedule based task. Likely better to have a IServiceProvider injected that will create a logger scope per iteration

var message = $"There is a high level of RavenDB dirty memory ({dirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue.";
Log.Warn(message);
return CheckResult.Failed(message);
logger.LogWarning("There is a high level of RavenDB dirty memory ({DirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue.", dirtyMemory);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
logger.LogWarning("There is a high level of RavenDB dirty memory ({DirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue.", dirtyMemory);
logger.LogWarning("There is a high level of RavenDB dirty memory ({DirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue", dirtyMemory);

Log.Warn(message);
return CheckResult.Failed(message);
logger.LogWarning("There is a high level of RavenDB dirty memory ({DirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue.", dirtyMemory);
return CheckResult.Failed($"There is a high level of RavenDB dirty memory ({dirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
return CheckResult.Failed($"There is a high level of RavenDB dirty memory ({dirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue.");
return CheckResult.Failed($"There is a high level of RavenDB dirty memory ({dirtyMemory}). See https://docs.particular.net/servicecontrol/troubleshooting#ravendb-dirty-memory for guidance on how to mitigate the issue");

{
public override Task<CheckResult> PerformCheck(CancellationToken cancellationToken = default)
{
if (Logger.IsDebugEnabled)
if (logger.IsEnabled(LogLevel.Debug))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, this is a scheduled job. Consider a logger scope identifying an iteration

}
catch (Exception e)
{
Logger.Error("Failed to stop infrastructure", e);
logger.LogError(e, "Failed to stop infrastructure");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment for the OnMessage method below: Add logging scope :-)

Comment on lines 50 to 51
logger.LogInformation("Shutdown complete");
NLog.LogManager.Shutdown();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as before, ensure any loggers used are properly flushing

@@ -32,16 +30,14 @@ public virtual async Task HandleMessage(MessageContext message, IMessageDispatch
}
else
{
Log.WarnFormat("{0}: Can't find message body. Missing header ServiceControl.Retry.Attempt.MessageId", messageId);
logger.LogWarning("{MessageId}: Can't find message body. Missing header ServiceControl.Retry.Attempt.MessageId", messageId);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So... lets use a Logger scope instead of prefixing these with the message id?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logger scope doesn't print to file unless specified in the nlog layout string, which we don't want for the vast majority of log entries

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants