-
Notifications
You must be signed in to change notification settings - Fork 797
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
Top-level byte array isn't destructured, but other byte sequences are #1954
Comments
I think your second statement:
isn't calling the overload of Let me know if this helps :-) |
No, that's not it. Here is a modification to the repro that uses multiple values, thereby avoiding that ambiguity. The output is the same as the original example. Log.Information("Byte {Kind}: {@Data}", "list", List([ 1uy ]))
Log.Information("Byte {Kind}: {@Data}", "array", [| 1uy |]) |
🤔 hmmmmmm... I think then it will be that byte arrays are processed as scalars (converted to hex strings): https://github.com/serilog/serilog/blob/dev/src/Serilog/Capturing/PropertyValueConverter.cs#L68 but other enumerable types ( https://github.com/serilog/serilog/blob/dev/src/Serilog/Capturing/PropertyValueConverter.cs#L174 I don't think it's likely to be a bug per se, just the outcome of different types being processed differently - not sure whether/where we'd make any changes to enable a different approach, but if you're able to share some more info about your scenario/preferences it'd be good data to have. Thanks! |
The repro uses
Certainly! Destructuring per se doesn't help me, so I don't use that. In fact, it would actively hurt me, at least in the first case below.
In both of these cases, the only thing that matter to me is the log message. I therefore simply want the rendered log message to be as nicely formatted as possible. To achieve this, I am serializing most values using custom settings, so they are easy to read. (I used JSON first, but recently switched to YAML because it's even easier to read.) I use this not only for complex objects, but also single-case discriminated unions ("wrapped primitives"), which are unwrapped using my serialization settings. In general, no matter what I serialize using my "log JSON setting", the output is either better or the same, never worse. Of course, relative to other performance costs of logging, serialization is a heavy hitter. I used to serialize synchronously and insert the string directly into the log message ( I have not found any other way to accomplish 1) nice custom-formatted complex objects in log messages, and 2) not serializing for disabled log levels. In terms of this issue, the point is that this destructuring-based approach works wonderfully for everything except byte arrays. Specifically, I'd like to represent them with spaces between the bytes, like |
Thanks for taking the time to write that! 👍 I've never been entirely comfortable with our opinionated byte array formatting - the current system came about though because treating byte arrays as lists of bytes was ...... problematic to say the least 😅 ... so something (useful) needed to be done. Unfortunately, byte arrays are something of an anomaly; most/all "scalar" types Serilog cares about are structs/value objects, which have copy semantics and so can be passed as-is through to the asynchronous side of the logging pipeline, or in the case of In the past we've considered making Depending on how much control you have on the application side, constructing a proxy type such as: record struct ByteArrayProxy(byte[] Bytes);
Log.Information("Some {Data}", new ByteArrayProxy(myBytes)); and then targeting it with an Hope this helps. |
Thanks for the clarification! I am indeed wrapping the byte array as a workaround (in the In any case, what I really want is to be able to control how Serilog formats values of arbitrary types. The fact that I'm using destructuring is just because that's the only way I found. If it would be possible to add a way to let users specify formatting of arbitrary types (e.g., pass |
The reason to use destructuring or enrichment is that Serilog does capturing on the foreground thread (at the point the event is logged), but formatting on a (potentially) background thread. By the time the data reaches the formatting stage it's already been snapshotted; this is how mutable things like arrays end up logged with the right contents (and race conditions/threading bugs are avoided). HTH! |
Thanks, though I'm not sure what you intend for me to do with that information? |
Just filling in the picture, unfortunately it doesn't get us closer to a solution, just narrows down the possible places to investigate :-) |
Repro:
Expected output:
Actual output:
Top-level byte arrays aren't passed to my destructuring policy. This seems inconsistent. Could this inconsistency be fixed, so that byte arrays are passed to the destructuring policy?
The text was updated successfully, but these errors were encountered: