Skip to content

Commit aab1424

Browse files
authored
[receiver/opencensus]: check for ErrListenerClosed when reporting multiplexer status (open-telemetry#34093)
Fixes open-telemetry#33865 --------- Signed-off-by: odubajDT <[email protected]>
1 parent c389bb2 commit aab1424

File tree

3 files changed

+113
-1
lines changed

3 files changed

+113
-1
lines changed

.chloggen/correctness-traces.yaml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: bug_fix
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: opencensusreceiver
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: Do not report an error into resource status during receiver shutdown when the listener connection was closed.
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [33865]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: []

receiver/opencensusreceiver/opencensus.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,12 @@ func (ocr *ocReceiver) Start(ctx context.Context, host component.Host) error {
113113
if !hasConsumer {
114114
return errors.New("cannot start receiver: no consumers were specified")
115115
}
116+
116117
ocr.ln, err = net.Listen(string(ocr.cfg.NetAddr.Transport), ocr.cfg.NetAddr.Endpoint)
117118
if err != nil {
118119
return fmt.Errorf("failed to bind to address %q: %w", ocr.cfg.NetAddr.Endpoint, err)
119120
}
121+
120122
// Register the grpc-gateway on the HTTP server mux
121123
var c context.Context
122124
c, ocr.cancel = context.WithCancel(context.Background())
@@ -155,7 +157,7 @@ func (ocr *ocReceiver) Start(ctx context.Context, host component.Host) error {
155157
}()
156158
go func() {
157159
startWG.Done()
158-
if err := ocr.multiplexer.Serve(); !errors.Is(err, cmux.ErrServerClosed) && err != nil {
160+
if err := ocr.multiplexer.Serve(); !errors.Is(err, cmux.ErrServerClosed) && !errors.Is(err, cmux.ErrListenerClosed) && err != nil {
159161
ocr.settings.TelemetrySettings.ReportStatus(component.NewFatalErrorEvent(err))
160162
}
161163
}()

receiver/opencensusreceiver/opencensus_test.go

+83
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,89 @@ func TestStartWithoutConsumersShouldFail(t *testing.T) {
302302
require.Error(t, r.Start(context.Background(), componenttest.NewNopHost()))
303303
}
304304

305+
func TestStartListenerClosed(t *testing.T) {
306+
307+
addr := testutil.GetAvailableLocalAddress(t)
308+
309+
// Set the buffer count to 1 to make it flush the test span immediately.
310+
sink := new(consumertest.TracesSink)
311+
cfg := &Config{
312+
ServerConfig: configgrpc.ServerConfig{
313+
NetAddr: confignet.AddrConfig{
314+
Endpoint: addr,
315+
Transport: "tcp",
316+
},
317+
},
318+
}
319+
ocr := newOpenCensusReceiver(cfg, sink, nil, receivertest.NewNopSettings())
320+
321+
ctx := context.Background()
322+
323+
// start receiver
324+
err := ocr.Start(ctx, componenttest.NewNopHost())
325+
require.NoError(t, err, "Failed to start trace receiver: %v", err)
326+
327+
url := fmt.Sprintf("http://%s/v1/trace", addr)
328+
329+
traceJSON := []byte(`
330+
{
331+
"node":{"identifier":{"hostName":"testHost"}},
332+
"spans":[
333+
{
334+
"traceId":"W47/95gDgQPSabYzgT/GDA==",
335+
"spanId":"7uGbfsPBsXM=",
336+
"name":{"value":"testSpan"},
337+
"startTime":"2018-12-13T14:51:00Z",
338+
"endTime":"2018-12-13T14:51:01Z",
339+
"attributes": {
340+
"attributeMap": {
341+
"attr1": {"intValue": "55"}
342+
}
343+
}
344+
}
345+
]
346+
}`)
347+
348+
// send request to verify listener is working
349+
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(traceJSON))
350+
require.NoError(t, err, "Error creating trace POST request: %v", err)
351+
req.Header.Set("Content-Type", "application/json")
352+
353+
client := &http.Client{}
354+
defer client.CloseIdleConnections()
355+
resp, err := client.Do(req)
356+
require.NoError(t, err, "Error posting trace to grpc-gateway server: %v", err)
357+
358+
defer func() {
359+
require.NoError(t, resp.Body.Close())
360+
}()
361+
362+
respBytes, err := io.ReadAll(resp.Body)
363+
require.NoError(t, err)
364+
respStr := string(respBytes)
365+
366+
assert.Equal(t, http.StatusOK, resp.StatusCode)
367+
assert.Empty(t, respStr)
368+
369+
// stop the listener
370+
ocr.ln.Close()
371+
372+
// verify trace was sent
373+
got := sink.AllTraces()
374+
require.Len(t, got, 1)
375+
require.Equal(t, 1, got[0].ResourceSpans().Len())
376+
gotNode, gotResource, gotSpans := opencensus.ResourceSpansToOC(got[0].ResourceSpans().At(0))
377+
378+
wantNode := &commonpb.Node{Identifier: &commonpb.ProcessIdentifier{HostName: "testHost"}}
379+
wantResource := &resourcepb.Resource{}
380+
assert.True(t, proto.Equal(wantNode, gotNode))
381+
assert.True(t, proto.Equal(wantResource, gotResource))
382+
require.Len(t, gotSpans, 1)
383+
384+
// stop the receiver to verify it's not blocked by the closed listener
385+
require.NoError(t, ocr.Shutdown(ctx))
386+
}
387+
305388
func tempSocketName(t *testing.T) string {
306389
tmpfile, err := os.CreateTemp("", "sock")
307390
require.NoError(t, err)

0 commit comments

Comments
 (0)