github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/pkg/promtail/targets/kafka/target_test.go (about) 1 package kafka 2 3 import ( 4 "context" 5 "fmt" 6 "sync" 7 "testing" 8 "time" 9 10 "github.com/Shopify/sarama" 11 "github.com/prometheus/common/model" 12 "github.com/prometheus/prometheus/model/relabel" 13 "github.com/stretchr/testify/require" 14 "go.uber.org/atomic" 15 16 "github.com/grafana/loki/clients/pkg/promtail/client/fake" 17 ) 18 19 // Consumergroup handler 20 type testConsumerGroupHandler struct { 21 handler sarama.ConsumerGroupHandler 22 ctx context.Context 23 topics []string 24 25 returnErr error 26 27 consuming atomic.Bool 28 } 29 30 func (c *testConsumerGroupHandler) Consume(ctx context.Context, topics []string, handler sarama.ConsumerGroupHandler) error { 31 if c.returnErr != nil { 32 return c.returnErr 33 } 34 c.ctx = ctx 35 c.topics = topics 36 c.handler = handler 37 c.consuming.Store(true) 38 <-ctx.Done() 39 c.consuming.Store(false) 40 return nil 41 } 42 43 func (c testConsumerGroupHandler) Errors() <-chan error { 44 return nil 45 } 46 47 func (c testConsumerGroupHandler) Close() error { 48 return nil 49 } 50 51 type testSession struct { 52 markedMessage []*sarama.ConsumerMessage 53 } 54 55 func (s *testSession) Claims() map[string][]int32 { return nil } 56 func (s *testSession) MemberID() string { return "foo" } 57 func (s *testSession) GenerationID() int32 { return 10 } 58 func (s *testSession) MarkOffset(topic string, partition int32, offset int64, metadata string) {} 59 func (s *testSession) Commit() {} 60 func (s *testSession) ResetOffset(topic string, partition int32, offset int64, metadata string) {} 61 func (s *testSession) MarkMessage(msg *sarama.ConsumerMessage, metadata string) { 62 s.markedMessage = append(s.markedMessage, msg) 63 } 64 func (s *testSession) Context() context.Context { return context.Background() } 65 66 type testClaim struct { 67 topic string 68 partition int32 69 offset int64 70 messages chan *sarama.ConsumerMessage 71 } 72 73 func newTestClaim(topic string, partition int32, offset int64) *testClaim { 74 return &testClaim{ 75 topic: topic, 76 partition: partition, 77 offset: offset, 78 messages: make(chan *sarama.ConsumerMessage), 79 } 80 } 81 82 func (t *testClaim) Topic() string { return t.topic } 83 func (t *testClaim) Partition() int32 { return t.partition } 84 func (t *testClaim) InitialOffset() int64 { return t.offset } 85 func (t *testClaim) HighWaterMarkOffset() int64 { return 0 } 86 func (t *testClaim) Messages() <-chan *sarama.ConsumerMessage { return t.messages } 87 func (t *testClaim) Send(m *sarama.ConsumerMessage) { 88 t.messages <- m 89 } 90 91 func (t *testClaim) Stop() { 92 close(t.messages) 93 } 94 95 func Test_TargetRun(t *testing.T) { 96 tc := []struct { 97 name string 98 inMessageKey string 99 inLS model.LabelSet 100 inDiscoveredLS model.LabelSet 101 relabels []*relabel.Config 102 expectedLS model.LabelSet 103 }{ 104 { 105 name: "no relabel config", 106 inMessageKey: "foo", 107 inDiscoveredLS: model.LabelSet{"__meta_kafka_foo": "bar"}, 108 inLS: model.LabelSet{"buzz": "bazz"}, 109 relabels: nil, 110 expectedLS: model.LabelSet{"buzz": "bazz"}, 111 }, 112 { 113 name: "message key with relabel config", 114 inMessageKey: "foo", 115 inDiscoveredLS: model.LabelSet{"__meta_kafka_foo": "bar"}, 116 inLS: model.LabelSet{"buzz": "bazz"}, 117 relabels: []*relabel.Config{ 118 { 119 SourceLabels: model.LabelNames{"__meta_kafka_message_key"}, 120 Regex: relabel.MustNewRegexp("(.*)"), 121 TargetLabel: "message_key", 122 Replacement: "$1", 123 Action: "replace", 124 }, 125 }, 126 expectedLS: model.LabelSet{"buzz": "bazz", "message_key": "foo"}, 127 }, 128 { 129 name: "no message key with relabel config", 130 inMessageKey: "", 131 inDiscoveredLS: model.LabelSet{"__meta_kafka_foo": "bar"}, 132 inLS: model.LabelSet{"buzz": "bazz"}, 133 relabels: []*relabel.Config{ 134 { 135 SourceLabels: model.LabelNames{"__meta_kafka_message_key"}, 136 Regex: relabel.MustNewRegexp("(.*)"), 137 TargetLabel: "message_key", 138 Replacement: "$1", 139 Action: "replace", 140 }, 141 }, 142 expectedLS: model.LabelSet{"buzz": "bazz", "message_key": "none"}, 143 }, 144 } 145 for _, tt := range tc { 146 t.Run(tt.name, func(t *testing.T) { 147 session, claim := &testSession{}, newTestClaim("footopic", 10, 12) 148 var closed bool 149 fc := fake.New( 150 func() { 151 closed = true 152 }, 153 ) 154 tg := NewTarget(session, claim, tt.inDiscoveredLS, tt.inLS, tt.relabels, fc, true) 155 156 var wg sync.WaitGroup 157 wg.Add(1) 158 go func() { 159 defer wg.Done() 160 tg.run() 161 }() 162 163 for i := 0; i < 10; i++ { 164 claim.Send(&sarama.ConsumerMessage{ 165 Timestamp: time.Unix(0, int64(i)), 166 Value: []byte(fmt.Sprintf("%d", i)), 167 Key: []byte(tt.inMessageKey), 168 }) 169 } 170 claim.Stop() 171 wg.Wait() 172 re := fc.Received() 173 174 require.Len(t, session.markedMessage, 10) 175 require.Len(t, re, 10) 176 require.True(t, closed) 177 for _, e := range re { 178 require.Equal(t, tt.expectedLS.String(), e.Labels.String()) 179 } 180 }) 181 } 182 }