Skip to content

Add metric health schema to Entities #50

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

Merged
merged 32 commits into from
Jan 8, 2021
Merged

Conversation

pavan-traceable
Copy link
Contributor

@pavan-traceable pavan-traceable commented Dec 2, 2020

Add baseline for metrics for entities

Description

Baseline, lower bound and upper bound values for entity metrics and used gateway service implementation.

Testing

Please describe the tests that you ran to verify your changes. Please summarize what did you test and what needs to be tested e.g. deployed and tested helm chart locally.

Checklist:

  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • Any dependent changes have been merged and published in downstream modules

Documentation

Make sure that you have documented corresponding changes in this repository or hypertrace docs repo if required.

@pavan-traceable pavan-traceable requested a review from a team as a code owner December 2, 2020 16:07
implements MetricContainer {

private final Map<Duration, List<MetricInterval>> metricSeriesMap;

ConvertedMetricContainer(
Map<MetricLookupMapKey, MetricAggregation> metricAggregationMap,
Map<MetricLookupMapKey, BaselineMetricAggregation> metricAggregationMap,
Copy link
Contributor

Choose a reason for hiding this comment

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

BaselineMetricAggregation implies something totally different from the existing MetricAggregation. Are you sure you want to do a replace/rename instead of an augmentation to the existing users of MetricAggregation with a different object of the type BaselineMetricAggregation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tim-mwangi I didn't understand. Can you please illustrate more ?

@pavan-traceable
Copy link
Contributor Author

@tim-mwangi @aaron-steinfeld thanks for the quick review. This patch is not complete it needs refactoring i should have updated description well, i have just updated just to verify with you guys regarding schema changes. Since generics is not supported in graphql so want to check whether schema changes fine or not.

@aaron-steinfeld
Copy link
Contributor

@tim-mwangi @aaron-steinfeld thanks for the quick review. This patch is not complete it needs refactoring i should have updated description well, i have just updated just to verify with you guys regarding schema changes. Since generics is not supported in graphql so want to check whether schema changes fine or not.

Just to clarify, generics can be used (and should be, for enforcing keeping objects in sync) - they just need to be reified in child interfaces so the reflection code can find the appropriate types.

Pavan Kumar Kolamuri and others added 6 commits December 18, 2020 16:56
@pavan-traceable
Copy link
Contributor Author

@aaron-steinfeld Please review the implementation and API changes. Some minor things pending will address along with review comments. Not able to find placeholder to calculate Health to metrics, please suggest the right place.

private final MetricBaselineAggregationConverter baselineAggregationConverter;

@Inject
BaselineIntervalListContainer(MetricBaselineAggregationConverter baselineAggregationConverter) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this looks like mostly copy paste from the existing interval list converter - how much of the logic could be shared? I expect most of it could go in a base class that is just parameterized with the specific impementation builders.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will raise a jira and do this refactoring later.

this.endTime = intervalTimeRange.getEndTime();
}

// TODO Fix this
Copy link
Contributor

Choose a reason for hiding this comment

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

Assume this is due to the null below?

public Single<Map<Duration, List<BaselineMetricInterval>>> convert(
List<MetricSeriesRequest> metricSeriesRequests,
Map<String, BaselineMetricSeries> baselineMetricSeriesMap) {
return Observable.fromIterable(metricSeriesRequests)
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as intervallist, this looks like copy paste that could be shared.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As i said earlier will do refactoring in next iteration since it already became big patch.

@aaron-steinfeld
Copy link
Contributor

@aaron-steinfeld Please review the implementation and API changes. Some minor things pending will address along with review comments. Not able to find placeholder to calculate Health to metrics, please suggest the right place.

Lots of comments, many of them nit/style. Can we please first format this code with google style (in 1 standalone commit), then merge in main (again standalone), then fix any compilation issues, since it's not even running in CI and I'm fairly sure it won't compile as is.

As to health, my recommendation would be to omit it (from the schema as well as the implementation). We need to be far more iterative with this, and we can easily add health in a later round - the scope of this is already very large and difficult to review.

@jcchavezs
Copy link

Lots of comments, many of them nit/style. Can we please first format this code with google style (in 1 standalone commit), then merge in main (again standalone), then fix any compilation issues, since it's not even running in CI and I'm fairly sure it won't compile as is.

My 2p in here. Could we add a GH action checking this by default? That way we avoid unrelated changes in PRs due to formatting. cc @JBAhire

As to health, my recommendation would be to omit it (from the schema as well as the implementation). We need to be far more iterative with this, and we can easily add health in a later round - the scope of this is already very large and difficult to review.

Yes please, this PR is already big. Maybe it is easier to break it up in small PRs? Otherwise reviewing this is almost impossible and it is easy to make mistakes. Please consider either merge smaller PRs against main or another feature branch as they are easier to review.

@pavan-traceable
Copy link
Contributor Author

Compilation issues are because it depends on gateway-service which is not merged yet.

@JBAhire
Copy link
Member

JBAhire commented Jan 3, 2021

Related to formating on CI: hypertrace/document-store#24

Will incorporate this. Thanks @jcchavezs :)

@pavan-traceable
Copy link
Contributor Author

@jcchavezs We can divide this PR into API and implementation, but API part is small compared to implementation. From next time i will try to push small PR's, if possible

Pavan Kumar Kolamuri added 2 commits January 4, 2021 13:16
}
}

