Skip to content

Commit 0c18419

Browse files
authored
Merge pull request #43 from cockroachdb/20800812-report
report,redact: incrementally improve the ergonomics of reports
2 parents 558717e + 1a9bf4e commit 0c18419

File tree

7 files changed

+100
-81
lines changed

7 files changed

+100
-81
lines changed

contexttags/contexttags_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ func TestTagRedaction(t *testing.T) {
107107

108108
// This will be our reference expected value.
109109
refStrings := [][]string{
110-
[]string{"planet1=<string>", "planet2=universe"},
111-
[]string{"foo1=<int>", "x<int>", "bar1", "foo2=123", "y456", "bar2"},
110+
[]string{"planet1=string:<redacted>", "planet2=universe"},
111+
[]string{"foo1=int:<redacted>", "xint:<redacted>", "bar1", "foo2=123", "y456", "bar2"},
112112
}
113113

114114
// Construct the error object.

report/report.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ func BuildSentryReport(err error) (event *sentry.Event, extraDetails map[string]
269269
stKey := fmt.Sprintf("%d: details", extraNum)
270270
var extraStr bytes.Buffer
271271
for _, d := range details[i].SafeDetails {
272-
fmt.Fprintln(&extraStr, d)
272+
fmt.Fprintln(&extraStr, strings.ReplaceAll(d, "\n", "\n "))
273273
}
274274
extras[stKey] = extraStr.String()
275275
fmt.Fprintf(&longMsgBuf, " (%d)", extraNum)

report/report_test.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ func TestReport(t *testing.T) {
5353
thisDomain := domains.NamedDomain("thisdomain")
5454

5555
err = goErr.New("hello")
56-
err = safedetails.WithSafeDetails(err, "universe %d", safedetails.Safe(123))
56+
err = safedetails.WithSafeDetails(err, "universe %d %s",
57+
safedetails.Safe(123), safedetails.Safe("multi\nline"))
5758
err = withstack.WithStack(err)
5859
err = domains.WithDomain(err, thisDomain)
5960
defer errbase.TestingWithEmptyMigrationRegistry()()
@@ -73,7 +74,7 @@ func TestReport(t *testing.T) {
7374

7475
tt.Run("long message payload", func(tt testutils.T) {
7576
expectedLongMessage := `^\*errors.errorString
76-
\*safedetails.withSafeDetails: universe %d \(1\)
77+
\*safedetails.withSafeDetails: format: "universe %d %s" \(1\)
7778
report_test.go:\d+: \*withstack.withStack \(top exception\)
7879
\*domains\.withDomain: error domain: "thisdomain" \(2\)
7980
\*report_test\.myWrapper
@@ -91,7 +92,10 @@ github.com/cockroachdb/errors/report_test/*report_test.myWrapper (some/previous/
9192
types := fmt.Sprintf("%s", e.Extra["error types"])
9293
tt.CheckEqual(types, expectedTypes)
9394

94-
expectedDetail := "universe %d\n-- arg 1: 123"
95+
expectedDetail := `format: "universe %d %s"
96+
-- arg 1: 123
97+
-- arg 2: multi
98+
line`
9599
detail := fmt.Sprintf("%s", e.Extra["1: details"])
96100
tt.CheckEqual(strings.TrimSpace(detail), expectedDetail)
97101

safedetails/redact.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func Redact(r interface{}) string {
4242
}
4343
redactErr(&buf, t)
4444
default:
45-
typAnd(&buf, r, "")
45+
typRedacted(&buf, r)
4646
}
4747

4848
return buf.String()
@@ -60,7 +60,7 @@ func redactErr(buf *strings.Builder, err error) {
6060

6161
// Add any additional safe strings from the wrapper, if present.
6262
if payload := errbase.GetSafeDetails(err); len(payload.SafeDetails) > 0 {
63-
buf.WriteString("\n(more details:)")
63+
buf.WriteString("\n(more details about this error:)")
6464
for _, sd := range payload.SafeDetails {
6565
buf.WriteByte('\n')
6666
buf.WriteString(strings.TrimSpace(sd))
@@ -69,7 +69,7 @@ func redactErr(buf *strings.Builder, err error) {
6969
}
7070

7171
func redactWrapper(buf *strings.Builder, err error) {
72-
buf.WriteString("\nwrapper: ")
72+
buf.WriteString("\n")
7373
switch t := err.(type) {
7474
case *os.SyscallError:
7575
typAnd(buf, t, t.Syscall)
@@ -83,16 +83,16 @@ func redactWrapper(buf *strings.Builder, err error) {
8383
fmt.Fprintf(buf, " %s", t.Net)
8484
}
8585
if t.Source != nil {
86-
buf.WriteString("<redacted>")
86+
buf.WriteString(" <redacted>")
8787
}
8888
if t.Addr != nil {
8989
if t.Source != nil {
90-
buf.WriteString("->")
90+
buf.WriteString(" ->")
9191
}
92-
buf.WriteString("<redacted>")
92+
buf.WriteString(" <redacted>")
9393
}
9494
default:
95-
typAnd(buf, err, "")
95+
typRedacted(buf, err)
9696
}
9797
}
9898

@@ -126,14 +126,17 @@ func redactLeafErr(buf *strings.Builder, err error) {
126126
typAnd(buf, t, t.SafeMessage())
127127
default:
128128
// No further information about this error, simply report its type.
129-
typAnd(buf, err, "")
129+
typRedacted(buf, err)
130130
}
131131
}
132132

133+
func typRedacted(buf *strings.Builder, r interface{}) {
134+
fmt.Fprintf(buf, "%T:<redacted>", r)
135+
}
136+
133137
func typAnd(buf *strings.Builder, r interface{}, msg string) {
134-
if msg == "" {
135-
fmt.Fprintf(buf, "<%T>", r)
136-
} else {
137-
fmt.Fprintf(buf, "%T: %s", r, msg)
138+
if len(msg) == 0 {
139+
msg = "(empty string)"
138140
}
141+
fmt.Fprintf(buf, "%T: %s", r, msg)
139142
}

safedetails/redact_test.go

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ func TestRedact(t *testing.T) {
3737
}{
3838
// Redacting non-error values.
3939

40-
{123, `<int>`},
41-
{"secret", `<string>`},
40+
{123, `int:<redacted>`},
41+
{"secret", `string:<redacted>`},
4242

4343
// Redacting SafeMessagers.
4444

@@ -47,24 +47,24 @@ func TestRedact(t *testing.T) {
4747
{mySafeError{}, `hello`},
4848
{&werrFmt{mySafeError{}, "unseen"},
4949
`safedetails_test.mySafeError: hello
50-
wrapper: <*safedetails_test.werrFmt>`},
50+
*safedetails_test.werrFmt:<redacted>`},
5151

5252
// Redacting errors.
5353

5454
// Unspecial cases, get redacted.
55-
{errors.New("secret"), `<*errors.errorString>`},
55+
{errors.New("secret"), `*errors.errorString:<redacted>`},
5656

5757
// Stack trace in error retrieves some info about the context.
5858
{withstack.WithStack(errors.New("secret")),
59-
`<path>: <*errors.errorString>
60-
wrapper: <*withstack.withStack>
61-
(more details:)
59+
`...path...: *errors.errorString:<redacted>
60+
*withstack.withStack:<redacted>
61+
(more details about this error:)
6262
github.com/cockroachdb/errors/safedetails_test.TestRedact
63-
<path>
63+
...path...
6464
testing.tRunner
65-
<path>
65+
...path...
6666
runtime.goexit
67-
<path>`},
67+
...path...`},
6868

6969
// Special cases, unredacted.
7070
{os.ErrInvalid, `*errors.errorString: invalid argument`},
@@ -83,22 +83,22 @@ runtime.goexit
8383
`*runtime.TypeAssertionError: interface conversion: interface {} is nil, not int`},
8484

8585
{errSentinel, // explodes if Error() called
86-
`<struct { error }>`},
86+
`struct { error }:<redacted>`},
8787

8888
{&werrFmt{&werrFmt{os.ErrClosed, "unseen"}, "unsung"},
8989
`*errors.errorString: file already closed
90-
wrapper: <*safedetails_test.werrFmt>
91-
wrapper: <*safedetails_test.werrFmt>`},
90+
*safedetails_test.werrFmt:<redacted>
91+
*safedetails_test.werrFmt:<redacted>`},
9292

9393
// Special cases, get partly redacted.
9494

9595
{os.NewSyscallError("rename", os.ErrNotExist),
9696
`*errors.errorString: file does not exist
97-
wrapper: *os.SyscallError: rename`},
97+
*os.SyscallError: rename`},
9898

9999
{&os.PathError{Op: "rename", Path: "secret", Err: os.ErrNotExist},
100100
`*errors.errorString: file does not exist
101-
wrapper: *os.PathError: rename`},
101+
*os.PathError: rename`},
102102

103103
{&os.LinkError{
104104
Op: "moo",
@@ -107,23 +107,23 @@ wrapper: *os.PathError: rename`},
107107
Err: os.ErrNotExist,
108108
},
109109
`*errors.errorString: file does not exist
110-
wrapper: *os.LinkError: moo <redacted> <redacted>`},
110+
*os.LinkError: moo <redacted> <redacted>`},
111111

112112
{&net.OpError{
113113
Op: "write",
114114
Net: "tcp",
115115
Source: &net.IPAddr{IP: net.IP("sensitive-source")},
116116
Addr: &net.IPAddr{IP: net.IP("sensitive-addr")},
117117
Err: errors.New("not safe"),
118-
}, `<*errors.errorString>
119-
wrapper: *net.OpError: write tcp<redacted>-><redacted>`},
118+
}, `*errors.errorString:<redacted>
119+
*net.OpError: write tcp <redacted> -> <redacted>`},
120120
}
121121

122122
tt := testutils.T{T: t}
123123

124124
for _, tc := range testData {
125125
s := safedetails.Redact(tc.obj)
126-
s = fileref.ReplaceAllString(s, "<path>")
126+
s = fileref.ReplaceAllString(s, "...path...")
127127

128128
tt.CheckStringEqual(s, tc.expected)
129129
}

safedetails/safedetails.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,18 @@ func WithSafeDetails(err error, format string, args ...interface{}) error {
3333

3434
details := make([]string, 1, 1+len(args))
3535
details[0] = format
36+
if len(format) > 0 && len(args) > 0 {
37+
// Call out that this string was a formatting string.
38+
details[0] = fmt.Sprintf("format: %q", details[0])
39+
}
3640
for i, a := range args {
37-
details = append(details, fmt.Sprintf("-- arg %d: %s", i+1, Redact(a)))
41+
what := ""
42+
if _, ok := a.(error); ok {
43+
// Call out that this argument was an error, to facilitate
44+
// interpretation of subsequent lines.
45+
what = " (error)"
46+
}
47+
details = append(details, fmt.Sprintf("-- arg %d%s: %s", i+1, what, Redact(a)))
3848
}
3949
return &withSafeDetails{cause: err, safeDetails: details}
4050
}

0 commit comments

Comments
 (0)