-
Notifications
You must be signed in to change notification settings - Fork 67
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
GetContextTags question/improvement #51
Comments
Hi Georgy, first thank you for your interest and your many questions.
Well it depends, if there were multiple contexts of interest across multiple servers (error flowing through microservices), the caller may be interested to see the grouping of tags to determine how many servers were involved. That said it is easy and quick to get the merged list of tags: a
Here what you need to know is this:
They get printed for your human eyes -- there is no intent to make them structurally visible to algorithms. The general problem here is that all Go code other than this library expects errors to be structured as linked lists and will never know how to look "sideways". Moreover, it's not possible to "insert" errors in this list due to how error types are implemented. Hope this helps! Let me know if you have further questions or comments. |
Thanks a lot for all the details. The But I still have some uncertainty about the Thanks in advance! |
Your use case seems reasonable to me. But in that case, I would log the various groups of tags separately (i.e. I would make the logging format aware that errors are structured in layers, and report the groups of tags in the layers where they belong). For example, CockroachDB uses semi-strructured logging and crash reporting: errors are reported verbosely, and the Is there something like this that could apply to your use case? |
Let's consider this code: package main
import (
"context"
"fmt"
"log"
"github.com/cockroachdb/errors"
"github.com/cockroachdb/logtags"
)
func layer1(ctx context.Context) error {
ctx = logtags.AddTag(ctx, "layer1_tag", "1")
err := errors.New("root error")
return errors.WithContextTags(err, ctx)
}
func layer2(ctx context.Context) error {
ctx = logtags.AddTag(ctx, "layer2_tag", "2")
err := layer1(ctx)
err = errors.Wrap(err, "layer1 failed")
err = errors.WithContextTags(err, ctx)
return err
}
func main() {
ctx := context.Background()
err := layer2(ctx)
tags := errors.GetContextTags(err)
var logStmt string
for _, t := range tags {
logStmt += fmt.Sprintf("tags: %s\n", t)
}
logStmt += fmt.Sprintf("error: %s\n", err)
log.Println(logStmt)
} So you mean that I separate/group tags in my log statement by layer and log everything at once with the actual error message. The result is something like that:
But how can I achieve that with structured logging for example with library like logrus. Log event is just a flat list of key-value pairs with one special key "msg". In order to separate tags I would need to add a prefix like |
yes something like this indeed: tags := errors.GetContextTags(err)
logStmt := "tags: "
semi := ""
for _, b := range tagBuffers {
logStmt += semi + b.String()
semi = "; "
}
Yes, I was thinking about something like that too.
Can you explain why on this point specifically? |
Sure. For example, layer1 has a tag |
ok I have two sets of questions
In this last point, let me illustrate with a case we have from CockroachDB: queries get processed on multiple nodes. So we have In our case, the I could perhaps imagine a custom combine logic that says that "for the node ID tag, we need to concatenate values with a separator, not just replace them" so as to get e.g. But then -- do you foresee a way to "do the right thing" for every tag value, in a generic way that can be included in the errors library? |
No. You should get the list of all logs satisfying the filter
Actually, I am surprised that ELK supports that type of filter: when you specify the key prefix, not the value prefix:
I don't think ordering is respected. It's really like a tag pool/map. And I don't foresee tags with the same name but different values i.e conflicting tags. Actually, I am starting to understand your case with
I thought about that, when you preserve the tag name and just concatente the values, but in this case you can't understand how tags are grouped per context. So going with suffixes
Now I understand that its harder to do. The only thing that is quite general is to introduce a helper function on top of |
Hi. Any update on this? |
I'm not sure - what update did you have in mind? |
Sorry I might misuse the word. There is no next action. It was more like a ping because I thought that my last comment #51 (comment) didn't reach you. It contains some hypothetical questions/ideas. If it did reach you and you don't have any further thoughts to share I am totally okay to close the issue because you already covered all my initial concerns. |
I agree with everything you wrote, so I didn't feel there was anything to answer (except maybe to say I agree). If you have further questions I'll be happy to help further. |
Understood. |
Hi. I have a few questions about the usage of
GetContextTags
function.For example, I have a package that has an important set of tags during operation processing and in case of an error, I want to attach those tags to the returned error so the caller could reveal them. It's simple, I do it like that:
And later up to the stack the caller decides to log the error in a structured way, it needs to extract the list of all tags from the error:
But it returns a list of Buffers (Buffer for each error with tags in the chain) and each buffer contains a list of tags.
So it's
[][]Tag
, instead of[]Tag
. Wouldn't it be better to add a function that will return merged buffers with a single list of unique tags, isn't it what the caller interested the most?Another thing that I wanted to ask about is how context tags work with the
CombineError
function. As far as I can see if I combine two errorserr1
anderr2
(both of them have context tags):The resulting error will contain tags only from the
err1
when I callGetContextTags
on it. But for example, if the error gets printed, all stack traces will be displayed for the second error two. Shouldn'tGetContextTags
visit all child errors (including secondaries) and follow the stack trace printing logic?The text was updated successfully, but these errors were encountered: