Skip to content

[Infra] Replace MetricsUIAggregation in favor of estypes.AggregationsAggregate#190495

Merged
jennypavlova merged 18 commits intoelastic:mainfrom
jennypavlova:190311-infra-replace-metricsuiaggregation-in-favor-of-estypesaggregationsaggregate
Aug 21, 2024
Merged

[Infra] Replace MetricsUIAggregation in favor of estypes.AggregationsAggregate#190495
jennypavlova merged 18 commits intoelastic:mainfrom
jennypavlova:190311-infra-replace-metricsuiaggregation-in-favor-of-estypesaggregationsaggregate

Conversation

@jennypavlova
Copy link
Copy Markdown
Member

@jennypavlova jennypavlova commented Aug 14, 2024

Closes #190311

Summary

This PR replaces MetricsUIAggregation in favor of estypes.AggregationsAggregate. Now the MetricsUIAggregation uses estypes.AggregationsAggregate and the MetricsUIAggregationRT is removed which also allows us to remove the ESAggregationRT. Instead of maintaining the runtime types we now rely on the types provided by elasticsearch.

A follow-up issue will be linked here to address the other aggregation types related changes: #190497

Testing

@jennypavlova jennypavlova added release_note:skip Skip the PR/issue when compiling release notes backport:skip This PR does not require backporting Team:obs-ux-infra_services - DEPRECATED DEPRECATED - Use Team:obs-presentation. labels Aug 14, 2024
@jennypavlova jennypavlova self-assigned this Aug 14, 2024
@obltmachine
Copy link
Copy Markdown

🤖 GitHub comments

Expand to view the GitHub comments

Just comment with:

  • /oblt-deploy : Deploy a Kibana instance using the Observability test environments.
  • run docs-build : Re-trigger the docs validation. (use unformatted text in the comment!)

@jennypavlova
Copy link
Copy Markdown
Member Author

/ci

@jennypavlova jennypavlova force-pushed the 190311-infra-replace-metricsuiaggregation-in-favor-of-estypesaggregationsaggregate branch from 6467553 to 97610bd Compare August 14, 2024 14:07
@jennypavlova
Copy link
Copy Markdown
Member Author

/ci

@jennypavlova
Copy link
Copy Markdown
Member Author

/ci

Copy link
Copy Markdown
Contributor

@crespocarlos crespocarlos left a comment

Choose a reason for hiding this comment

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

Thanks for this refactoring! I know it's still a draft, but I've left some comments.

Nice that the files in the snapshot folder are already reflecting the changes without having to change them.

@@ -6,15 +6,12 @@
*/
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Apparently, this endpoint is used nowhere 🤔

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Interesting - maybe it was replaced at one point. I will check if I can remove it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Removed ✅

Comment on lines +328 to +338
export const hasAggregations = (
aggregations?: Record<string, estypes.AggregationsAggregate>
): aggregations is Record<string, estypes.AggregationsAggregate> => {
return !!(aggregations as Record<string, estypes.AggregationsAggregate>);
};

export const MetricsUIAggregationRT = rt.record(rt.string, ESAggregationRT);
export type MetricsUIAggregation = rt.TypeOf<typeof MetricsUIAggregationRT>;
export const hasSnapshotTermsWithAggregation = (
termWithAggregation?: unknown
): termWithAggregation is SnapshotTermsWithAggregation => {
return !!(termWithAggregation as SnapshotTermsWithAggregation);
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could these be moved to a helper/utils file?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Those are removed now as we use the previous rt types for alerts

@@ -5,35 +5,38 @@
* 2.0.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can we remove this file? It's a duplicate from metrics_api in metrics_data_access.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Removed ✅

Comment on lines +12 to +36
export interface TimeRange {
from: number;
to: number;
interval: string;
}

export interface MetricsAPIMetric {
id: string;
aggregations: MetricsUIAggregation;
}

export interface MetricsAPIRequest {
timerange: TimeRange;
indexPattern: string;
metrics: MetricsAPIMetric[];
includeTimeseries: boolean | undefined;
groupBy?: Array<string | null | undefined>;
groupInstance?: Array<string | null | undefined>;
modules?: string[];
afterKey?: Record<string, string | null> | null;
limit?: number | null;
filters?: Array<Record<string, unknown>>;
dropPartialBuckets?: boolean;
alignDataToEnd?: boolean;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Perhaps we can leave this typed with io-ts, wdyt? We just need to change aggregations to be an rt.UnkonwnRecord.

I wouldn't be so worried about it being an UnknownRecord because /infra/metrics/metrics_api doesn't seem to be used, so this is just used internally by /metrics_explorer and /snapshot endpoints when they call the query function.

/metrics_explorer builds the object manually in the convertMetricToMetricsAPIMetric function and /snapshot, except for custom metrics, gets the aggregations from inventory_models/<entity_type>/snapshot/ folder. Those metrics will be typed correctly

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I changed that, thanks for the suggestion!


export type MetricsAPISeries = rt.TypeOf<typeof MetricsAPISeriesRT>;

export type MetricsAPIRequest = rt.TypeOf<typeof MetricsAPIRequestRT>;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Alternatively, if you decide to keep MetricsAPIRequestRT, you can do the following:

export type MetricsAPIRequest = Omit<rt.OutputOf<typeof MetricsAPIRequestRT>, 'metrics'> & {
  metrics: Array<MetricsAPIMetric>; // ts type
};

It will generate the same typescript type you defined above. This way, internally, anywhere that uses MetricsAPIRequest will be forced to be compatible with MetricsUIAggregation type.

The MetricsAPIRequestRT type in this case is more to validate the request body for the metrics_api endpoint.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good point! Changed 👍

Comment on lines 27 to 29
if (hasAggregations(aggregations)) {
return { id: metric.type, aggregations };
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If the aggregation comes from snapshot object, which is a catalog of metrics aggregations we maintain, and it's properly typed, I would say we don't need this if. If it's not a SnapshotCustomMetricInputRT.is(metric) we can return { id: metric.type, aggregations } without this check.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Removed ✔️

Comment on lines 20 to 22
if (hasAggregations(metric) || metric === undefined) {
return false;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Q: Isn't hasAggregations(metric) redundant, considering the metric is already defined as MetricUIAggregation? Perhaps we could leave just the undefined check here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I left only the undefined check 👍

const values = Object.values(metric);
return (
values.some((agg) => ESTermsWithAggregationRT.is(agg)) &&
values.some((agg) => hasSnapshotTermsWithAggregation(agg)) &&
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Wdyt if we keep ESTermsWithAggregationRT for alerting stuff?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I was trying that but the issue I faced is that ESTermsWithAggregationRT is still using the aggregation type we replace and if we try to still use it then SnapshotTermsWithAggregation is using already the new MetricsUIAggregation which depends on the estypes (Record<string, estypes.AggregationsAggregate>) and there will be incompatible with the "old" type.
I will think about another way to keep them compatible but so far what I tried was not working

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

So I used the old es types and SnapshotTermsWithAggregation renamed to SnapshotTermsWithAggregationForAlerts to keep them the same as before but this will also need refactoring in the future I guess

@jennypavlova jennypavlova marked this pull request as ready for review August 19, 2024 17:22
@jennypavlova jennypavlova requested a review from a team as a code owner August 19, 2024 17:22
@jennypavlova jennypavlova requested review from a team August 19, 2024 17:22
@jennypavlova jennypavlova requested a review from a team as a code owner August 19, 2024 17:22
@elasticmachine
Copy link
Copy Markdown
Contributor

Pinging @elastic/obs-ux-infra_services-team (Team:obs-ux-infra_services)

@botelastic botelastic Bot added the ci:project-deploy-observability Create an Observability project label Aug 19, 2024
Copy link
Copy Markdown
Contributor

@crespocarlos crespocarlos left a comment

Choose a reason for hiding this comment

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

Hey! Thanks for the applying the suggestions. I've got a few more. Overall, it's looking good.

return metrics.reduce((aggs, metric, index) => {
const aggregation = metricToAggregation(options.nodeType, metric, index);
if (!MetricsUIAggregationRT.is(aggregation)) {
if (!!(aggregation as Record<string, estypes.AggregationsAggregate>)) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I guess here we can just check if aggregation is undefined. The only way for aggregation to not be valid is if the metric doesn't exist in the snapshot object for the nodeType.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

it makes sense, changed 👍

Comment on lines +13 to +17
export interface TimeRange {
from: number;
to: number;
interval: string;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this used? We can remove it in favor of MetricsAPITimerange, wdyt?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Removed, thanks!

Comment on lines +19 to +22
export interface MetricsAPIMetric {
id: string;
aggregations: MetricsUIAggregation;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we need to export this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, it is used as a type in different places.

Comment on lines +350 to +353
export interface SnapshotTermsWithAggregationForAlerts {
terms: { field: string };
aggregations: rt.TypeOf<typeof MetricsUIAggregationRT>;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We could probably remove this at this point if we change the ESTermsWithAggregationRT and ESAggregationRT types as suggested

Comment on lines +328 to +334
export const ESTermsWithAggregationRT: rt.Type<SnapshotTermsWithAggregationForAlerts> =
rt.recursion('SnapshotModelRT', () =>
rt.type({
terms: rt.type({ field: rt.string }),
aggregations: MetricsUIAggregationRT,
})
);
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggestion: I think we can simplify this and even remove a few things

export const ESTermsWithAggregationRT = rt.type({
  terms: rt.type({ field: rt.string }),
  aggregations: rt.UnknownRecord,
});

We only need the ESTermsWithAggregationRT type to validate one thing in the is_rate function.

is_rate just needs to know whether the object is a terms agg and I think this can be inferred by whether the object has terms and aggregations attributes. So I'd say that it doesn't need to deeply validate the shape of aggregations.

Once that's changed, these could be removed, leaving only those types that is_rate is using.

  • ESPercentileAggRT
  • ESBucketScriptAggRT
  • ESCumulativeSumAggRT
  • ESCaridnalityAggRT
  • ESTopMetricsAggRT
  • ESMaxPeriodFilterExistsAggRT

We could even remove ESAggregationRT and MetricsUIAggregationRT altogether because there will be nowhere else using them. Wdyt?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It gives us the possibility to get rid of a lot of the old aggregation types which is good. As this is not the only validation there and we also check for ESSumBucketAggRT it should be fine to only validate that we have term and aggregations attributes. I applied the suggestion 👍

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice! I think now we can safely remove these, can't we?

ESPercentileAggRT
ESBucketScriptAggRT
ESCumulativeSumAggRT
ESCaridnalityAggRT
ESTopMetricsAggRT
ESMaxPeriodFilterExistsAggRT

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, I removed all of the types that are no longer used 👍


export const isInterfaceRateAgg = (metric: MetricsUIAggregation | undefined) => {
if (!MetricsUIAggregationRT.is(metric)) {
if (metric === undefined) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe?

Suggested change
if (metric === undefined) {
if (!metric) {


export const isMetricRate = (metric: MetricsUIAggregation | undefined): boolean => {
if (!MetricsUIAggregationRT.is(metric)) {
if (metric === undefined) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe?

Suggested change
if (metric === undefined) {
if (!metric) {

@kibana-ci
Copy link
Copy Markdown

kibana-ci commented Aug 20, 2024

💚 Build Succeeded

  • Buildkite Build
  • Commit: 6093b35
  • Kibana Serverless Image: docker.elastic.co/kibana-ci/kibana-serverless:pr-190495-6093b355a86a

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
infra 1576 1575 -1
metricsDataAccess 288 317 +29
total +28

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
metricsDataAccess 109 128 +19

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
infra 1.5MB 1.5MB +101.0B

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
metricsDataAccess 6 5 -1

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
infra 98.8KB 97.7KB -1.1KB
metricsDataAccess 57.9KB 60.2KB +2.2KB
total +1.1KB
Unknown metric groups

API count

id before after diff
metricsDataAccess 109 128 +19

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

cc @jennypavlova

Copy link
Copy Markdown
Contributor

@crespocarlos crespocarlos left a comment

Choose a reason for hiding this comment

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

LGTM 💯 ! Thanks for this PR.

Copy link
Copy Markdown
Contributor

@kdelemme kdelemme left a comment

Choose a reason for hiding this comment

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

ux-logs-management code change looks good to me!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip This PR does not require backporting ci:project-deploy-observability Create an Observability project release_note:skip Skip the PR/issue when compiling release notes Team:obs-ux-infra_services - DEPRECATED DEPRECATED - Use Team:obs-presentation. v8.16.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Infra] Replace MetricsUIAggregation in favor of estypes.AggregationsAggregate

7 participants