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  }