Skip to content

Commit 775b4ac

Browse files
chore: added extra unit test cases for recorder.go
1 parent 68aa726 commit 775b4ac

File tree

2 files changed

+172
-2
lines changed

2 files changed

+172
-2
lines changed

recorder.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,19 +138,32 @@ func (r *Recorder) GetQueuedSpans() []Span {
138138

139139
// Flush sends queued spans to the agent
140140
func (r *Recorder) Flush(ctx context.Context) error {
141-
spansToSend := r.GetQueuedSpans()
142-
if len(spansToSend) == 0 {
141+
// For test mode, we don't want to actually send spans
142+
if r.testMode {
143143
return nil
144144
}
145145

146+
// Check if agent is ready before getting and clearing spans
146147
muSensor.Lock()
147148
if sensor == nil {
148149
muSensor.Unlock()
149150
return nil
150151
}
152+
151153
agent := sensor.Agent()
154+
agentReady := agent.Ready()
152155
muSensor.Unlock()
153156

157+
// If agent is not ready, don't flush spans
158+
if !agentReady {
159+
return nil
160+
}
161+
162+
spansToSend := r.GetQueuedSpans()
163+
if len(spansToSend) == 0 {
164+
return nil
165+
}
166+
154167
if err := agent.SendSpans(spansToSend); err != nil {
155168
r.Lock()
156169
defer r.Unlock()

recorder_test.go

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,14 @@
44
package instana_test
55

66
import (
7+
"context"
8+
"fmt"
79
"testing"
10+
"time"
811

912
instana "github.com/instana/go-sensor"
13+
"github.com/instana/go-sensor/acceptor"
14+
"github.com/instana/go-sensor/autoprofile"
1015
ot "github.com/opentracing/opentracing-go"
1116
"github.com/opentracing/opentracing-go/ext"
1217
"github.com/stretchr/testify/assert"
@@ -68,3 +73,155 @@ func TestRecorder_BatchSpan_Single(t *testing.T) {
6873

6974
assert.Nil(t, spans[0].Batch)
7075
}
76+
77+
func TestRecorder_Flush_EmptyQueue(t *testing.T) {
78+
recorder := instana.NewTestRecorder()
79+
80+
// Test flushing an empty queue
81+
err := recorder.Flush(context.Background())
82+
assert.NoError(t, err)
83+
}
84+
85+
func TestRecorder_MaxBufferedSpans(t *testing.T) {
86+
recorder := instana.NewTestRecorder()
87+
c := instana.InitCollector(&instana.Options{
88+
AgentClient: alwaysReadyClient{},
89+
Recorder: recorder,
90+
MaxBufferedSpans: 3, // Set a small buffer size for testing
91+
})
92+
defer instana.ShutdownCollector()
93+
94+
// Create more spans than the buffer can hold
95+
for i := 0; i < 5; i++ {
96+
c.StartSpan(fmt.Sprintf("span-%d", i)).Finish()
97+
}
98+
99+
// Verify that only the most recent MaxBufferedSpans are kept
100+
spans := recorder.GetQueuedSpans()
101+
assert.Len(t, spans, 3)
102+
103+
// Verify that only the most recent MaxBufferedSpans are kept
104+
assert.Len(t, spans, 3)
105+
}
106+
107+
func TestRecorder_ForceTransmission(t *testing.T) {
108+
// Create a mock agent client that tracks when spans are sent
109+
mockAgent := &mockAgentClient{
110+
ready: true,
111+
}
112+
113+
recorder := instana.NewRecorder()
114+
c := instana.InitCollector(&instana.Options{
115+
AgentClient: mockAgent,
116+
Recorder: recorder,
117+
MaxBufferedSpans: 10,
118+
ForceTransmissionStartingAt: 2, // Force transmission after 2 spans
119+
})
120+
defer instana.ShutdownCollector()
121+
122+
// Create spans to trigger force transmission
123+
for i := 0; i < 2; i++ {
124+
c.StartSpan(fmt.Sprintf("span-%d", i)).Finish()
125+
}
126+
127+
// Give some time for the async flush to happen
128+
time.Sleep(100 * time.Millisecond)
129+
130+
// Verify that SendSpans was called
131+
assert.True(t, mockAgent.spansSent, "Expected spans to be sent to the agent")
132+
}
133+
134+
// Mock agent client for testing
135+
type mockAgentClient struct {
136+
ready bool
137+
spansSent bool
138+
}
139+
140+
func (m *mockAgentClient) Ready() bool { return m.ready }
141+
func (m *mockAgentClient) SendMetrics(data acceptor.Metrics) error { return nil }
142+
func (m *mockAgentClient) SendEvent(event *instana.EventData) error { return nil }
143+
func (m *mockAgentClient) SendSpans(spans []instana.Span) error {
144+
m.spansSent = true
145+
return nil
146+
}
147+
func (m *mockAgentClient) SendProfiles(profiles []autoprofile.Profile) error { return nil }
148+
func (m *mockAgentClient) Flush(context.Context) error { return nil }
149+
150+
// alwaysReadyClient is already defined in instrumentation_http_test.go
151+
152+
func TestRecorder_Flush_Error(t *testing.T) {
153+
// Create a mock agent client that returns an error on SendSpans
154+
mockAgent := &errorAgentClient{
155+
ready: true,
156+
}
157+
158+
recorder := instana.NewRecorder()
159+
c := instana.InitCollector(&instana.Options{
160+
AgentClient: mockAgent,
161+
Recorder: recorder,
162+
})
163+
defer instana.ShutdownCollector()
164+
165+
// Create a span to be flushed
166+
c.StartSpan("test-span").Finish()
167+
168+
// Flush should return an error
169+
err := recorder.Flush(context.Background())
170+
assert.Error(t, err)
171+
assert.Contains(t, err.Error(), "failed to send collected spans")
172+
173+
// Verify that spans are put back in the queue
174+
assert.Greater(t, recorder.QueuedSpansCount(), 0)
175+
}
176+
177+
// Mock agent client that returns an error on SendSpans
178+
type errorAgentClient struct {
179+
ready bool
180+
}
181+
182+
func (m *errorAgentClient) Ready() bool { return m.ready }
183+
func (m *errorAgentClient) SendMetrics(data acceptor.Metrics) error { return nil }
184+
func (m *errorAgentClient) SendEvent(event *instana.EventData) error { return nil }
185+
func (m *errorAgentClient) SendSpans(spans []instana.Span) error { return fmt.Errorf("mock error") }
186+
func (m *errorAgentClient) SendProfiles(profiles []autoprofile.Profile) error { return nil }
187+
func (m *errorAgentClient) Flush(context.Context) error { return nil }
188+
189+
// TestRecorder_Flush_AgentNotReady tests the behavior when the agent is not ready
190+
func TestRecorder_Flush_AgentNotReady(t *testing.T) {
191+
// Create a mock agent client that is not ready
192+
mockAgent := &notReadyAgentClient{}
193+
194+
// Use a regular recorder, not a test recorder
195+
recorder := instana.NewRecorder()
196+
c := instana.InitCollector(&instana.Options{
197+
AgentClient: mockAgent,
198+
Recorder: recorder,
199+
})
200+
defer instana.ShutdownCollector()
201+
202+
// Create a span to be flushed
203+
c.StartSpan("test-span").Finish()
204+
205+
// Wait a bit for the span to be processed
206+
time.Sleep(100 * time.Millisecond)
207+
208+
// Get the initial count
209+
initialCount := recorder.QueuedSpansCount()
210+
211+
// Flush should not return an error when agent is not ready
212+
err := recorder.Flush(context.Background())
213+
assert.NoError(t, err)
214+
215+
// Spans should still be in the queue when agent is not ready
216+
assert.Equal(t, initialCount, recorder.QueuedSpansCount(), "Spans should remain in queue when agent is not ready")
217+
}
218+
219+
// Mock agent client that is never ready
220+
type notReadyAgentClient struct{}
221+
222+
func (notReadyAgentClient) Ready() bool { return false }
223+
func (notReadyAgentClient) SendMetrics(data acceptor.Metrics) error { return nil }
224+
func (notReadyAgentClient) SendEvent(event *instana.EventData) error { return nil }
225+
func (notReadyAgentClient) SendSpans(spans []instana.Span) error { return nil }
226+
func (notReadyAgentClient) SendProfiles(profiles []autoprofile.Profile) error { return nil }
227+
func (notReadyAgentClient) Flush(context.Context) error { return nil }

0 commit comments

Comments
 (0)