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

refactor: change metrics export data model to match OTLP protos #2809

Merged
merged 8 commits into from
Mar 6, 2022

Conversation

seemk
Copy link
Contributor

@seemk seemk commented Feb 28, 2022

Which problem is this PR solving?

Refactor metrics export data model to be more in line with metrics protos.

Fixes #2775

Short description of the changes

This introduces MetricsData (naming suggestions welcome) class, which internally groups metric datapoints by resource and instrumentation library and provides a helper to "flatten" into the OTLP protos shape.

Thus instrumentationLibrary and resource are removed from BaseMetricData, saving memory and code duplication.

Checklist:

  • Followed the style guidelines of this project
  • Unit tests have been added

@seemk seemk requested a review from a team February 28, 2022 20:28
@codecov
Copy link

codecov bot commented Feb 28, 2022

Codecov Report

Merging #2809 (4411266) into main (82192b5) will decrease coverage by 0.01%.
The diff coverage is n/a.

@@            Coverage Diff             @@
##             main    #2809      +/-   ##
==========================================
- Coverage   93.48%   93.46%   -0.02%     
==========================================
  Files         163      163              
  Lines        5541     5543       +2     
  Branches     1166     1167       +1     
==========================================
+ Hits         5180     5181       +1     
- Misses        361      362       +1     
Impacted Files Coverage Δ
...s-base/src/export/PeriodicExportingMetricReader.ts 95.34% <0.00%> (-2.22%) ⬇️
...ckages/opentelemetry-sdk-metrics-base/src/Meter.ts 97.82% <0.00%> (ø)
...entelemetry-sdk-metrics-base/src/aggregator/Sum.ts 100.00% <0.00%> (ø)
...ntelemetry-sdk-metrics-base/src/aggregator/Drop.ts 100.00% <0.00%> (ø)
...telemetry-sdk-metrics-base/src/aggregator/types.ts 100.00% <0.00%> (ø)
...elemetry-sdk-metrics-base/src/export/MetricData.ts 100.00% <0.00%> (ø)
...emetry-sdk-metrics-base/src/export/MetricReader.ts 100.00% <0.00%> (ø)
...emetry-sdk-metrics-base/src/state/MetricStorage.ts 100.00% <0.00%> (ø)
...metry-sdk-metrics-base/src/aggregator/Histogram.ts 97.91% <0.00%> (ø)
...metry-sdk-metrics-base/src/aggregator/LastValue.ts 100.00% <0.00%> (ø)
... and 4 more

Copy link
Member

@legendecas legendecas left a comment

Choose a reason for hiding this comment

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

Thank you for your work! 👍

@@ -130,16 +130,21 @@ export class Meter implements metrics.Meter {
* @param collectionTime the HrTime at which the collection was initiated.
* @returns the list of {@link MetricData} collected.
*/
async collect(collector: MetricCollectorHandle, collectionTime: HrTime): Promise<MetricData[]> {
const result = await Promise.all(Array.from(this._metricStorageRegistry.values()).map(metricStorage => {
async collect(collector: MetricCollectorHandle, collectionTime: HrTime): Promise<MetricsData> {
Copy link
Member

Choose a reason for hiding this comment

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

It seems like InstrumentationLibraryMetrics is what a Meter represents regarding the export model. Maybe we can return a Promise<InstrumentationLibraryMetrics> here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, even less code :) Changed it

const collectionTime = hrTime();
const results = await Promise.all(this._sharedState.meters
.map(meter => meter.collect(this, collectionTime)));

return results.reduce((cumulation, current) => cumulation.concat(current), []);
return results.reduce((cumulation, current) => cumulation.merge(current), new MetricsData());
Copy link
Member

Choose a reason for hiding this comment

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

When the meter returns a plain interface of InstrumentationLibraryMetricsData, it seems we don't need a MetricsData.merge here and exporters don't need MetricsData.resourceMetrics to transform maps of data to plain structures?

i.e. a ResourceMetrics could be constructed with an array of InstrumentationLibraryMetricsData and returned.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! This made it possible to get rid of MetricsData

@ehudsh
Copy link

ehudsh commented Mar 1, 2022

Will this MR will make sdk-metrics-base to be compatible with OTLP proto 0.11+ ? Thanks !

@legendecas
Copy link
Member

Will this MR will make sdk-metrics-base to be compatible with OTLP proto 0.11+ ? Thanks !

No, we still need to update the metrics-otlp exporter to adopt the changes.

@seemk
Copy link
Contributor Author

seemk commented Mar 4, 2022

Perhaps one open question - should metrics data be grouped together here by instrumentation library metrics (need to check for value equality) when doing the collect? Or do we think it's fine to have possible duplicates of instrumentation libraries there?

@dyladan
Copy link
Member

dyladan commented Mar 4, 2022

It's technically fine to have duplicates there. Grouping them may have some small benefit on the total payload size

@legendecas
Copy link
Member

Perhaps one open question - should metrics data be grouped together here by instrumentation library metrics (need to check for value equality) when doing the collect?

I think we can do it by preventing from creating duplicated meters, so that the burden is at the time creating the meter, rather than duplicating the work at the collection time. Either way, I think we don't need to do it in this PR. We can track the meter identity in #2593

Copy link
Member

@legendecas legendecas left a comment

Choose a reason for hiding this comment

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

Overall LGTM 👍 , just one minor question.

const results = await Promise.all(this._sharedState.meters
.map(meter => meter.collect(this, collectionTime)));
const instrumentationLibraryMetrics = (await Promise.all(this._sharedState.meters
.map(meter => meter.collect(this, collectionTime)))).filter(({ metrics }) => metrics.length > 0);
Copy link
Member

Choose a reason for hiding this comment

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

I'd find we don't need to do this filtering in the SDK. Like, say, with the DELTA aggregation temporality, the metrics for a meter may contain no items if in a period of time there is no metric event reported. It may be confusing that the InstrumentationLibrary sometimes disappears.

Copy link
Member

Choose a reason for hiding this comment

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

So you are suggesting to export empty InstrumentationLibraryMetrics in that case and leave it up to the exporter and/or backend to sort it out?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, exactly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the filtering

Copy link
Member

@dyladan dyladan left a comment

Choose a reason for hiding this comment

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

Looks good generally. Think this will be ready to merge soon

Copy link
Member

@vmarchaud vmarchaud left a comment

Choose a reason for hiding this comment

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

lgtm

Copy link
Member

@legendecas legendecas left a comment

Choose a reason for hiding this comment

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

Thank you for your work!

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.

Refactor metrics export data model to match proto
5 participants