Files
tasks/common/rpc/dial_tracer_test.go
Vladyslav SimonenkoandGitHub 1916d05702 Instrument gRPC dial calls with metrics (#8162)
## What changed?
Instrument gRPC dial calls with metrics monitoring connection
establishment. This PR adds the following metrics:

1. ServiceDialLatency
2. ServiceDialSuccessCount
3. ServiceDialErrorCount

## Why?
Currently the visibility into gRPC dial calls is limited, there are no
metrics for how long establishing the connection took, or how many
failures we encountered. Since `grpc.NewClient` is "lazy", in the sense
that it doesn't establish connection right away, but rather on the first
RPC, we need to instrument it via some hooks.

This PR uses `grpc.WithContextDialer` to achieve this. gRPC library
itself uses platform-specific keep alive hack to use OS defaults for TCP
keepalive, but since we are on Go 1.23+ we can simply use newly
introduced KeepAliveConfig.

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

## Potential risks
2025-09-04 14:47:36 -07:00

87 lines
2.0 KiB
Go

package rpc
import (
"context"
"net/http/httptrace"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.temporal.io/server/common/log"
"go.temporal.io/server/common/metrics"
)
func TestDialTracer_DialSuccess(t *testing.T) {
t.Parallel()
addr := "127.0.0.1:1234"
dt := newDialTracer(addr, metrics.NoopMetricsHandler, log.NewNoopLogger())
ctx := context.Background()
ctx, ndt := dt.beginNetworkDial(ctx)
trace := httptrace.ContextClientTrace(ctx)
require.NotNil(t, trace)
trace.ConnectStart("tcp", addr)
rewind(&ndt.connectStart)
trace.ConnectDone("tcp", addr, nil)
dt.endNetworkDial(ndt, nil)
assert.Positive(t, ndt.connectDuration)
assert.Equal(t, addr, ndt.connectAddr)
assert.Nil(t, ndt.connectErr)
}
func TestDialTracer_DialError(t *testing.T) {
t.Parallel()
addr := "127.0.0.1:1234"
dt := newDialTracer(addr, metrics.NoopMetricsHandler, log.NewNoopLogger())
ctx := context.Background()
ctx, ndt := dt.beginNetworkDial(ctx)
trace := httptrace.ContextClientTrace(ctx)
require.NotNil(t, trace)
connectErr := assert.AnError
trace.ConnectStart("tcp", addr)
rewind(&ndt.connectStart)
trace.ConnectDone("tcp", addr, connectErr)
dt.endNetworkDial(ndt, nil)
assert.Positive(t, ndt.connectDuration)
assert.Equal(t, addr, ndt.connectAddr)
assert.Equal(t, connectErr, ndt.connectErr)
}
func TestDialTracer_NoConnectStart(t *testing.T) {
t.Parallel()
addr := "127.0.0.1:1234"
dt := newDialTracer(addr, metrics.NoopMetricsHandler, log.NewNoopLogger())
ctx := context.Background()
ctx, ndt := dt.beginNetworkDial(ctx)
trace := httptrace.ContextClientTrace(ctx)
require.NotNil(t, trace)
trace.ConnectDone("tcp", addr, nil)
dt.endNetworkDial(ndt, nil)
assert.Zero(t, ndt.connectDuration)
assert.Equal(t, addr, ndt.connectAddr)
assert.Nil(t, ndt.connectErr)
}
// rewind moves a timestamp back by 1 millisecond to ensure positive durations in tests
func rewind(ts *time.Time) {
*ts = ts.Add(-time.Millisecond)
}