github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/clients/pkg/promtail/targets/kafka/topics.go (about)

     1  package kafka
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"regexp"
     7  	"sort"
     8  )
     9  
    10  type topicClient interface {
    11  	RefreshMetadata(topics ...string) error
    12  	Topics() ([]string, error)
    13  }
    14  
    15  type topicManager struct {
    16  	client topicClient
    17  
    18  	patterns []*regexp.Regexp
    19  	matches  []string
    20  }
    21  
    22  // newTopicManager fetches topics and returns matchings one based on list of requested topics.
    23  // If a topic starts with a '^' it is treated as a regexp and can match multiple topics.
    24  func newTopicManager(client topicClient, topics []string) (*topicManager, error) {
    25  	var (
    26  		patterns []*regexp.Regexp
    27  		matches  []string
    28  	)
    29  	for _, t := range topics {
    30  		if len(t) == 0 {
    31  			return nil, errors.New("invalid empty topic")
    32  		}
    33  		if t[0] != '^' {
    34  			matches = append(matches, t)
    35  		}
    36  		re, err := regexp.Compile(t)
    37  		if err != nil {
    38  			return nil, fmt.Errorf("invalid topic pattern: %w", err)
    39  		}
    40  		patterns = append(patterns, re)
    41  	}
    42  	return &topicManager{
    43  		client:   client,
    44  		patterns: patterns,
    45  		matches:  matches,
    46  	}, nil
    47  }
    48  
    49  func (tm *topicManager) Topics() ([]string, error) {
    50  	if err := tm.client.RefreshMetadata(); err != nil {
    51  		return nil, err
    52  	}
    53  	topics, err := tm.client.Topics()
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  
    58  	result := make([]string, 0, len(topics))
    59  
    60  Outer:
    61  	for _, topic := range topics {
    62  		for _, m := range tm.matches {
    63  			if m == topic {
    64  				result = append(result, topic)
    65  				continue Outer
    66  			}
    67  		}
    68  		for _, p := range tm.patterns {
    69  			if p.MatchString(topic) {
    70  				result = append(result, topic)
    71  				continue Outer
    72  			}
    73  		}
    74  	}
    75  
    76  	sort.Strings(result)
    77  	return result, nil
    78  }