2023-03-28 18:39:22 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
2023-08-11 13:12:13 +00:00
|
|
|
// SPDX-License-Identifier: BUSL-1.1
|
2023-03-28 18:39:22 +00:00
|
|
|
|
2022-07-13 15:33:48 +00:00
|
|
|
package internal
|
2020-08-28 23:23:40 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"net"
|
2020-10-13 23:38:13 +00:00
|
|
|
"sort"
|
2020-08-28 23:23:40 +00:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/armon/go-metrics"
|
2020-10-13 23:38:13 +00:00
|
|
|
"github.com/google/go-cmp/cmp"
|
2020-08-28 23:23:40 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"golang.org/x/sync/errgroup"
|
|
|
|
"google.golang.org/grpc"
|
2020-10-08 23:43:49 +00:00
|
|
|
|
2021-08-22 18:06:26 +00:00
|
|
|
"github.com/hashicorp/go-hclog"
|
2022-07-13 15:33:48 +00:00
|
|
|
|
2022-12-13 20:09:55 +00:00
|
|
|
"github.com/hashicorp/consul/agent/consul/rate"
|
2022-10-11 22:00:32 +00:00
|
|
|
"github.com/hashicorp/consul/agent/grpc-middleware/testutil"
|
|
|
|
"github.com/hashicorp/consul/agent/grpc-middleware/testutil/testservice"
|
2023-02-17 21:14:46 +00:00
|
|
|
"github.com/hashicorp/consul/proto/private/prototest"
|
2020-08-28 23:23:40 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestHandler_EmitsStats(t *testing.T) {
|
2022-10-11 22:00:32 +00:00
|
|
|
sink, metricsObj := testutil.NewFakeSink(t)
|
2020-08-28 23:23:40 +00:00
|
|
|
|
|
|
|
addr := &net.IPAddr{IP: net.ParseIP("127.0.0.1")}
|
2024-01-12 16:54:07 +00:00
|
|
|
handler := NewHandler(hclog.Default(), addr, metricsObj, rate.NullRequestLimitsHandler())
|
2020-09-08 21:31:47 +00:00
|
|
|
|
2024-01-12 16:54:07 +00:00
|
|
|
testservice.RegisterSimpleServer(handler, &testservice.Simple{})
|
2020-08-28 23:23:40 +00:00
|
|
|
|
|
|
|
lis, err := net.Listen("tcp", "127.0.0.1:0")
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
t.Cleanup(cancel)
|
|
|
|
|
|
|
|
g, ctx := errgroup.WithContext(ctx)
|
|
|
|
g.Go(func() error {
|
|
|
|
return handler.srv.Serve(lis)
|
|
|
|
})
|
|
|
|
t.Cleanup(func() {
|
|
|
|
if err := handler.Shutdown(); err != nil {
|
|
|
|
t.Logf("grpc server shutdown: %v", err)
|
|
|
|
}
|
|
|
|
if err := g.Wait(); err != nil {
|
|
|
|
t.Logf("grpc server error: %v", err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2022-11-07 16:34:30 +00:00
|
|
|
//nolint:staticcheck
|
2020-08-28 23:23:40 +00:00
|
|
|
conn, err := grpc.DialContext(ctx, lis.Addr().String(), grpc.WithInsecure())
|
|
|
|
require.NoError(t, err)
|
2020-10-14 17:21:51 +00:00
|
|
|
t.Cleanup(func() { conn.Close() })
|
2020-08-28 23:23:40 +00:00
|
|
|
|
|
|
|
client := testservice.NewSimpleClient(conn)
|
|
|
|
fClient, err := client.Flow(ctx, &testservice.Req{Datacenter: "mine"})
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// Wait for the first event so that we know the stream is sending.
|
|
|
|
_, err = fClient.Recv()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-09-14 17:16:13 +00:00
|
|
|
cancel()
|
2020-10-08 23:43:49 +00:00
|
|
|
conn.Close()
|
|
|
|
handler.srv.GracefulStop()
|
2020-09-14 17:16:13 +00:00
|
|
|
// Wait for the server to stop so that active_streams is predictable.
|
2020-10-08 23:43:49 +00:00
|
|
|
require.NoError(t, g.Wait())
|
|
|
|
|
2020-10-13 23:38:13 +00:00
|
|
|
// Occasionally the active_stream=0 metric may be emitted before the
|
|
|
|
// active_conns=0 metric. The order of those metrics is not really important
|
|
|
|
// so we sort the calls to match the expected.
|
2022-10-11 22:00:32 +00:00
|
|
|
sort.Slice(sink.GaugeCalls, func(i, j int) bool {
|
2020-10-13 23:38:13 +00:00
|
|
|
if i < 2 || j < 2 {
|
|
|
|
return i < j
|
|
|
|
}
|
2022-10-11 22:00:32 +00:00
|
|
|
if len(sink.GaugeCalls[i].Key) < 4 || len(sink.GaugeCalls[j].Key) < 4 {
|
2020-10-13 23:38:13 +00:00
|
|
|
return i < j
|
|
|
|
}
|
2022-10-11 22:00:32 +00:00
|
|
|
return sink.GaugeCalls[i].Key[3] < sink.GaugeCalls[j].Key[3]
|
2020-10-13 23:38:13 +00:00
|
|
|
})
|
|
|
|
|
2022-10-11 22:00:32 +00:00
|
|
|
cmpMetricCalls := cmp.AllowUnexported(testutil.MetricCall{})
|
|
|
|
expLabels := []metrics.Label{{
|
|
|
|
Name: "server_type",
|
|
|
|
Value: "internal",
|
|
|
|
}}
|
|
|
|
expectedGauge := []testutil.MetricCall{
|
|
|
|
{Key: []string{"testing", "grpc", "server", "connections"}, Val: 1, Labels: expLabels},
|
|
|
|
{Key: []string{"testing", "grpc", "server", "streams"}, Val: 1, Labels: expLabels},
|
|
|
|
{Key: []string{"testing", "grpc", "server", "connections"}, Val: 0, Labels: expLabels},
|
|
|
|
{Key: []string{"testing", "grpc", "server", "streams"}, Val: 0, Labels: expLabels},
|
2020-10-08 23:43:49 +00:00
|
|
|
}
|
2022-10-11 22:00:32 +00:00
|
|
|
prototest.AssertDeepEqual(t, expectedGauge, sink.GaugeCalls, cmpMetricCalls)
|
2020-09-14 17:16:13 +00:00
|
|
|
|
2022-10-11 22:00:32 +00:00
|
|
|
expectedCounter := []testutil.MetricCall{
|
|
|
|
{Key: []string{"testing", "grpc", "server", "connection", "count"}, Val: 1, Labels: expLabels},
|
|
|
|
{Key: []string{"testing", "grpc", "server", "request", "count"}, Val: 1, Labels: expLabels},
|
|
|
|
{Key: []string{"testing", "grpc", "server", "stream", "count"}, Val: 1, Labels: expLabels},
|
2020-08-28 23:23:40 +00:00
|
|
|
}
|
2022-10-11 22:00:32 +00:00
|
|
|
prototest.AssertDeepEqual(t, expectedCounter, sink.IncrCounterCalls, cmpMetricCalls)
|
2020-08-28 23:23:40 +00:00
|
|
|
}
|
2020-09-14 17:16:13 +00:00
|
|
|
|
|
|
|
func logError(t *testing.T, f func() error) func() {
|
|
|
|
return func() {
|
|
|
|
if err := f(); err != nil {
|
|
|
|
t.Logf(err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|