-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Add MetricsQueryService grcp handler #3091
Add MetricsQueryService grcp handler #3091
Conversation
defaultDependencyLookbackDuration = time.Hour * 24 | ||
defaultTraceQueryLookbackDuration = time.Hour * 24 * 2 | ||
defaultAPIPrefix = "api" |
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.
moved to default_params.go so all defaults are in one file, given they are shared between gRPC and HTTP handlers.
@@ -84,7 +84,7 @@ message MetricsQueryBaseRequest { | |||
message GetLatenciesRequest { | |||
MetricsQueryBaseRequest baseRequest = 1; | |||
// quantile is the quantile to compute from latency histogram metrics. | |||
// Valid range: 0 - 1 (inclusive). | |||
// Valid range: (0, 1] |
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 non-nullable because it's mandatory for the GetLatencies
endpoint. However, if a client fails to provide the Quantile
, its zero value will be used which is 0.0
, which should be caught and error returned.
cmd/query/app/grpc_handler.go
Outdated
} | ||
|
||
// NewGRPCHandler returns a GRPCHandler | ||
func NewGRPCHandler(queryService *querysvc.QueryService, logger *zap.Logger, tracer opentracing.Tracer) *GRPCHandler { | ||
func NewGRPCHandler(queryService *querysvc.QueryService, metricsQueryService querysvc.MetricsQueryService, logger *zap.Logger, tracer opentracing.Tracer, clock clock) *GRPCHandler { |
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.
is it worth adopting the functional options pattern here given the list of params is growing?
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.
Lately I've been trying to stay away from functional options and just use an options/params struct, it's less work to implement and has better discoverability.
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.
In this concrete example, we don't even need any additional struct, just remove this function and initialize GRPCHandler directly
Codecov Report
@@ Coverage Diff @@
## master #3091 +/- ##
==========================================
+ Coverage 95.82% 95.91% +0.09%
==========================================
Files 235 235
Lines 10067 10143 +76
==========================================
+ Hits 9647 9729 +82
+ Misses 348 344 -4
+ Partials 72 70 -2
Continue to review full report at Codecov.
|
Signed-off-by: albertteoh <[email protected]>
2698575
to
313d636
Compare
@@ -177,3 +190,123 @@ func (g *GRPCHandler) GetDependencies(ctx context.Context, r *api_v2.GetDependen | |||
|
|||
return &api_v2.GetDependenciesResponse{Dependencies: dependencies}, nil | |||
} | |||
|
|||
// GetLatencies is the gRPC handler to fetch latency metrics. | |||
func (g *GRPCHandler) GetLatencies(ctx context.Context, r *metrics.GetLatenciesRequest) (*metrics.GetMetricsResponse, error) { |
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.
recently we've seen some tickets showing that apparently with some client libs it's possible to send a request where r==nil, which crashes the server.
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 see you already have this check in g.newBaseQueryParameters, but should call this first then
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, at least the grpc clients generated in this project fail to marshal a nil message over the wire; but I trust in what you've seen from other client libs, so I've added a nil check for the request.
Note, the original nil check in g.newBaseQueryParameters
was just for the MetricsQueryBaseRequest
, which is a common attribute among all the request objects, but it doesn't check the parent request for nil.
cmd/query/app/grpc_handler.go
Outdated
switch { | ||
case errors.Is(err, disabled.ErrDisabled): | ||
return errGRPCMetricsQueryDisabled | ||
case errors.Is(err, errMissingServiceNames), errors.Is(err, errMissingQuantile): |
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.
rather than enumerating, could we check if it's already an instance of status.Error?
cmd/query/app/util.go
Outdated
"github.com/jaegertracing/jaeger/storage/spanstore" | ||
) | ||
|
||
// clock is a wrapper around the time package to allow mocking of the current 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.
You can avoid this type by using the function signature directly func() time.Time
, and then pass time.Now
as main impl
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, sans minor nits
Signed-off-by: albertteoh <[email protected]>
Signed-off-by: albertteoh <[email protected]>
@@ -177,3 +190,123 @@ func (g *GRPCHandler) GetDependencies(ctx context.Context, r *api_v2.GetDependen | |||
|
|||
return &api_v2.GetDependenciesResponse{Dependencies: dependencies}, nil | |||
} | |||
|
|||
// GetLatencies is the gRPC handler to fetch latency metrics. | |||
func (g *GRPCHandler) GetLatencies(ctx context.Context, r *metrics.GetLatenciesRequest) (*metrics.GetMetricsResponse, error) { |
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, at least the grpc clients generated in this project fail to marshal a nil message over the wire; but I trust in what you've seen from other client libs, so I've added a nil check for the request.
Note, the original nil check in g.newBaseQueryParameters
was just for the MetricsQueryBaseRequest
, which is a common attribute among all the request objects, but it doesn't check the parent request for nil.
switch v := r.(type) { | ||
case *metrics.GetLatenciesRequest: | ||
baseRequest = v.BaseRequest | ||
case *metrics.GetCallRatesRequest: | ||
baseRequest = v.BaseRequest | ||
case *metrics.GetErrorRatesRequest: | ||
baseRequest = v.BaseRequest | ||
} |
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.
is there a better way?
The reason for taking this approach is to avoid the same nil check in each of the endpoint handlers (GetLatencies
, etc...) so they can just pass the parent request object in, and have a single place to perform the nil check.
The trade-off is given each of these request objects belong to different types, but I need to access the common BaseRequest
out of each request, a type switch was necessary.
Thanks Yuri! |
Signed-off-by: albertteoh [email protected]
Which problem is this PR solving?
Short description of the changes