static class MetricBaselineAggregationDefaultInstance implements MetricBaselineAggregation {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@aaron-steinfeld Please suggest if this can be improved further.

Copy link
Contributor

Choose a reason for hiding this comment

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

My suggestion would be to remove the default one - if Baseline is null, convert should not be called, since that indicates no baseline object was either requested or returned from the server. The behavior I'd expect for null responses for requested data is described below.

Also to make MetricBaselineAggregationImpl a simple value class like most of our converted classes, handling the unpacking of it in the converter itself rather than the value class.
Example:

  @lombok.Value
  @Accessors(fluent = true)
  private static class MetricBaselineAggregationImpl implements MetricBaselineAggregation {
    Double value;
    Double lowerBound;
    Double upperBound;
  }

In terms of nulls, we want the following behavior:
if I request an aggregation, but there's no data in the time range (this can only happen in the recently added, time agnostic mode):

  // Request
  sum {
     value
  }

  // No data response
 { 
   sum: {
     value: null 
   }
 }

Extending that to baselines, I'd expect:

  sum {
     value
     baseline {
         value
         lowerBound
         upperBound
      }
 }
// No baseline response
 { 
   sum: { 
      value: 42 
      baseline: null // the object, not the contents
   }
 }

@pavan-traceable
Copy link
Contributor Author

@aaron-steinfeld I have updated all comments. Please review.

.flatMap(baselineRequest -> baselineProvider.makeRequest(request.resultSetRequest().context(), baselineRequest))
.flatMap(baselineResponse -> this.entityConverter.convert(request, serverResponse, baselineResponse))));
.flatMap(
serverRequest ->
Copy link
Contributor

Choose a reason for hiding this comment

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

Correct, it's not a ton of complexity (although triconverter doesn't appear to be defined anywhere in this PR, one of the reasons it doesn't compile), it just saves a level of nesting here. The reason the nesting is required is we're doing one operation at a time but not carrying the previous results with us - so using a result container both saves nesting and removes the need for the new converter interface. It's not required, but I do think it would be nice to remove the nesting one way or another to improve readability. Another way of doing that is just breaking out the calls into different methods rather than doing them inline. For example, creating a new method like makeBaselineAndEntityRequests

}
}

static class MetricBaselineAggregationDefaultInstance implements MetricBaselineAggregation {
Copy link
Contributor

Choose a reason for hiding this comment

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

My suggestion would be to remove the default one - if Baseline is null, convert should not be called, since that indicates no baseline object was either requested or returned from the server. The behavior I'd expect for null responses for requested data is described below.

Also to make MetricBaselineAggregationImpl a simple value class like most of our converted classes, handling the unpacking of it in the converter itself rather than the value class.
Example:

