-
Notifications
You must be signed in to change notification settings - Fork 454
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
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1565 +/- ##
======================================
Coverage 71.9% 71.9%
======================================
Files 950 950
Lines 78800 78800
======================================
Hits 56666 56666
Misses 18431 18431
Partials 3703 3703
Continue to review full report at Codecov.
|
@@ -38,6 +38,8 @@ func (m MatchType) String() string { | |||
return "=~" | |||
case MatchNotRegexp: | |||
return "!~" | |||
case MatchAll: | |||
return "*" |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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).
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what do you mean?
There was a problem hiding this comment.
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{ |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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{}, |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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() |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure sounds good
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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 usesrc/x/test/NewLogger
in tests
@@ -304,6 +304,35 @@ func renderDefaultTagCompletionResultsJSON( | |||
return jw.Close() | |||
} | |||
|
|||
// RenderListTagResultsJSON renders list tag results to json format. | |||
func RenderListTagResultsJSON( |
There was a problem hiding this comment.
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
?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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" |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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{ |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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{} |
There was a problem hiding this comment.
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
URL: &url.URL{ | ||
RawQuery: "", | ||
}, | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Adds this Prometheus endpoint that lists all available tags