Skip to content

Commit 6186854

Browse files
committed
Merge branch 'nslaughter/azureeventhubreceiver-20240611' into nslaughter/migrate-eventhub-sdk
2 parents 97bee5d + b2a6fd7 commit 6186854

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+7448
-703
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
- name: Install builder
2323
working-directory: ./collector
2424
run: |
25-
go install go.opentelemetry.io/collector/cmd/builder@v0.97.0
25+
go install go.opentelemetry.io/collector/cmd/builder@v0.102.1
2626
- name: Build
2727
working-directory: ./collector
2828
run: make build-linux

collector/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ install-tools: install-builder
3838

3939
.PHONY: install-builder - Install the builder
4040
install-builder:
41-
go install "go.opentelemetry.io/collector/cmd/builder@v0.98.0"
41+
go install "go.opentelemetry.io/collector/cmd/builder@v0.102.1"
4242

4343
.PHONY: docker - Build docker image
4444
docker:
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
package azureeventhubreceiver
2+
3+
// https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/messaging/azeventhubs/processor.go
4+
// https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/messaging/azeventhubs/processor_partition_client.go
5+
6+
/*
7+
>> https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/messaging/azeventhubs/example_consuming_with_checkpoints_test.go
8+
- get a processor
9+
- dispatchPartitionClients
10+
- processor.Run
11+
12+
13+
14+
>> https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/messaging/azeventhubs/example_consuming_events_test.go
15+
- ReceiveEvents(ctx, count int, options *ReceiveEventsOptions) ([]*ReceivedEventData, error)
16+
- call cancel()
17+
- panic if there's an error that isn't context.DeadlineExceeded
18+
- process events
19+
--> put them into the entity thingy
20+
*/
21+
22+
// import (
23+
// "context"
24+
// "errors"
25+
// "fmt"
26+
// "time"
27+
28+
// "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs"
29+
// "github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/checkpoints"
30+
// "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container"
31+
// )
32+
33+
// // Assuming there's a struct managing the processor setup
34+
// // type EventHubProcessor struct {
35+
// // Processor *azeventhubs.Processor
36+
// // }
37+
38+
// // Updated initialization function using the new SDK components
39+
// func NewEventHubProcessor(ehConn, ehName, storageConn, storageCnt string) (*EventHubProcessor, error) {
40+
// checkpointingProcessor, err := newCheckpointingProcessor(ehConn, ehName, storageConn, storageCnt)
41+
// if err != nil {
42+
// return nil, fmt.Errorf("failed to create checkpointing processor: %w", err)
43+
// }
44+
45+
// // Start processing events
46+
// return &EventHubProcessor{
47+
// Processor: checkpointingProcessor,
48+
// }, nil
49+
// }
50+
51+
// // Assume there's a function to start processing events
52+
// func (e *EventHubProcessor) StartProcessing(ctx context.Context) error {
53+
// // Start the processor
54+
// if err := e.Processor.Run(ctx); err != nil {
55+
// return fmt.Errorf("error running processor: %w", err)
56+
// }
57+
// return nil
58+
// }
59+
60+
// // Assuming there's a struct managing the processor setup
61+
// type EventHubProcessor struct {
62+
// Processor *azeventhubs.Processor
63+
// }
64+
65+
// // These are config values the processor factory can use to create processors:
66+
// //
67+
// // (a) EventHubConnectionString
68+
// // (b) EventHubName
69+
// // (c) StorageConnectionString
70+
// // (d) StorageContainerName
71+
// //
72+
// // You always need the EventHub variable values.
73+
// // And you need all 4 of these to checkpoint.
74+
// //
75+
// // I think the config values should be managed in the factory struct.
76+
// /*
77+
// func (pf *processorFactory) CreateProcessor() (*azeventhubs.Processor, error) {
78+
// // Create the consumer client
79+
// consumerClient, err := azeventhubs.NewConsumerClientFromConnectionString(pf.EventHubConnectionString, pf.EventHubName, azeventhubs.DefaultConsumerGroup, nil)
80+
// if err != nil {
81+
// return nil, err
82+
// }
83+
84+
// // Create the blob container client for the checkpoint store
85+
// blobContainerClient, err := container.NewClientFromConnectionString(pf.StorageConnectionString, pf.StorageContainerName, nil)
86+
// if err != nil {
87+
// return nil, err
88+
// }
89+
90+
// // Create the checkpoint store using the blob container client
91+
// checkpointStore, err := azeventhubs.NewBlobCheckpointStore(blobContainerClient, nil)
92+
// // checkpointStore, err := azeventhubs.NewBlobCheckpointStore(blobContainerClient, nil)
93+
// // if err != nil {
94+
// // return nil, err
95+
// // }
96+
97+
// // Create the processor with checkpointing
98+
// processor, err := azeventhubs.NewProcessor(consumerClient, checkpointStore, nil)
99+
// if err != nil {
100+
// return nil, err
101+
// }
102+
103+
// return processor, nil
104+
// }
105+
// */
106+
107+
// // checkpointing processor should be auth aware
108+
109+
// func newCheckpointingProcessor(eventHubConnectionString, eventHubName, storageConnectionString, storageContainerName string) (*azeventhubs.Processor, error) {
110+
// blobContainerClient, err := container.NewClientFromConnectionString(storageConnectionString, storageContainerName, nil)
111+
// if err != nil {
112+
// return nil, err
113+
// }
114+
// checkpointStore, err := checkpoints.NewBlobStore(blobContainerClient, nil)
115+
// if err != nil {
116+
// return nil, err
117+
// }
118+
119+
// consumerClient, err := azeventhubs.NewConsumerClientFromConnectionString(eventHubConnectionString, eventHubName, azeventhubs.DefaultConsumerGroup, nil)
120+
// if err != nil {
121+
// return nil, err
122+
// }
123+
124+
// return azeventhubs.NewProcessor(consumerClient, checkpointStore, nil)
125+
// }
126+
/*
127+
func dispatchPartitionClients(processor *azeventhubs.Processor) {
128+
for {
129+
processorPartitionClient := processor.NextPartitionClient(context.TODO())
130+
if processorPartitionClient == nil {
131+
break
132+
}
133+
134+
go func() {
135+
if err := processEventsForPartition(processorPartitionClient); err != nil {
136+
panic(err)
137+
}
138+
}()
139+
}
140+
}
141+
142+
func processEventsForPartition(partitionClient *azeventhubs.ProcessorPartitionClient) error {
143+
defer shutdownPartitionResources(partitionClient)
144+
if err := initializePartitionResources(partitionClient.PartitionID()); err != nil {
145+
return err
146+
}
147+
148+
for {
149+
receiveCtx, cancelReceive := context.WithTimeout(context.TODO(), time.Minute)
150+
events, err := partitionClient.ReceiveEvents(receiveCtx, 100, nil)
151+
cancelReceive()
152+
153+
if err != nil && !errors.Is(err, context.DeadlineExceeded) {
154+
return err
155+
}
156+
if len(events) == 0 {
157+
continue
158+
}
159+
160+
if err := processEvents(events, partitionClient); err != nil {
161+
return err
162+
}
163+
164+
if err := partitionClient.UpdateCheckpoint(context.TODO(), events[len(events)-1], nil); err != nil {
165+
return err
166+
}
167+
}
168+
}
169+
170+
func shutdownPartitionResources(partitionClient *azeventhubs.ProcessorPartitionClient) {
171+
if err := partitionClient.Close(context.TODO()); err != nil {
172+
panic(err)
173+
}
174+
}
175+
176+
func initializePartitionResources(partitionID string) error {
177+
fmt.Printf("Initializing resources for partition %s\n", partitionID)
178+
return nil
179+
}
180+
181+
// This is very much like the old processEvents function
182+
func processEvents(events []*azeventhubs.ReceivedEventData, partitionClient *azeventhubs.ProcessorPartitionClient) error {
183+
for _, event := range events {
184+
185+
186+
// fmt.Printf("Processing event: %v\n", event.EventData())
187+
}
188+
return nil
189+
}
190+
*/