  @lombok.Value
  @Accessors(fluent = true)
  private static class MetricBaselineAggregationImpl implements MetricBaselineAggregation {
    Double value;
    Double lowerBound;
    Double upperBound;
  }

In terms of nulls, we want the following behavior:
if I request an aggregation, but there's no data in the time range (this can only happen in the recently added, time agnostic mode):

  // Request
  sum {
     value
  }

  // No data response
 { 
   sum: {
     value: null 
   }
 }

Extending that to baselines, I'd expect:

  sum {
     value
     baseline {
         value
         lowerBound
         upperBound
      }
 }
// No baseline response
 { 
   sum: { 
      value: 42 
      baseline: null // the object, not the contents
   }
 }

import org.hypertrace.graphql.metric.schema.BaselineMetricInterval;
import org.hypertrace.graphql.metric.schema.BaselinedMetricAggregation;
import org.hypertrace.graphql.metric.schema.MetricBaselineAggregation;

Copy link
Contributor

Choose a reason for hiding this comment

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

should be no gap in imports - please use the google formatter and update your IDE! We should enforce this in CI too, but all of our projects follow the same formatter regardless.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes did that sometime back, even though i formatted entire code using google formatter, it didnt deleted that gap. Anyway i am deleting myself.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm - did you use the intellij format config or the plugin? I know the format file isn't able to capture the full style, the plugin might have shortcomings too - I use both, but that feels excessive. We'll revisit this with the push to enforce this in CI (and maybe add a gradle task)

@pavan-traceable
Copy link
Contributor Author

@aaron-steinfeld I have addressed all your comments, only thing pending is removing nesting inline in GatewayServiceEntityDao which can be done in next iteration. UI team is already blocked on this. Lets push this, but before that we should merge hypertrace/hypertrace-core-graphql#43

@pavan-traceable
Copy link
Contributor Author

I have updated core-graphql still it is showing conflicts.


@Override
public Double value() {
return metricAggregation.value();
public MetricBaselineAggregation baseline() {
Copy link
Contributor

Choose a reason for hiding this comment

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

These two methods shouldn't be needed with the lombok annotations above

public Double value() {
return null;
}
static final MetricBaselineAggregation EMPTY =
Copy link
Contributor

Choose a reason for hiding this comment

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

So this would end up with null values rather than a null baseline object - we can go with that and revisit

@aaron-steinfeld
Copy link
Contributor

I have updated core-graphql still it is showing conflicts.

You'll need to rebase this repo off main, then update core-graphql. Once that's done, I think we're good at a good iteration point.

@codecov
Copy link

codecov bot commented Jan 8, 2021

Codecov Report

Merging #50 (ef9fc9b) into main (41dd991) will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff            @@
##               main      #50   +/-   ##
=========================================
  Coverage     80.55%   80.55%           
  Complexity        2        2           
=========================================
  Files             2        2           
  Lines            36       36           
=========================================
  Hits             29       29           
  Misses            7        7           
Flag Coverage Δ Complexity Δ
unit 80.55% <ø> (ø) 0.00 <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.


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 41dd991...ef9fc9b. Read the comment docs.

@github-actions

This comment has been minimized.

@pavan-traceable
Copy link
Contributor Author

@aaron-steinfeld All checks have passed.

@pavan-traceable pavan-traceable merged commit 3d0decb into main Jan 8, 2021
@pavan-traceable pavan-traceable deleted the master/feature/healthapi branch January 8, 2021 15:27
@github-actions
Copy link

github-actions bot commented Jan 8, 2021

Unit Test Results

1 files  ±0  1 suites  ±0   1s ⏱️ -1s
1 tests ±0  1 ✔️ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 3d0decb. ± Comparison against base commit 41dd991.

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.

5 participants