[
https://issues.apache.org/jira/browse/THRIFT-5745?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Yuxuan Wang reassigned THRIFT-5745:
-----------------------------------
Assignee: Yuxuan Wang
> go: Implement slog.LogValuer for exceptions and/or structs
> ----------------------------------------------------------
>
> Key: THRIFT-5745
> URL: https://issues.apache.org/jira/browse/THRIFT-5745
> Project: Thrift
> Issue Type: Task
> Components: Go - Compiler
> Reporter: Yuxuan Wang
> Assignee: Yuxuan Wang
> Priority: Major
>
> To follow up on THRIFT-5744, implement
> [slog.LogValuer|https://pkg.go.dev/log/slog#LogValuer] on compiler generated
> exceptions, and maybe also structs.
> The current problem is that when logging an exception, the Stringer
> implementation will be used, but that usually gives you quite unhelpful
> string, especially when optional fields are used.
> For example we have [this exception
> defined|https://github.com/reddit/baseplate.py/blob/8c446337dab6a1692900decf9cd01f3f4e39d764/baseplate/thrift/baseplate.thrift#L197]:
> {code:java}
> exception Error {
> 1: optional i32 code
> 2: optional string message
> 3: optional map<string, string> details
> 4: optional bool retryable
> }
> {code}
> When you create an instance of it:
> {code:go}
> return &baseplate.Error{
> Code: thrift.Int32Ptr(404),
> Message: thrift.Pointer("no such id"),
> }
> {code}
> And then log that error, instead of getting something useful with the code
> (404) and message ("no such id") in it, you get something like this instead
> because this is how we implemented fmt.Stringer from the compiler:
> {code:go}
> Error({Code:0xc000426648 Message:0xc00041ca10 Details:map[] Retryable:<nil>})
> {code}
> The compiler generates implementation for json.Marshaler for all exceptions,
> which will be much more helpful. The marshaled json for such error would be:
> {code:json}
> {"code":400,"message":"no such id"}
> {code}
> They are also much more expensive, so probably not suitable to replace the
> current Stringer implementation, but when logging them, it's probably worth
> it to implement slog.LogValuer so we can log something more useful, probably
> like this:
> {code:go}
> func (p *Error) LogValue() slog.Value{
> var sb strings.Builder
> sb.WriteString("baseplate.Error")
> bytes, err := json.Marshal(p)
> if err != nil {
> // should not happen
> return slog.StringValue(fmt.Sprintf("baseplate.Error.LogValue: failed to
> marshal json: %v", err))
> }
> sb.Write(bytes)
> return slog.StringValue(sb.String())
> }
> {code}
> Which will make the error logged show as:
> {code:json}
> baseplate.Error{"code":400,"message":"no such id"}
> {code}
> Some open questions:
> # Is this also useful for structs?
> # Do we want to make this optional (e.g. only generate LogValue function when
> a compiler flag is passed in)?
--
This message was sent by Atlassian Jira
(v8.20.10#820010)