Skip to content

Commit 509959f

Browse files
add build tag to disable tracing (#754)
* add build tag to disable tracing * add new build tag `-build=retrynotrace` to support dead code elimination * fix copyright headers * Update interceptors/retry/trace_notrace.go Co-authored-by: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com> * add interceptors/retry/README.md --------- Co-authored-by: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
1 parent 8b26373 commit 509959f

6 files changed

+186
-2
lines changed

interceptors/retry/README.md

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
## Retry Interceptor
2+
3+
The `retry` interceptor is a client-side middleware for gRPC that provides a generic mechanism to retry requests based on gRPC response codes.
4+
5+
### Build Flags
6+
7+
The `retry` interceptor supports a build flag `retrynotrace` to disable tracing for retry attempts.
8+
This can be useful to avoid importing `golang.org/x/net/trace`, which allows for more aggressive deadcode elimination. This can yield improvements in binary size when tracing is not needed.
9+
10+
To build your application with the `retrynotrace` flag, use the following command:
11+
12+
```shell
13+
go build -tags retrynotrace -o your_application
14+
```
15+
16+
### Usage
17+
18+
To use the `retry` interceptor, you need to add it to your gRPC client interceptor chain:
19+
20+
```go
21+
import (
22+
"github.com/grpc-ecosystem/go-grpc-middleware/v2/interceptors/retry"
23+
"google.golang.org/grpc"
24+
)
25+
26+
func main() {
27+
opts := []grpc.DialOption{
28+
grpc.WithUnaryInterceptor(retry.UnaryClientInterceptor(
29+
retry.WithMax(3), // Maximum number of retries
30+
retry.WithPerRetryTimeout(2*time.Second), // Timeout per retry
31+
)),
32+
}
33+
34+
conn, err := grpc.NewClient("your_grpc_server_address", opts...)
35+
if err != nil {
36+
log.Fatalf("Failed to connect: %v", err)
37+
}
38+
defer conn.Close()
39+
40+
// Your gRPC client code here
41+
}
42+
```
43+
44+
### Configuration Options
45+
46+
- `retry.WithMax(maxRetries int)`: Sets the maximum number of retry attempts.
47+
- `retry.WithPerRetryTimeout(timeout time.Duration)`: Sets the timeout for each retry attempt.
48+
- `retry.WithBackoff(backoffFunc retry.BackoffFunc)`: Sets a custom backoff strategy.
49+
- `retry.WithCodes(codes ...codes.Code)`: Specifies the gRPC response codes that should trigger a retry.

interceptors/retry/retry.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"time"
1212

1313
"github.com/grpc-ecosystem/go-grpc-middleware/v2/metadata"
14-
"golang.org/x/net/trace"
1514
"google.golang.org/grpc"
1615
"google.golang.org/grpc/codes"
1716
grpcMetadata "google.golang.org/grpc/metadata"
@@ -320,7 +319,7 @@ func contextErrToGrpcErr(err error) error {
320319
}
321320

322321
func logTrace(ctx context.Context, format string, a ...any) {
323-
tr, ok := trace.FromContext(ctx)
322+
tr, ok := traceFromCtx(ctx)
324323
if !ok {
325324
return
326325
}

interceptors/retry/trace_notrace.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) The go-grpc-middleware Authors.
2+
// Licensed under the Apache License 2.0.
3+
4+
//go:build retrynotrace
5+
6+
package retry
7+
8+
// retrynotrace can be used to avoid importing golang.org/x/net/trace,
9+
// which allows for more aggressive deadcode elimination, which can
10+
// yield improvements in binary size when tracing is not needed.
11+
12+
import (
13+
"context"
14+
"fmt"
15+
)
16+
17+
type notrace struct{}
18+
19+
func (notrace) LazyLog(x fmt.Stringer, sensitive bool) {}
20+
func (notrace) LazyPrintf(format string, a ...any) {}
21+
func (notrace) SetError() {}
22+
func (notrace) SetRecycler(f func(any)) {}
23+
func (notrace) SetTraceInfo(traceID, spanID uint64) {}
24+
func (notrace) SetMaxEvents(m int) {}
25+
func (notrace) Finish() {}
26+
27+
func traceFromCtx(ctx context.Context) (notrace, bool) {
28+
return notrace{}, true
29+
}
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) The go-grpc-middleware Authors.
2+
// Licensed under the Apache License 2.0.
3+
4+
//go:build retrynotrace
5+
6+
package retry
7+
8+
import (
9+
"context"
10+
"testing"
11+
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func Test_traceFromCtx(t *testing.T) {
16+
tr := notrace{}
17+
ctx := context.Background()
18+
19+
type args struct {
20+
ctx context.Context
21+
}
22+
tests := []struct {
23+
name string
24+
args args
25+
want notrace
26+
want1 bool
27+
}{
28+
{
29+
name: "should return notrace",
30+
args: args{ctx: ctx},
31+
want: tr,
32+
want1: true,
33+
},
34+
}
35+
for _, tt := range tests {
36+
t.Run(tt.name, func(t *testing.T) {
37+
got, got1 := traceFromCtx(tt.args.ctx)
38+
assert.Equalf(t, tt.want, got, "traceFromCtx(%v)", tt.args.ctx)
39+
assert.Equalf(t, tt.want1, got1, "traceFromCtx(%v)", tt.args.ctx)
40+
})
41+
}
42+
}

interceptors/retry/trace_withtrace.go

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright (c) The go-grpc-middleware Authors.
2+
// Licensed under the Apache License 2.0.
3+
4+
//go:build !retrynotrace
5+
6+
package retry
7+
8+
import (
9+
"context"
10+
11+
t "golang.org/x/net/trace"
12+
)
13+
14+
func traceFromCtx(ctx context.Context) (t.Trace, bool) {
15+
return t.FromContext(ctx)
16+
}
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (c) The go-grpc-middleware Authors.
2+
// Licensed under the Apache License 2.0.
3+
4+
//go:build !retrynotrace
5+
6+
package retry
7+
8+
import (
9+
"context"
10+
"testing"
11+
12+
"github.com/stretchr/testify/assert"
13+
"golang.org/x/net/trace"
14+
)
15+
16+
func Test_traceFromCtx(t *testing.T) {
17+
tr := trace.New("test", "with trace")
18+
ctx := trace.NewContext(context.Background(), tr)
19+
20+
type args struct {
21+
ctx context.Context
22+
}
23+
tests := []struct {
24+
name string
25+
args args
26+
want trace.Trace
27+
want1 bool
28+
}{
29+
{
30+
name: "should return trace",
31+
args: args{ctx: ctx},
32+
want: tr,
33+
want1: true,
34+
},
35+
{
36+
name: "should return false if trace not found in ctx",
37+
args: args{ctx: context.Background()},
38+
want: nil,
39+
want1: false,
40+
},
41+
}
42+
for _, tt := range tests {
43+
t.Run(tt.name, func(t *testing.T) {
44+
got, got1 := traceFromCtx(tt.args.ctx)
45+
assert.Equalf(t, tt.want, got, "traceFromCtx(%v)", tt.args.ctx)
46+
assert.Equalf(t, tt.want1, got1, "traceFromCtx(%v)", tt.args.ctx)
47+
})
48+
}
49+
}

0 commit comments

Comments
 (0)