Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Detected labels - get and filter labels from ingesters #12432

Merged
merged 11 commits into from
Apr 3, 2024
37 changes: 37 additions & 0 deletions pkg/ingester/ingester.go
Original file line number Diff line number Diff line change
Expand Up @@ -1371,3 +1371,40 @@ func (i *Ingester) GetDetectedFields(_ context.Context, _ *logproto.DetectedFiel
},
}, nil
}

// GetDetectedLabels returns map of detected labels and unique values from this ingester
func (i *Ingester) GetDetectedLabels(ctx context.Context, req *logproto.DetectedLabelsRequest) (*logproto.LabelToValuesResponse, error) {
userID, err := tenant.TenantID(ctx)
if err != nil {
return nil, err
}

instance, err := i.GetOrCreateInstance(userID)
if err != nil {
return nil, err
}
var matchers []*labels.Matcher
if req.Query != "" {
matchers, err := syntax.ParseMatchers(req.Query, true)
if err != nil {
return nil, err
}
level.Info(i.logger).Log("msg", matchers)
}

labelMap, err := instance.LabelsWithValues(ctx, *req.Start, matchers...)

if err != nil {
return nil, err
}
result := make(map[string]*logproto.UniqueLabelValues)
for label, values := range labelMap {
uniqueValues := make([]string, len(values))
for v := range values {
uniqueValues = append(uniqueValues, v)
}

result[label] = &logproto.UniqueLabelValues{Values: uniqueValues}
}
return &logproto.LabelToValuesResponse{Labels: result}, nil
}
28 changes: 28 additions & 0 deletions pkg/ingester/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,8 @@ func (i *instance) Label(ctx context.Context, req *logproto.LabelRequest, matche
}

labels := util.NewUniqueStrings(0)
// (shantanu) can create a map here to store label names::values and count the unique values
// just return a string to int map
err := i.forMatchingStreams(ctx, *req.Start, matchers, nil, func(s *stream) error {
for _, label := range s.labels {
if req.Values && label.Name == req.Name {
Expand All @@ -583,6 +585,32 @@ func (i *instance) Label(ctx context.Context, req *logproto.LabelRequest, matche
}, nil
}

type UniqueValues map[string]struct{}

// LabelsWithValues returns the label names with all the unique values depending on the request
func (i *instance) LabelsWithValues(ctx context.Context, startTime time.Time, matchers ...*labels.Matcher) (map[string]UniqueValues, error) {
// TODO (shantanu): Figure out how to get the label names from index directly when no matchers are given.

labelMap := make(map[string]UniqueValues)
err := i.forMatchingStreams(ctx, startTime, matchers, nil, func(s *stream) error {
for _, label := range s.labels {
v, exists := labelMap[label.Name]
if !exists {
v = make(map[string]struct{})
}
if label.Value != "" {
v[label.Value] = struct{}{}
}
labelMap[label.Name] = v
}
return nil
})
if err != nil {
return nil, err
}
return labelMap, nil
}

func (i *instance) Series(ctx context.Context, req *logproto.SeriesRequest) (*logproto.SeriesResponse, error) {
groups, err := logql.MatchForSeriesRequest(req.GetGroups())
if err != nil {
Expand Down
Loading
Loading