fix: Correct project id on client side metrics by avoiding getProjectId calls with the metric service client#1757
Conversation
| client_name: string; | ||
| streaming: StreamingState; | ||
| status: string; | ||
| projectId: string; |
There was a problem hiding this comment.
I think projectId should be part of IMetricsCollectorData
There was a problem hiding this comment.
I made this change
| * @param {grpc.status} attemptStatus The grpc status for the attempt. | ||
| */ | ||
| onAttemptComplete(attemptStatus: grpc.status) { | ||
| onAttemptComplete(projectId: string, attemptStatus: grpc.status) { |
There was a problem hiding this comment.
projectId is static and won't change per request. Why not add it to line 228 this.getMetricsCollectorData()?
There was a problem hiding this comment.
Sure. Then we can get it from this.tabularApiSurface.
| * @param exporter The exporter the metrics will be sent to. | ||
| */ | ||
| function createInstruments(exporter: PushMetricExporter): MetricsInstruments { | ||
| function createInstruments( |
There was a problem hiding this comment.
I don't think you need to update this, instead you can get it from the attirbutes in the data point:
https://github.com/googleapis/nodejs-bigtable/blob/3e532ab657409c7acd09008c143c41d36d9efd41/src/client-side-metrics/exporter.ts#L134C15-L135, similar to how you get instance id.
There was a problem hiding this comment.
We can definitely do it that way, but then what do we do here? (
)Should we just use the projectId from the first data point for name?
There was a problem hiding this comment.
I don't think you need to update this, instead you can get it from the attirbutes in the data point
There is nothing wrong with doing it this way and I'll do this change, but is there any reason it is preferred?
There was a problem hiding this comment.
Second thought, I don't think we should do it this way.
instead you can get it from the attributes in the data point
This is only true if I start sending the projectId through the OTEL stack which I am not doing right now. And I don't recommend doing that because it increases the data load on the OTEL stack with a bunch of projectId values across all the metrics that we know are all the same.
Let me know what you think.
There was a problem hiding this comment.
Should we just use the projectId from the first data point for name?
Yes.
but is there any reason it is preferred?
OTEL attributes provide context of a metrics. If someone attaches a different exporter on their OTEL instance, without the project id as part of the attributes, this context would be missing and they won't be able to group or filter metrics on project id. It also feels weird to have the project id on Resource because Resource describes where the metric is coming from (in this case it's just bigtable). The extra memory usage from an extra project id field is minimal.
There was a problem hiding this comment.
I made the change you requested.
…ub.com/googleapis/nodejs-bigtable into 467064670-pass-project-id-through-otel
|
|
||
| // Helper to create interceptor provider for OperationMetricsCollector | ||
| function createMetricsInterceptorProvider( | ||
| table: TabularApiSurface, |
There was a problem hiding this comment.
why do we need to pass this in?
There was a problem hiding this comment.
We don't. I removed this. We needed it before because onAttemptComplete needed the projectId, but now it doesn't need the project id.
| * @param exporter The exporter the metrics will be sent to. | ||
| */ | ||
| function createInstruments(exporter: PushMetricExporter): MetricsInstruments { | ||
| function createInstruments( |
There was a problem hiding this comment.
Should we just use the projectId from the first data point for name?
Yes.
but is there any reason it is preferred?
OTEL attributes provide context of a metrics. If someone attaches a different exporter on their OTEL instance, without the project id as part of the attributes, this context would be missing and they won't be able to group or filter metrics on project id. It also feels weird to have the project id on Resource because Resource describes where the metric is coming from (in this case it's just bigtable). The extra memory usage from an extra project id field is minimal.
| table: data.metricsCollectorData.table, | ||
| cluster: data.metricsCollectorData.cluster, | ||
| zone: data.metricsCollectorData.zone, | ||
| projectId: data.metricsCollectorData.projectId, |
There was a problem hiding this comment.
nit: can we move this above instanceId?
| table: data.metricsCollectorData.table, | ||
| cluster: data.metricsCollectorData.cluster, | ||
| zone: data.metricsCollectorData.zone, | ||
| projectId: data.metricsCollectorData.projectId, |
| zone?: string; | ||
| app_profile?: string; | ||
| method: MethodName; | ||
| projectId: string; |
There was a problem hiding this comment.
nit: can we move this on top of instance id?
Description
The project id being recorded for client side metrics is incorrect. The client side metrics monitoring tests are showing that the project id the metrics get recorded for does not actually match the project id the client makes a grpc call for. Specifically, values recorded for
bigtable.googleapis.com/frontend_server/handler_latenciesdon't match values recorded forbigtable.googleapis.com/internal/client/attempt_latencies, but they should match.There is some speculation that since
getProjectIdcalls on theMetricServiceClientdetermine the projectId recorded for client side metrics that the incorrect projectId is due to the differences between thisgetProjectIdcall on theMetricServiceClientand the way the project id is fetched on the Bigtable client. Therefore, we introduce this PR to record a projectId that is certain to be an exact match of the project id on the Bigtable client.Impact
This has a high probability of correcting the project id for the client side metrics
Testing
The fixtures have changed to accommodate for the fact that we now pass the projectId through the OTEL stack.