Files
tasks/common/testing/grpcinject/grpcinject.go
Stephan BehnkeandGitHub 06aaa0358b Export OTEL by test suite (#7941)
## What changed?

Redo of https://github.com/temporalio/temporal/pull/7871.

(1) Instead of collecting OTEL trace across all suites, it tracks it per
suite and only exports traces on failure.
(2) It annotates the test's RPCs with the test name.

## Why?

(1) More efficient.
(2) Allows filtering traces by test name.

## How did you test it?
- [ ] built
- [ ] run locally and tested manually
- [x] covered by existing tests
- [ ] added new unit test(s)
- [ ] added new functional test(s)

Example run with artifacts:
https://github.com/temporalio/temporal/actions/runs/15786189984?pr=7941

<img width="1100" alt="Screenshot 2025-06-20 at 12 37 20 PM"
src="https://github.com/user-attachments/assets/d46668e3-4766-4689-8ebf-b9df4ef9e569"
/>
2025-06-23 15:22:34 -07:00

63 lines
1.3 KiB
Go

package grpcinject
import (
"context"
"sync/atomic"
"google.golang.org/grpc"
)
// MetadataFunc is a function type that modifies the outgoing context with metadata
type MetadataFunc func(ctx context.Context) context.Context
type Interceptor struct {
current atomic.Value // type MetadataFunc
}
func NewInterceptor() *Interceptor {
return &Interceptor{}
}
func (i *Interceptor) Set(fn MetadataFunc) {
i.current.Store(fn)
}
func (i *Interceptor) currentFunc() MetadataFunc {
if v, ok := i.current.Load().(MetadataFunc); ok && v != nil {
return v
}
return nil
}
func (i *Interceptor) Unary() grpc.UnaryClientInterceptor {
return func(
ctx context.Context,
method string,
req, reply interface{},
cc *grpc.ClientConn,
invoker grpc.UnaryInvoker,
opts ...grpc.CallOption,
) error {
if fn, ok := i.current.Load().(MetadataFunc); ok && fn != nil {
ctx = fn(ctx)
}
return invoker(ctx, method, req, reply, cc, opts...)
}
}
func (i *Interceptor) Stream() grpc.StreamClientInterceptor {
return func(
ctx context.Context,
desc *grpc.StreamDesc,
cc *grpc.ClientConn,
method string,
streamer grpc.Streamer,
opts ...grpc.CallOption,
) (grpc.ClientStream, error) {
if fn, ok := i.current.Load().(MetadataFunc); ok && fn != nil {
ctx = fn(ctx)
}
return streamer(ctx, desc, cc, method, opts...)
}
}