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

Add MetricsQueryService grcp handler #3091

Merged
merged 3 commits into from
Jun 16, 2021

Conversation

albertteoh
Copy link
Contributor

Signed-off-by: albertteoh albert.teoh@logz.io

Which problem is this PR solving?

Short description of the changes

  • Adds the gRPC handler.

Comment on lines -45 to -47
defaultDependencyLookbackDuration = time.Hour * 24
defaultTraceQueryLookbackDuration = time.Hour * 24 * 2
defaultAPIPrefix = "api"
Copy link
Contributor Author

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]
Copy link
Contributor Author

@albertteoh albertteoh Jun 15, 2021

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.

}

// 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 {
Copy link
Contributor Author

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?

Copy link
Member

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.

Copy link
Member

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
Copy link

codecov bot commented Jun 15, 2021

Codecov Report

Merging #3091 (a26afca) into master (c9d6957) will increase coverage by 0.09%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            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     
Impacted Files Coverage Δ
cmd/query/app/http_handler.go 100.00% <ø> (ø)
cmd/query/app/grpc_handler.go 98.62% <100.00%> (+1.28%) ⬆️
cmd/query/app/server.go 97.20% <100.00%> (+1.58%) ⬆️
cmd/query/app/static_handler.go 96.77% <0.00%> (+1.61%) ⬆️
pkg/config/tlscfg/cert_watcher.go 94.80% <0.00%> (+2.59%) ⬆️

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 c9d6957...a26afca. Read the comment docs.

Signed-off-by: albertteoh <albert.teoh@logz.io>
@albertteoh albertteoh marked this pull request as ready for review June 15, 2021 11:25
@albertteoh albertteoh requested a review from a team as a code owner June 15, 2021 11:25
@yurishkuro yurishkuro changed the title Add grcp handler Add MetricsQueryService grcp handler Jun 15, 2021
@@ -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) {
Copy link
Member

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.

Copy link
Member

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

Copy link
Contributor Author

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 {
case errors.Is(err, disabled.ErrDisabled):
return errGRPCMetricsQueryDisabled
case errors.Is(err, errMissingServiceNames), errors.Is(err, errMissingQuantile):
Copy link
Member

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?

"github.com/jaegertracing/jaeger/storage/spanstore"
)

// clock is a wrapper around the time package to allow mocking of the current time.
Copy link
Member

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

yurishkuro
yurishkuro previously approved these changes Jun 15, 2021
Copy link
Member

@yurishkuro yurishkuro left a 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 <albert.teoh@logz.io>
Signed-off-by: albertteoh <albert.teoh@logz.io>
@@ -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) {
Copy link
Contributor Author

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.

Comment on lines +269 to +276
switch v := r.(type) {
case *metrics.GetLatenciesRequest:
baseRequest = v.BaseRequest
case *metrics.GetCallRatesRequest:
baseRequest = v.BaseRequest
case *metrics.GetErrorRatesRequest:
baseRequest = v.BaseRequest
}
Copy link
Contributor Author

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.

@yurishkuro yurishkuro merged commit e15c981 into jaegertracing:master Jun 16, 2021
@albertteoh albertteoh deleted the 2954-grpc-handler branch June 16, 2021 09:46
@albertteoh
Copy link
Contributor Author

Thanks Yuri!

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.

None yet

3 participants