Skip to content
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

Nest dotted property names produced by [LogProperties] into structured objects #54

Open
bitbonk opened this issue Nov 20, 2023 · 4 comments

Comments

@bitbonk
Copy link

bitbonk commented Nov 20, 2023

Since .NET 6, the preferred way to log (according to Microsoft), is using the the LoggerMessageAttribute, which causes the source generation of a strongly typed log message. Quite often, the LogPropertiesAttribute is used with it, which will cause all properties of the object to be added as properties to the log.

A typical way to use this would look like this:

internal static partial class LogPropertiesExampleExtensions
{
    [LoggerMessage(LogLevel.Information, Message = "Example log of MyProps {MyProps}")]
    public static partial void LogMyProp(this ILogger logger, [LogProperties] MyProps myProps);
}

where MyProps is a complex object that looks like this (stolen from a Microsoft.Extensions unit test):

internal class MyProps
{
    public DateTime P0 { get; set; }
    public DateTimeOffset P1 { get; set; }
    public TimeSpan P2 { get; set; }
    public Guid P3 { get; set; }
    public Version? P4 { get; set; }
    public Uri? P5 { get; set; }
    public IPAddress? P6 { get; set; }
    public EndPoint? P7 { get; set; }
    public IPEndPoint? P8 { get; set; }
    public DnsEndPoint? P9 { get; set; }
    public BigInteger P10 { get; set; }
    public Complex P11 { get; set; }
    public Matrix3x2 P12 { get; set; }
    public Matrix4x4 P13 { get; set; }
    public Plane P14 { get; set; }
    public Quaternion P15 { get; set; }
    public Vector2 P16 { get; set; }
    public Vector3 P17 { get; set; }
    public Vector4 P18 { get; set; }
    public TimeOnly P19 { get; set; }
    public DateOnly P20 { get; set; }
    public Dictionary<string, object>? P21 { get; set; }
}

The problem now is, that there doesn't seem to be a way to expand all properties of the object (MyProps) in Seq (so that it appears as proper highlighted json).

When I log something like this

_logger.LogMyProp(new MyProps()
{
    P0 = DateTime.Now,
    P1 = DateTimeOffset.Now,
    P2 = new TimeSpan(1234),
    P3 = Guid.NewGuid(),
    P4 = new Version(1, 2, 3, 4),
    P5 = new Uri("https://www.microsoft.com"),
    P6 = IPAddress.Parse("192.168.10.1"),
    P7 = new IPEndPoint(IPAddress.Parse("192.168.10.1"), 42),
    P8 = new IPEndPoint(IPAddress.Parse("192.168.10.1"), 42),
    P9 = new DnsEndPoint("microsoft.com", 42),
    P10 = new BigInteger(3.1415),
    P11 = new Complex(1.2, 3.4),
    P12 = new Matrix3x2(1, 2, 3, 4, 5, 6),
    P13 = new Matrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16),
    P14 = new Plane(1, 2, 3, 4),
    P15 = new Quaternion(1, 2, 3, 4),
    P16 = new Vector2(1),
    P17 = new Vector3(1, 2, 3),
    P18 = new Vector4(1, 2, 3, 4),
    P19 = new TimeOnly(123),
    P20 = new DateOnly(2022, 6, 21),
    P21 = new Dictionary<string, object>()
    {
       ["DictP0"] = DateTime.Now,
       ["DictP1"] = DateTimeOffset.Now,
       ["DictP2"] = new TimeSpan(1234)
    }
});

Seq has all the expanded properties at the top level but the JSON of its values are just dumb strings (no highlighting no expand and collapse) and I don't see a way to make them expand:
image

If I remove the [LogProperties] attributes so that the top level properties are not added to the log entry, I also do not get any expansion at all:
image

Trying to add an @ to the property in the template like this

internal static partial class LogPropertiesExampleExtensions
{
    [LoggerMessage(LogLevel.Information, Message = "Example log of MyProps {@MyProps}")]
    public static partial void LogMyProp(this ILogger logger, MyProps myProps);
}

will give me the following compiler error:

[LOGGEN031] Logging method "LogMyProp" has template(s) that start with "@": @myprops (https://aka.ms/dotnet-extensions-warnings/LOGGEN031)

So as far as I can tell there doesn't seem to be any way to get the fully expanded object into Seq.
It would be very nice, if Seq could fully support the new way of logging with Microsoft.Extensions, if possible.
Note that I am currently not using Serilog as a logging provider for Microsoft.Extensions.Logging. Maybe there is a way to solve this problem if I would?

@nblumhardt
Copy link
Member

Thanks for raising this @bitbonk, needs some investigation, we'll dig into it 👍

@nblumhardt
Copy link
Member

HI @bitbonk; as far as we can tell, this is [LogProperties] functioning as intended; the message template's MyProps token is being filled with the ToString representation of the object, and the additional properties with dotted names are tacked on.

It doesn't seem like [LogProperties] is intended to function in the same manner as Serilog's @.

We might be able to improve ergonomics here using UnflattenDottedPropertyNames from Serilog.Sinks.Seq.

@nblumhardt nblumhardt changed the title Cannot expand objects Nest dotted property names produced by [LogProperties] into structured objects Sep 11, 2024
@bitbonk
Copy link
Author

bitbonk commented Sep 11, 2024

@nblumhardt Via an other issue (that involves log redaction using Microsoft.Extensions.Compliance.Redaction and Microsoft.Extensions.Telemetry) I have learned that there is a new way to expand everything: the Transitive property. For some reason it is marked as experimental though.

I also have not tested yet if the Transitive property plays nice with Seq. I suppose it should be logged in Seq as fully expanded objects (just as if I would have used "{@MyProps}").

@nblumhardt
Copy link
Member

@bitbonk thanks for the pointer, I'll take a look when I can 👍

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

No branches or pull requests

2 participants