Skip to content

Commit

Permalink
Bump google.golang.org/grpc from 1.51.0 to 1.52.0 (jaegertracing#4149)
Browse files Browse the repository at this point in the history
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from
1.51.0 to 1.52.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/grpc/grpc-go/releases">google.golang.org/grpc's
releases</a>.</em></p>
<blockquote>
<h2>Release 1.52.0</h2>
<h1>New Features</h1>
<ul>
<li>xdsclient: log node ID with verbosity INFO (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5860">#5860</a>)</li>
<li>ringhash: impose cap on <code>max_ring_size</code> to reduce
possibility of OOMs (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5801">#5801</a>)</li>
</ul>
<h1>Behavior Changes</h1>
<ul>
<li>client: return an error from <code>Dial</code> if an empty target is
passed and no custom dialer is present; the ClientConn would otherwise
be unable to connect and perform RPCs (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5732">#5732</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/huangchong94"><code>@​huangchong94</code></a></li>
</ul>
</li>
</ul>
<h1>Bug Fixes</h1>
<ul>
<li>transport (net/http server handler): respond to bad HTTP requests
with status 400 (Bad Request) instead of 500 (Internal Server Error).
(<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5804">#5804</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/sjbarag"><code>@​sjbarag</code></a></li>
</ul>
</li>
<li>transport: Fixed closing a closed channel panic in handlePing (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5854">#5854</a>)</li>
<li>server: fix ChainUnaryInterceptor and ChainStreamInterceptor to
allow retrying handlers (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5666">#5666</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/yiminc"><code>@​yiminc</code></a></li>
</ul>
</li>
<li>transport: ensure value of <code>:authority</code> header matches
server name used in TLS handshake when the latter is overridden by the
name resolver (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5748">#5748</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/holdno"><code>@​holdno</code></a></li>
</ul>
</li>
</ul>
<h1>Documentation</h1>
<ul>
<li>examples: add an example to illustrate the usage of stats handler
(<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5657">#5657</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/Yash-Handa"><code>@​Yash-Handa</code></a></li>
</ul>
</li>
<li>examples: add new example to show updating metadata in interceptors
(<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5788">#5788</a>)
<ul>
<li>Special Thanks: <a
href="https://github.com/richzw"><code>@​richzw</code></a></li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/grpc/grpc-go/commit/ce56cefc0cc80503d7f8de1e1ec1af3cb741fbd7"><code>ce56cef</code></a>
Change version to 1.52.0 (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5870">#5870</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/a0e8eb9dc4111cd4d8dc52bc89cd733e5630fc0c"><code>a0e8eb9</code></a>
test: rename race.go to race_test.go (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5869">#5869</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/ae86ff40e723905d1d7f084405a7ed6e9a5265e1"><code>ae86ff4</code></a>
benchmark: fix typo in ClientReadBufferSize feature name (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5867">#5867</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/e53d28f5eb19a6816d4bb5c3db1b793ac2ba3e49"><code>e53d28f</code></a>
xdsclient: log node ID with verbosity INFO (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5860">#5860</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/9373e5cb26f0e34c1b5fa54f1ba712979b54d661"><code>9373e5c</code></a>
transport: Fix closing a closed channel panic in handlePing (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5854">#5854</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/2f413c454850afdb19a685fdee95c5d7701891ab"><code>2f413c4</code></a>
transport/http2: use HTTP 400 for bad requests instead of 500 (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5804">#5804</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/5003029eb684a60a7a84aad3ad498d7bf1e44628"><code>5003029</code></a>
testutils: do a better job of verifying pick_first in tests (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5850">#5850</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/3e27f89917e8092469db2709c5d726acaaa2396e"><code>3e27f89</code></a>
binarylog: Account for key in metadata truncation (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5851">#5851</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/f54bba9af73267dcc87fcc4841dfa1e0de39d332"><code>f54bba9</code></a>
test/xds: minor cleanup in xDS e2e test (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5843">#5843</a>)</li>
<li><a
href="https://github.com/grpc/grpc-go/commit/a9709c3f8cfe5f22703b8cfebd83d3996f8fbb33"><code>a9709c3</code></a>
Added logs for reasons causing connection and transport close (<a
href="https://github-redirect.dependabot.com/grpc/grpc-go/issues/5840">#5840</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/grpc/grpc-go/compare/v1.51.0...v1.52.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=google.golang.org/grpc&package-manager=go_modules&previous-version=1.51.0&new-version=1.52.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <[email protected]>
Signed-off-by: Yuri Shkuro <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Yuri Shkuro <[email protected]>
  • Loading branch information
2 people authored and shubbham1215 committed Feb 22, 2023
1 parent 4ceee52 commit 10da445
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 48 deletions.
4 changes: 3 additions & 1 deletion cmd/agent/app/processors/thrift_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ func (s *ThriftProcessor) processBuffer() {
protocol.Transport().Write(payload)
s.logger.Debug("Span(s) received by the agent", zap.Int("bytes-received", len(payload)))

if ok, err := s.handler.Process(context.Background(), protocol, protocol); !ok {
// NB: oddly, thrift-gen/agent/agent.go:L156 does this: `return true, thrift.WrapTException(err2)`
// So we check for both OK and error.
if ok, err := s.handler.Process(context.Background(), protocol, protocol); !ok || err != nil {
s.logger.Error("Processor failed", zap.Error(err))
s.metrics.HandlerProcessError.Inc(1)
}
Expand Down
80 changes: 44 additions & 36 deletions cmd/agent/app/processors/thrift_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"github.com/apache/thrift/lib/go/thrift"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zaptest"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

Expand Down Expand Up @@ -64,7 +64,7 @@ func createProcessor(t *testing.T, mFactory metrics.Factory, tFactory thrift.TPr
require.NoError(t, err)

numProcessors := 1
processor, err := NewThriftProcessor(server, numProcessors, mFactory, tFactory, handler, zap.NewNop())
processor, err := NewThriftProcessor(server, numProcessors, mFactory, tFactory, handler, zaptest.NewLogger(t))
require.NoError(t, err)

go processor.Serve()
Expand All @@ -83,14 +83,14 @@ func initCollectorAndReporter(t *testing.T) (*metricstest.Factory, *testutils.Gr
grpcCollector := testutils.StartGRPCCollector(t)
conn, err := grpc.Dial(grpcCollector.Listener().Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
require.NoError(t, err)
rep := grpcrep.NewReporter(conn, map[string]string{}, zap.NewNop())
rep := grpcrep.NewReporter(conn, map[string]string{}, zaptest.NewLogger(t))
metricsFactory := metricstest.NewFactory(0)
reporter := reporter.WrapWithMetrics(rep, metricsFactory)
return metricsFactory, grpcCollector, reporter, conn
}

func TestNewThriftProcessor_ZeroCount(t *testing.T) {
_, err := NewThriftProcessor(nil, 0, nil, nil, nil, zap.NewNop())
_, err := NewThriftProcessor(nil, 0, nil, nil, nil, zaptest.NewLogger(t))
assert.EqualError(t, err, "number of processors must be greater than 0, called with 0")
}

Expand Down Expand Up @@ -153,31 +153,36 @@ func TestProcessor_HandlerError(t *testing.T) {
)
}

// TestJaegerProcessor instantiates a real UDP receiver and a real gRPC collector
// and executes end-to-end batch submission.
func TestJaegerProcessor(t *testing.T) {
tests := []struct {
factory thrift.TProtocolFactory
name string
}{
{compactFactory},
{binaryFactory},
{compactFactory, "compact"},
{binaryFactory, "binary"},
}

for _, test := range tests {
metricsFactory, collector, reporter, conn := initCollectorAndReporter(t)
t.Run(test.name, func(t *testing.T) {
metricsFactory, collector, reporter, conn := initCollectorAndReporter(t)

hostPort, processor := createProcessor(t, metricsFactory, test.factory, agent.NewAgentProcessor(reporter))
hostPort, processor := createProcessor(t, metricsFactory, test.factory, agent.NewAgentProcessor(reporter))

client, clientCloser, err := testutils.NewJaegerThriftUDPClient(hostPort, test.factory)
require.NoError(t, err)
client, clientCloser, err := testutils.NewJaegerThriftUDPClient(hostPort, test.factory)
require.NoError(t, err)

err = client.EmitBatch(context.Background(), batch)
require.NoError(t, err)
err = client.EmitBatch(context.Background(), batch)
require.NoError(t, err)

assertJaegerProcessorCorrectness(t, collector, metricsFactory)
assertJaegerProcessorCorrectness(t, collector, metricsFactory)

processor.Stop()
clientCloser.Close()
conn.Close()
collector.Close()
processor.Stop()
clientCloser.Close()
conn.Close()
collector.Close()
})
}
}

Expand All @@ -188,7 +193,7 @@ func assertJaegerProcessorCorrectness(t *testing.T, collector *testutils.GrpcCol
nameF := func() string {
return collector.GetJaegerBatches()[0].Spans[0].OperationName
}
assertProcessorCorrectness(t, metricsFactory, sizeF, nameF, "jaeger")
assertCollectorReceivedData(t, metricsFactory, sizeF, nameF, "jaeger")
}

func assertZipkinProcessorCorrectness(t *testing.T, collector *testutils.GrpcCollector, metricsFactory *metricstest.Factory) {
Expand All @@ -198,37 +203,40 @@ func assertZipkinProcessorCorrectness(t *testing.T, collector *testutils.GrpcCol
nameF := func() string {
return collector.GetJaegerBatches()[0].Spans[0].OperationName
}
assertProcessorCorrectness(t, metricsFactory, sizeF, nameF, "zipkin")
assertCollectorReceivedData(t, metricsFactory, sizeF, nameF, "zipkin")
}

func assertProcessorCorrectness(
// assertCollectorReceivedData verifies that collector received the data
// and that agent reporter emitted corresponding metrics.
func assertCollectorReceivedData(
t *testing.T,
metricsFactory *metricstest.Factory,
sizeF func() int,
nameF func() string,
format string,
) {
// wait for server to receive
for i := 0; i < 1000; i++ {
if sizeF() == 1 {
break
}
time.Sleep(1 * time.Millisecond)
}

require.Equal(t, 1, sizeF())
require.Eventually(t,
func() bool { return sizeF() == 1 },
5*time.Second,
time.Millisecond,
"server should have received spans")
assert.Equal(t, testSpanName, nameF())

// wait for reporter to emit metrics
for i := 0; i < 1000; i++ {
key := "reporter.spans.submitted|format=" + format
ok := assert.Eventuallyf(t,
func() bool {
c, _ := metricsFactory.Snapshot()
_, ok := c[key]
return ok
},
5*time.Second,
time.Millisecond,
"reporter should have emitted metric %s", key)
if !ok {
c, _ := metricsFactory.Snapshot()
if _, ok := c["tc-reporter.spans.submitted"]; ok {
break
}
time.Sleep(1 * time.Millisecond)
t.Log("all metrics", c)
}

// agentReporter must emit metrics
metricsFactory.AssertCounterMetrics(t, []metricstest.ExpectedMetric{
{Name: "reporter.batches.submitted", Tags: map[string]string{"format": format}, Value: 1},
{Name: "reporter.spans.submitted", Tags: map[string]string{"format": format}, Value: 1},
Expand Down
2 changes: 2 additions & 0 deletions cmd/agent/app/reporter/grpc/reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package grpc

import (
"context"
"fmt"

"go.uber.org/zap"
"google.golang.org/grpc"
Expand Down Expand Up @@ -79,6 +80,7 @@ func (r *Reporter) send(ctx context.Context, spans []*model.Span, process *model
} else {
r.logger.Error("Could not send spans over gRPC", zap.Error(err))
}
err = fmt.Errorf("failed to export spans: %w", err)
}
return err
}
Expand Down
8 changes: 4 additions & 4 deletions cmd/agent/app/reporter/grpc/reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,12 @@ func TestReporter_EmitBatch(t *testing.T) {
}

func TestReporter_SendFailure(t *testing.T) {
conn, err := grpc.Dial("", grpc.WithTransportCredentials(insecure.NewCredentials()))
conn, err := grpc.Dial("invalid-host-name-blah:12345", grpc.WithTransportCredentials(insecure.NewCredentials()))
require.NoError(t, err)
rep := NewReporter(conn, nil, zap.NewNop())
err = rep.send(context.Background(), nil, nil)
require.Error(t, err)
assert.Contains(t, err.Error(), "transport: Error while dialing dial tcp: missing address")
assert.Contains(t, err.Error(), "failed to export spans:")
}

func TestReporter_AddProcessTags_EmptyTags(t *testing.T) {
Expand Down Expand Up @@ -218,11 +218,11 @@ func TestReporter_MultitenantEmitBatch(t *testing.T) {
}{
{
in: &jThrift.Batch{Process: &jThrift.Process{ServiceName: "node"}, Spans: []*jThrift.Span{{OperationName: "foo", StartTime: int64(model.TimeAsEpochMicroseconds(tm))}}},
err: "rpc error: code = PermissionDenied desc = missing tenant header",
err: "missing tenant header",
},
}
for _, test := range tests {
err = rep.EmitBatch(context.Background(), test.in)
assert.EqualError(t, err, test.err)
assert.Contains(t, err.Error(), test.err)
}
}
4 changes: 3 additions & 1 deletion cmd/agent/app/testutils/mock_grpc_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func StartGRPCCollector(t *testing.T) *GrpcCollector {
server := grpc.NewServer()
lis, err := net.Listen("tcp", "localhost:0")
require.NoError(t, err)
handler := &mockSpanHandler{}
handler := &mockSpanHandler{t: t}
api_v2.RegisterCollectorServiceServer(server, handler)
go func() {
require.NoError(t, server.Serve(lis))
Expand All @@ -65,6 +65,7 @@ func (c *GrpcCollector) Close() error {
}

type mockSpanHandler struct {
t *testing.T
mux sync.Mutex
requests []*api_v2.PostSpansRequest
}
Expand All @@ -81,6 +82,7 @@ func (h *mockSpanHandler) GetJaegerBatches() []model.Batch {
}

func (h *mockSpanHandler) PostSpans(_ context.Context, r *api_v2.PostSpansRequest) (*api_v2.PostSpansResponse, error) {
h.t.Logf("mockSpanHandler received %d spans", len(r.Batch.Spans))
h.mux.Lock()
defer h.mux.Unlock()
h.requests = append(h.requests, r)
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ require (
go.uber.org/zap v1.24.0
golang.org/x/net v0.5.0
golang.org/x/sys v0.4.0
google.golang.org/grpc v1.51.0
google.golang.org/grpc v1.52.0
google.golang.org/protobuf v1.28.1
gopkg.in/yaml.v2 v2.4.0
)
Expand Down Expand Up @@ -150,7 +150,7 @@ require (
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect
golang.org/x/text v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1111,8 +1111,8 @@ google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c h1:QgY/XxIAIeccR+Ca/rDdKubLIU9rcJ3xfy1DC/Wd2Oo=
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo=
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c=
google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
Expand All @@ -1136,8 +1136,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk=
google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
Expand Down

0 comments on commit 10da445

Please sign in to comment.