Skip to content

Feat: Add Custom OpenTelemetry Exporter in for Service Metrics #2272

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

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

lszinv
Copy link

@lszinv lszinv commented Apr 2, 2025

Description

This change adds an implementation for an OpenTelemetry exporter to send the following service metrics that are already present in the Python, Go and Java clients:

operation_latencies operation_count attempt_latencies attempt_count gfe_latency gfe_missing_header_count

Files added to a metrics folder in /src/metrics/ folder:

constants.ts - Constant values such as metric and label names to be used by both the exporter and eventual implementing code. spanner-metrics-exporter.ts - The definition for the exporter external-types.ts - Type definition for ExporterOptions, MetricKind, and ValueType transform.ts - Methods that help create a GCM timeseries list from scope metrics.

Based on regular client Google Cloud Monitoring exporter found here

Impact

Integrates Built-in Metrics support into Node.js spanner client library.

Testing

Unit tests were added in /test/metrics

Checklist

  • Make sure to open an issue as a bug/issue before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea

  • Ensure the tests and linter pass

  • Code coverage does not decrease

  • Appropriate docs were updated

  • Appropriate comments were added, particularly in complex areas or places that require background

  • No new warnings or issues will be generated from this change

@lszinv lszinv requested review from a team as code owners April 2, 2025 22:27
@lszinv
Copy link
Author

lszinv commented Apr 2, 2025

Note This is a re-submission of #2270 with some additional fixes done, please close #2270 and I'll continue to address issues from CI tests & review comments here instead (as @ravjotbrar is away on vacation, and I don't have access to his fork).

@product-auto-label product-auto-label bot added size: xl Pull request size is extra large. api: spanner Issues related to the googleapis/nodejs-spanner API. labels Apr 2, 2025
} from '@opentelemetry/core';
import {ExporterOptions} from './external-types';
import {GoogleAuth, JWT} from 'google-auth-library';
import {monitoring_v3} from 'googleapis';
Copy link
Contributor

Choose a reason for hiding this comment

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

Node support google-cloud-monitoring package which has MetricServiceClient , could we use that instead?

Choose a reason for hiding this comment

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

When I was implementing this, I referenced the original exporter, which also uses monitoring_v3 instead of MetricServiceClient.

However, if the expectation is to use MetricServiceClient, I can focus on making those changes.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes . MetricServiceClient is high level client provided to interact with Cloud Monitoring APIs. monitoring_v3 is low level and should be used within the node sdk.

Copy link
Contributor

Choose a reason for hiding this comment

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

With this change, I believe we should not be needing googleapis package and we should be using @google-cloud/monitoring

Copy link

@ravjotbrar ravjotbrar Apr 9, 2025

Choose a reason for hiding this comment

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

Copy link
Contributor

@surbhigarg92 surbhigarg92 Apr 10, 2025

Choose a reason for hiding this comment

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

I wasn't aware about this, I am checking with the opentelemetry team internally. Lets keep the monitoring_v3 package till then

/**
* Format and sends metrics information to Google Cloud Monitoring.
*/
export class CloudMonitoringMetricsExporter implements PushMetricExporter {
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of writing the CloudMonitoringMetricsExporter from scratch, can we extend the available cloud monitoring exporter and just override the "export" method

Choose a reason for hiding this comment

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

Thanks for the suggestion @surbhigarg92. I considered this, but based on the amount of refactoring we've done with the existing cloud monitoring exporter, this would involve undoing a lot of that work.

Copy link
Author

@lszinv lszinv Apr 9, 2025

Choose a reason for hiding this comment

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

We discussed this amongst ourselves. We'll can change the class to extend the existing Exporter. However, given that we will need to override the constructor connection logic to use the MetricServiceClient and override the Export functionality, there will be virtually no logical changes from the parent class remaining. It will however allow us to not need to re-define duplicate definitions exporter out of external-types.

Choose a reason for hiding this comment

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

Even using monitoring_v3, we'll need to define our own connection logic, since we now pass in an auth object instead of authOptions. In addition, the original exporter does not expose many of its variables requiring us to redefine anyways. However, if we still want to go that route, it is definitely possible.

Copy link
Contributor

Choose a reason for hiding this comment

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

@ravjotbrar Lets skip extending the exusting Exporter then if it is not adding any value. Thanks for considering.

dataPointType === DataPointType.EXPONENTIAL_HISTOGRAM
) {
return ValueType.DISTRIBUTION;
} else if (name.includes('count')) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Except this everything else is generic and auto detected. If possible , we could make this generic, if this would add a lot to code maintainability please skip.

Choose a reason for hiding this comment

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

At the moment, I'm unable to think of solutions that would make this generic. If I get an idea, I will definitely make the change.

} from '@opentelemetry/core';
import {ExporterOptions} from './external-types';
import {GoogleAuth, JWT} from 'google-auth-library';
import {monitoring_v3} from 'googleapis';
Copy link
Contributor

Choose a reason for hiding this comment

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

Yes . MetricServiceClient is high level client provided to interact with Cloud Monitoring APIs. monitoring_v3 is low level and should be used within the node sdk.

*
* Optional, default is `workload.googleapis.com`.
*/
prefix?: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

This should not be configurable for our use case as metrics will always go to "spanner.googleapis.com"

Choose a reason for hiding this comment

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

Got it, removed.

@surbhigarg92 surbhigarg92 added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Apr 11, 2025
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Apr 11, 2025
@surbhigarg92 surbhigarg92 added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Apr 14, 2025
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Apr 14, 2025
@surbhigarg92 surbhigarg92 added the owlbot:run Add this label to trigger the Owlbot post processor. label Apr 14, 2025
@gcf-owl-bot gcf-owl-bot bot removed the owlbot:run Add this label to trigger the Owlbot post processor. label Apr 14, 2025
@lszinv
Copy link
Author

lszinv commented Apr 14, 2025

Airlock is erroring on not being able to find @grpc/grpc-js@^1.13.3

edit: Removed grpc-js, and airlock eerrors on "googleapis": "146.0.0"

@surbhigarg92 surbhigarg92 added the automerge Merge the pull request once unit tests and other checks pass. label Apr 16, 2025
Copy link
Contributor

Merge-on-green attempted to merge your PR for 6 hours, but it was not mergeable because either one of your required status checks failed, one of your required reviews was not approved, or there is a do not merge label. Learn more about your required status checks here: https://help.github.com/en/github/administering-a-repository/enabling-required-status-checks. You can remove and reapply the label to re-run the bot.

@gcf-merge-on-green gcf-merge-on-green bot removed the automerge Merge the pull request once unit tests and other checks pass. label Apr 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: spanner Issues related to the googleapis/nodejs-spanner API. size: xl Pull request size is extra large.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants