Cysharp / ZLogger

Zero Allocation Text/Structured Logger for .NET with StringInterpolation and Source Generator, built on top of a Microsoft.Extensions.Logging.
MIT License
1.11k stars 79 forks source link

Recommendation for Caller* attributes #140

Closed Rurouni closed 5 months ago

Rurouni commented 5 months ago

Hello,

I am trying to switch some of our code to ZLogger, but we have methods like

public static void Debug(
            string format, 
            object arg0, 
            object arg1,
            object arg2,
            CallerArgsGuard nextParamsAreAlwaysDefaults = default,
            [CallerFilePath] string path = null,
            [CallerLineNumber] int line = 0,
            [CallerMemberName] string method = null)
        {

Is there some way to optionally include Caller location data while preserving ZLog methods alloc efficiency? The only idea I had was to use LogScopes to include extra caller properties and then do extra formatting via SuffixFormatter

Thank you

Rurouni commented 5 months ago

Example of what I am currently doing:

[UnityEngine.HideInCallstack]
    public static void Debug(
        this ILogger logger,
        [InterpolatedStringHandlerArgument("logger")] ref ZLoggerDebugInterpolatedStringHandler message, 
        UnityEngine.Object gameObject,
        [CallerFilePath] string path = null,
        [CallerLineNumber] int line = 0,
        [CallerMemberName] string method = null)
    {
        if (logger.IsEnabled(LogLevel.Debug))
        {
            using var x = logger.BeginScope("{Caller}",Log.FormatCallerInfo(path, line, method));
            logger.ZLogDebug(ref message, gameObject);
        }
    }

and then in PlainTextFormatter:

y.SetSuffixFormatter($"{0}", (message, info) =>
{
    var sb = new StringBuilder();
    if (info.ScopeState is { IsEmpty: false })
    {
        foreach (var pair in info.ScopeState.Properties)
        {
            if(pair.Key == "{OriginalFormat}")
                continue;
            sb.AppendLine();
            sb.Append("| ");   
            sb.Append(pair.Key);
            sb.Append(":");
            if (pair.Value is StringValues stringValues)
                sb.Append(stringValues.ToString());
            else
                sb.Append(pair.Value);
        }
        message.Format(sb.ToString());
    }
}
neuecc commented 5 months ago

I had considered including them in LogInfo, but abandoned the idea due to compatibility issues with Source Generator. However, by handling them as string?, int?, string? in LogInfo and making them optional in Source Generator, it seems possible to implement this without any issues. Therefore, I'd like to consider adding them to the standard Log method.

neuecc commented 5 months ago

I've released 2.3.0, it includes this feature.