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

[query] add list tags endpoint #1565

Merged
merged 6 commits into from
May 2, 2019
Merged

[query] add list tags endpoint #1565

merged 6 commits into from
May 2, 2019

Conversation

arnikola
Copy link
Collaborator

@arnikola arnikola commented Apr 17, 2019

Adds this Prometheus endpoint that lists all available tags

@codecov
Copy link

codecov bot commented Apr 17, 2019

Codecov Report

Merging #1565 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@          Coverage Diff           @@
##           master   #1565   +/-   ##
======================================
  Coverage    71.9%   71.9%           
======================================
  Files         950     950           
  Lines       78800   78800           
======================================
  Hits        56666   56666           
  Misses      18431   18431           
  Partials     3703    3703
Flag Coverage Δ
#aggregator 82.3% <0%> (ø) ⬆️
#cluster 85.7% <0%> (ø) ⬆️
#collector 63.7% <0%> (ø) ⬆️
#dbnode 79.9% <0%> (ø) ⬆️
#m3em 73.2% <0%> (ø) ⬆️
#m3ninx 74% <0%> (ø) ⬆️
#m3nsch 51.1% <0%> (ø) ⬆️
#metrics 17.6% <0%> (ø) ⬆️
#msg 74.7% <0%> (ø) ⬆️
#query 66.9% <0%> (ø) ⬆️
#x 86.8% <0%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 120fe60...efe5ed9. Read the comment docs.

@arnikola arnikola mentioned this pull request Apr 17, 2019
13 tasks
@@ -38,6 +38,8 @@ func (m MatchType) String() string {
return "=~"
case MatchNotRegexp:
return "!~"
case MatchAll:
return "*"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this String() method is only used for debugging yea?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah

@@ -304,6 +304,35 @@ func renderDefaultTagCompletionResultsJSON(
return jw.Close()
}

// RenderListTagResultsJSON renders list tag results to json format.
func RenderListTagResultsJSON(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we rely on json.Marshal with the appropriate struct instead of defining our own?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's an issue with a bunch of our stuff; called out removing json.Marshal in #1590

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a response on that issue, for any endpoints where we return a lot of data we should continue using our JSON writers:

One thing interesting about the JSON writers, the major reason in the past we did that is because the default JSON marshaller allocates a lot, however if we have JSON write methods for bytes/strings/whatever other concrete types we can avoid allocations when returning responses (which is what we have today with the current common library streamjson writer).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah was going to write some quick benchmarks when it came time to consider swapping it out; I think our initial thinking here was if we're using this writer internally there's a good reason

return
}

// TODO: Support multiple result types
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you mean?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copied an existing handler; removed this note, this should only support json

logger := logging.WithContext(ctx)
w.Header().Set("Content-Type", "application/json")

query := &storage.CompleteTagsQuery{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you want to add the ability to restrict to only a given set of tag field names?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the implementation of the Prom endpoint here, which expects no args and returns all valid tag names only: https://prometheus.io/docs/prometheus/latest/querying/api/#getting-label-names

w.Header().Set("Content-Type", "application/json")

query := &storage.CompleteTagsQuery{
CompleteNameOnly: true,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more a question: what is this for?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This restricts search results to only give tag names rather than tag names and values

TagMatchers: models.Matchers{{Type: models.MatchAll}},

// NB: necessarily spans entire possible query range.
Start: time.Time{},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is fine for default but should it be overridable from the incoming request?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally yes, but this particular endpoint is intended to work across all time

End: time.Now(),
}

opts := storage.NewFetchOptions()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this might be a silly question: what are these options/how come we can just use the defaults?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default is fine here; for context, this includes:

  • tracing options (could potentially be added)
  • fetch limit (irrelevant for this endpoint)
  • block fetch type (irrelevant for this endpoint - this is used to switch between decompressing blocks as soon as fetched vs keeping fetches as series iterators until applying non-lazy functions)
  • fanout options (this may change in future if we allow a standalone index to use instead of doing our best guess fanout at the moment, but defaults are fine here for virtually all cases; this is mostly here to allow us to override the graphite query path)

Data []string `json:"data"`
}

func TestFind(t *testing.T) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if possible could you add a failure test situation too

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure sounds good

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

}

func TestFind(t *testing.T) {
logging.InitWithCores(nil)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

been trying to push the standard stuff we have for zap now, could you use src/x/test/NewLogger to create the test logger and pass down to the appropriate place

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Called out in #1590 as well; all our other handlers are doing this at the moment, may be nicer to fix them all at once?

Copy link
Collaborator Author

@arnikola arnikola Apr 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're currently using zap for logging; although we may do it in a bit of a weird way with a global zap logger rather than passing it down

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this to #1590 under "General":

Remove use of global Zap logger usage in favor of src/x/instrument logger which uses Zap and use src/x/test/NewLogger in tests

@@ -304,6 +304,35 @@ func renderDefaultTagCompletionResultsJSON(
return jw.Close()
}

// RenderListTagResultsJSON renders list tag results to json format.
func RenderListTagResultsJSON(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, is there a scenario where status isn't success?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No; if it errors, it won't use this render function but rather the default error printer

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point of having a status field then lol

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's expected in the Prom output unfortunately

@@ -0,0 +1,90 @@
// Copyright (c) 2018 Uber Technologies, Inc.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: 2019


const (
// ListTagsURL is the url for listing tags.
ListTagsURL = handler.RoutePrefixV1 + "/labels"
Copy link
Collaborator

@benraskin92 benraskin92 Apr 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: name ListLabelsURL (here and throughout) to be consistent with Prom?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather be consistent internally here; we've been renaming prom label endpoints as tags


func (h *ListTagsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), handler.HeaderKey, r.Header)
logger := logging.WithContext(ctx)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This using the new logging (zap) stuff?

Copy link
Collaborator Author

@arnikola arnikola Apr 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be, same as the other handlers afaik


// execute the query
w := &writer{}
req := &http.Request{
Copy link
Collaborator

@robskillington robskillington Apr 29, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Better to use httptest.NewRequest(...) I think here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this seems much nicer 👍

handler := NewListTagsHandler(store)

// execute the query
w := &writer{}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Better to use httptest.NewRecorder(...) here:
https://play.golang.org/p/y_M3RA0YUDB

And:
https://golang.org/pkg/net/http/httptest/

URL: &url.URL{
RawQuery: "",
},
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same notes about using httptest.NewRecorder(...) and httptest.NewRequest(...) here.

Copy link
Collaborator

@robskillington robskillington left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@arnikola arnikola merged commit e50a400 into master May 2, 2019
@arnikola arnikola deleted the arnikola/list_all_tags branch May 2, 2019 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants