-
Notifications
You must be signed in to change notification settings - Fork 33
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
Log forwarding #153
Log forwarding #153
Conversation
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.
One main question.
Also I noticed we're not sending the span_contexts
field from core (and I think I missed that in the Python PR). That's useful to send and have show up somehow as it provides a good bit of context (can kind of be considered part of the target)
@@ -131,7 +131,8 @@ internal static class OptionsExtensions | |||
return new Interop.LoggingOptions() | |||
{ | |||
filter = scope.ByteArray(options.Filter.FilterString), | |||
forward = (byte)0, | |||
// Forward callback is set in the Runtime constructor | |||
// forward_to = ??? |
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.
Leftover line?
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.
Intentional, as a way to say "I know I am not setting this field here". Maybe ???
should be <set elsewhere>
EDIT: Updated
target: ByteArray, | ||
message: ByteArray, | ||
timestamp_millis: u64, | ||
fields_json: ByteArray, |
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'm confused why we're converting the fields to JSON here rather than passing something structured back into .NET? Can we not convert into some .NET object here and send that over in ForwardedLog
rather than doing this serialization?
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.
To pass something structured over the C FFI boundary means I build an entire object model in C to represent that. This usually means a recursive union with a new enum and figure out lifetime issues (vs copying). It's just more complicated, I don't already have serde_json::Value
at my disposal in C like you have in Rust. It's a similar question to why I send proto bytes to/from core instead of creating structures to represent those.
But if it's worth it, I can do it. For now, I'm just converting to Dictionary<string, JsonElement>
on the .NET side anyways. The other option I considered is to just pass a "fields_suffix" string for now that is built Rust side, but I figured I might as well provide the somewhat-structured field.
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.
Yeah, I get that - I just thought it would probably be easy enough to make the right structure here since there's only a handful of types. I think it's probably worth it in the sense that it's not code we're likely to have any problem with, just a bit of extra boilerplate but it'll be quite a bit more efficient on a fairly hot path.
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 don't think it's going to be that much more efficient since I am turning it back into a string anyways on the .NET side. So I guess I can just let the Rust side turn it into a string for me and then we'll have the best performance. The only reason to use structured data is if the user wants structured data. If we're concerned about performance, we should make the user decide to turn it to structured (which they can given a JSON string).
So now I've come full circle back to my current impl except not expose it as a Dictionary<string, JsonElement>
but rather Dictionary<string, string>
where values are JSON strings and if a user wants more structure, they can parse values.
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.
Ok, I updated this to give keys and values where the values are raw JSON. This is the best performing I can do, and is better than converting each nested Rust object into a nested .NET object just to turn it to a string in the log message on the .NET side. Having Rust just serialize JSON is plenty fast for this use case (and not worth a new C map structure).
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.
👍 makes sense to me. What I missed originally is that ILogger
doesn't have any explicit structured k/v pairs in the interface anyway, so yeah there's no "place" to offer the structured objects.
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.
there's no "place" to offer the structured objects.
Well, there is in that a logger gets an arbitrary "state" which is an enumerable of k/v pairs. So advanced users can use that to get the fields out (we do in our tests). But the default is to append the field values stringified anyways. So I'd prefer to make that the performant path and force users to deserialize JSON if they need more advanced structure if they happen to be doing something advanced with the values.
I left these off as I couldn't see a good way of them making it into log and I'm hesitant to bring in more data just for the log record if it's not on the default log message currently. But if they should be on the default log message it can make more sense, any suggestions of log message format welcome. Otherwise, I was just gonna wait until someone asked. |
I am seeing some segfaults on Ubuntu ARM with the new logging test which is scary. I am moving this into draft mode while I do the push-debug-code-watch-CI dance to see if I can figure out what is happening. |
e842700
to
c6477fd
Compare
aeb2253
to
30aff36
Compare
Segfault lifetime issue fixed |
What was changed
Temporalio.Runtime.LogForwardingConfig
that accepts aILogger
to forward logs toTemporalio.Runtime.LoggingOptions.Forwarding
to accept the aboveChecklist