github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/storage/stores/series/series_store_utils.go (about)

     1  package series
     2  
     3  import (
     4  	"strings"
     5  	"unicode/utf8"
     6  
     7  	"github.com/prometheus/common/model"
     8  
     9  	"github.com/grafana/loki/pkg/logproto"
    10  	"github.com/grafana/loki/pkg/storage/chunk"
    11  	"github.com/grafana/loki/pkg/storage/config"
    12  	"github.com/grafana/loki/pkg/util"
    13  )
    14  
    15  func filterChunksByTime(from, through model.Time, chunks []chunk.Chunk) []chunk.Chunk {
    16  	filtered := make([]chunk.Chunk, 0, len(chunks))
    17  	for _, chunk := range chunks {
    18  		if chunk.Through < from || through < chunk.From {
    19  			continue
    20  		}
    21  		filtered = append(filtered, chunk)
    22  	}
    23  	return filtered
    24  }
    25  
    26  func filterChunkRefsByTime(from, through model.Time, chunks []logproto.ChunkRef) []logproto.ChunkRef {
    27  	filtered := make([]logproto.ChunkRef, 0, len(chunks))
    28  	for _, chunk := range chunks {
    29  		if chunk.Through < from || through < chunk.From {
    30  			continue
    31  		}
    32  		filtered = append(filtered, chunk)
    33  	}
    34  	return filtered
    35  }
    36  
    37  func labelNamesFromChunks(chunks []chunk.Chunk) []string {
    38  	var result util.UniqueStrings
    39  	for _, c := range chunks {
    40  		for _, l := range c.Metric {
    41  			if l.Name == model.MetricNameLabel {
    42  				continue
    43  			}
    44  
    45  			result.Add(l.Name)
    46  		}
    47  	}
    48  	return result.Strings()
    49  }
    50  
    51  func filterChunksByUniqueFingerprint(s config.SchemaConfig, chunks []chunk.Chunk) ([]chunk.Chunk, []string) {
    52  	filtered := make([]chunk.Chunk, 0, len(chunks))
    53  	keys := make([]string, 0, len(chunks))
    54  	uniqueFp := map[model.Fingerprint]struct{}{}
    55  
    56  	for _, chunk := range chunks {
    57  		if _, ok := uniqueFp[chunk.FingerprintModel()]; ok {
    58  			continue
    59  		}
    60  		filtered = append(filtered, chunk)
    61  		keys = append(keys, s.ExternalKey(chunk.ChunkRef))
    62  		uniqueFp[chunk.FingerprintModel()] = struct{}{}
    63  	}
    64  	return filtered, keys
    65  }
    66  
    67  func filterChunkRefsByUniqueFingerprint(s config.SchemaConfig, chunks []logproto.ChunkRef) ([]chunk.Chunk, []string) {
    68  	filtered := make([]chunk.Chunk, 0, len(chunks))
    69  	keys := make([]string, 0, len(chunks))
    70  	uniqueFp := map[model.Fingerprint]struct{}{}
    71  
    72  	for _, c := range chunks {
    73  		if _, ok := uniqueFp[c.FingerprintModel()]; ok {
    74  			continue
    75  		}
    76  		filtered = append(filtered, chunk.Chunk{
    77  			ChunkRef: c,
    78  		})
    79  		keys = append(keys, s.ExternalKey(c))
    80  		uniqueFp[c.FingerprintModel()] = struct{}{}
    81  	}
    82  	return filtered, keys
    83  }
    84  
    85  func uniqueStrings(cs []string) []string {
    86  	if len(cs) == 0 {
    87  		return []string{}
    88  	}
    89  
    90  	result := make([]string, 1, len(cs))
    91  	result[0] = cs[0]
    92  	i, j := 0, 1
    93  	for j < len(cs) {
    94  		if result[i] == cs[j] {
    95  			j++
    96  			continue
    97  		}
    98  		result = append(result, cs[j])
    99  		i++
   100  		j++
   101  	}
   102  	return result
   103  }
   104  
   105  func intersectStrings(left, right []string) []string {
   106  	var (
   107  		i, j   = 0, 0
   108  		result = []string{}
   109  	)
   110  	for i < len(left) && j < len(right) {
   111  		if left[i] == right[j] {
   112  			result = append(result, left[i])
   113  		}
   114  
   115  		if left[i] < right[j] {
   116  			i++
   117  		} else {
   118  			j++
   119  		}
   120  	}
   121  	return result
   122  }
   123  
   124  // Bitmap used by func isRegexMetaCharacter to check whether a character needs to be escaped.
   125  var regexMetaCharacterBytes [16]byte
   126  
   127  // isRegexMetaCharacter reports whether byte b needs to be escaped.
   128  func isRegexMetaCharacter(b byte) bool {
   129  	return b < utf8.RuneSelf && regexMetaCharacterBytes[b%16]&(1<<(b/16)) != 0
   130  }
   131  
   132  func init() {
   133  	for _, b := range []byte(`.+*?()|[]{}^$`) {
   134  		regexMetaCharacterBytes[b%16] |= 1 << (b / 16)
   135  	}
   136  }
   137  
   138  // FindSetMatches returns list of values that can be equality matched on.
   139  // copied from Prometheus querier.go, removed check for Prometheus wrapper.
   140  func FindSetMatches(pattern string) []string {
   141  	escaped := false
   142  	sets := []*strings.Builder{{}}
   143  	for i := 0; i < len(pattern); i++ {
   144  		if escaped {
   145  			switch {
   146  			case isRegexMetaCharacter(pattern[i]):
   147  				sets[len(sets)-1].WriteByte(pattern[i])
   148  			case pattern[i] == '\\':
   149  				sets[len(sets)-1].WriteByte('\\')
   150  			default:
   151  				return nil
   152  			}
   153  			escaped = false
   154  		} else {
   155  			switch {
   156  			case isRegexMetaCharacter(pattern[i]):
   157  				if pattern[i] == '|' {
   158  					sets = append(sets, &strings.Builder{})
   159  				} else {
   160  					return nil
   161  				}
   162  			case pattern[i] == '\\':
   163  				escaped = true
   164  			default:
   165  				sets[len(sets)-1].WriteByte(pattern[i])
   166  			}
   167  		}
   168  	}
   169  	matches := make([]string, 0, len(sets))
   170  	for _, s := range sets {
   171  		if s.Len() > 0 {
   172  			matches = append(matches, s.String())
   173  		}
   174  	}
   175  	return matches
   176  }