collector/components/azureeventhubreceiver/azureresourcelogs_unmarshaler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
package azureeventhubreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/azureeventhubreceiver"
55

66
import (
7-
"github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs"
87
"go.opentelemetry.io/collector/component"
98
"go.opentelemetry.io/collector/pdata/plog"
109
"go.uber.org/zap"
1110

11+
"github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs"
1212
"github.com/open-telemetry/opentelemetry-collector-contrib/pkg/translator/azure"
1313
)
1414

collector/components/azureeventhubreceiver/eventhubhandler.go

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,13 @@ import (
1212

1313
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
1414
"github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs"
15+
"github.com/Azure/azure-sdk-for-go/sdk/messaging/azeventhubs/checkpoints"
16+
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container"
1517
"go.opentelemetry.io/collector/component"
1618
"go.opentelemetry.io/collector/receiver"
1719
"go.uber.org/zap"
1820
)
1921

20-
const (
21-
batchCount = 100
22-
)
23-
2422
type eventHandler interface {
2523
run(ctx context.Context, host component.Host) error
2624
close(ctx context.Context) error
@@ -40,11 +38,7 @@ type consumerClientWrapperImpl struct {
4038
}
4139

4240
func newConsumerClientWrapperImplementation(cfg *Config) (*consumerClientWrapperImpl, error) {
43-
splits := strings.Split(cfg.Connection, "/")
44-
eventhubName := splits[len(splits)-1]
45-
// if that didn't work it's ok as the SDK will try to parse it to create the client
46-
47-
consumerClient, err := azeventhubs.NewConsumerClientFromConnectionString(cfg.Connection, eventhubName, cfg.ConsumerGroup, nil)
41+
consumerClient, err := azeventhubs.NewConsumerClientFromConnectionString(cfg.Connection, cfg.EventHubName, cfg.ConsumerGroup, nil)
4842
if err != nil {
4943
return nil, err
5044
}
@@ -61,7 +55,7 @@ func (c *consumerClientWrapperImpl) GetPartitionProperties(ctx context.Context,
6155
return c.consumerClient.GetPartitionProperties(ctx, partitionID, options)
6256
}
6357

64-
func (c *consumerClientWrapperImpl) NewConsumer(_ context.Context, _ *azeventhubs.ConsumerClientOptions) (*azeventhubs.ConsumerClient, error) {
58+
func (c *consumerClientWrapperImpl) NewConsumer(ctx context.Context, options *azeventhubs.ConsumerClientOptions) (*azeventhubs.ConsumerClient, error) {
6559
return c.consumerClient, nil
6660
}
6761

@@ -74,6 +68,7 @@ func (c *consumerClientWrapperImpl) Close(ctx context.Context) error {
7468
}
7569

7670
type eventhubHandler struct {
71+
processor *azeventhubs.Processor
7772
consumerClient consumerClientWrapper
7873
dataConsumer dataConsumer
7974
config *Config
@@ -94,7 +89,7 @@ func newEventhubHandler(config *Config, settings receiver.CreateSettings) *event
9489
return &eventhubHandler{
9590
config: config,
9691
settings: settings,
97-
useProcessor: true,
92+
useProcessor: false,
9893
}
9994
}
10095

@@ -109,33 +104,25 @@ func (h *eventhubHandler) init(ctx context.Context) error {
109104
}
110105

111106
func (h *eventhubHandler) run(ctx context.Context, host component.Host) error {
112-
ctx, h.cancel = context.WithCancel(ctx)
113107
if h.useProcessor {
114-
return h.runWithProcessor(ctx, host)
108+
return h.runWithProcessor(ctx)
115109
}
116110
return h.runWithConsumerClient(ctx, host)
117111
}
118-
func (h *eventhubHandler) runWithProcessor(ctx context.Context, host component.Host) error {
119-
checkpointStore, err := createCheckpointStore(ctx, host, h.config, h.settings)
112+
113+
func (h *eventhubHandler) runWithProcessor(ctx context.Context) error {
114+
checkpointStore, err := createCheckpointStore(h.config.StorageConnection, h.config.StorageContainer)
120115
if err != nil {
121-
h.settings.Logger.Debug("Error creating CheckpointStore", zap.Error(err))
122116
return err
123117
}
124118

125-
consumerClientImpl, ok := h.consumerClient.(*consumerClientWrapperImpl)
126-
if !ok {
127-
// we're in a testing environment
128-
return nil
129-
}
130-
131-
processor, err := azeventhubs.NewProcessor(consumerClientImpl.consumerClient, checkpointStore, nil)
119+
processor, err := azeventhubs.NewProcessor(h.consumerClient.(*consumerClientWrapperImpl).consumerClient, checkpointStore, nil)
132120
if err != nil {
133-
h.settings.Logger.Debug("Error creating Processor", zap.Error(err))
134121
return err
135122
}
136123

137-
processorCtx, processorCancel := context.WithCancel(ctx)
138124
go h.dispatchPartitionClients(processor)
125+
processorCtx, processorCancel := context.WithCancel(ctx)
139126
defer processorCancel()
140127

141128
return processor.Run(processorCtx)
@@ -166,7 +153,7 @@ func (h *eventhubHandler) processEventsForPartition(partitionClient *azeventhubs
166153

167154
for {
168155
receiveCtx, cancelReceive := context.WithTimeout(context.TODO(), time.Minute)
169-
events, err := partitionClient.ReceiveEvents(receiveCtx, 100, nil)
156+
events, err := partitionClient.ReceiveEvents(receiveCtx, h.config.BatchCount, nil)
170157
cancelReceive()
171158

172159
if err != nil && !errors.Is(err, context.DeadlineExceeded) {
@@ -193,7 +180,7 @@ func (h *eventhubHandler) processEventsForPartition(partitionClient *azeventhubs
193180
}
194181
}
195182

196-
func (h *eventhubHandler) runWithConsumerClient(ctx context.Context, _ component.Host) error {
183+
func (h *eventhubHandler) runWithConsumerClient(ctx context.Context, host component.Host) error {
197184
if h.consumerClient == nil {
198185
if err := h.init(ctx); err != nil {
199186
return err
@@ -231,7 +218,11 @@ func (h *eventhubHandler) setupPartition(ctx context.Context, partitionID string
231218
if cc == nil {
232219
return errors.New("failed to initialize consumer client")
233220
}
234-
defer cc.Close(ctx)
221+
defer func() {
222+
if cc != nil {
223+
cc.Close(ctx)
224+
}
225+
}()
235226

236227
pcOpts := &azeventhubs.PartitionClientOptions{
237228
StartPosition: azeventhubs.StartPosition{
@@ -258,12 +249,15 @@ func (h *eventhubHandler) setupPartition(ctx context.Context, partitionID string
258249
}
259250

260251
func (h *eventhubHandler) receivePartitionEvents(ctx context.Context, pc *azeventhubs.PartitionClient) {
252+
var wait = 1
261253
for {
262-
rcvCtx, rcvCtxCancel := context.WithTimeout(context.TODO(), time.Second*10)
263-
events, err := pc.ReceiveEvents(rcvCtx, batchCount, nil)
264-
rcvCtxCancel()
265-
if err != nil && !errors.Is(err, context.DeadlineExceeded) {
266-
h.settings.Logger.Error("Error receiving events", zap.Error(err))
254+
rcvCtx, _ := context.WithTimeout(context.TODO(), time.Second*10)
255+
events, err := pc.ReceiveEvents(rcvCtx, h.config.BatchCount, nil)
256+
if err != nil {
257+
h.settings.Logger.Error("Error receiving event", zap.Error(err))
258+
time.Sleep(time.Duration(wait) * time.Second)
259+
wait *= 2
260+
continue
267261
}
268262

269263
for _, event := range events {
@@ -297,3 +291,11 @@ func (h *eventhubHandler) close(ctx context.Context) error {
297291
func (h *eventhubHandler) setDataConsumer(dataConsumer dataConsumer) {
298292
h.dataConsumer = dataConsumer
299293
}
294+
295+
func createCheckpointStore(storageConnectionString, containerName string) (azeventhubs.CheckpointStore, error) {
296+
azBlobContainerClient, err := container.NewClientFromConnectionString(storageConnectionString, containerName, nil)
297+
if err != nil {
298+
return nil, err
299+
}
300+
return checkpoints.NewBlobStore(azBlobContainerClient, nil)
301+
}

0 commit comments

Comments
 (0)