feat: gcp pubsub admin endpoints#4957
Conversation
…pubsub-admin-endpoints
…pubsub-admin-endpoints
|
…pubsub-admin-endpoints
BenchmarksBenchmark execution time: 2026-06-26 15:49:42 Comparing candidate commit fb1c555 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 297 metrics, 2 unstable metrics, 1 flaky benchmarks without significant changes.
|
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3c0147bb7f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| func (c *TopicAdminClient) ListTopics(ctx context.Context, req *pubsubpb.ListTopicsRequest, opts ...gax.CallOption) *vkit.TopicIterator { | ||
| ctx, finish := pstrace.TraceListTopics(ctx, req, c.opts...) | ||
| it := c.TopicAdminClient.ListTopics(ctx, req, opts...) | ||
| finish(nil) |
There was a problem hiding this comment.
Defer finishing list spans until iteration
When callers use any of the List* admin methods, the Pub/Sub GAPIC returns an iterator and reports RPC errors when the iterator is consumed via Next/All, not from this method call. Finishing the span here with nil before returning means auth, deadline, or service errors during listing, as well as the actual RPC latency, are recorded as a successful near-zero span; the same pattern appears in the other List* wrappers/aspects, so those spans need to be closed from the iterator path instead.
Useful? React with 👍 / 👎.
| # implemented on the GAPIC clients in cloud.google.com/go/pubsub/v2/apiv1. A package-level | ||
| # tracer is injected into that package and each management method is wrapped to emit a | ||
| # gcp.pubsub.request span. | ||
| - id: Initialize pubsubtrace (admin) |
There was a problem hiding this comment.
these orchestrion aspects should have comprehensive tests inside internal/orchestrion/_integration trying to cover all the different patterns this library can be used.
| // SpanTypeWorker marks a span as a worker/management operation, such as a | ||
| // Pub/Sub admin (topic, subscription, snapshot, schema management) request. | ||
| SpanTypeWorker = "worker" |
There was a problem hiding this comment.
is this the only usage we intend for this new span type? or do we intend to change all the existing worker kind of spans to this new type?
| // management operations. It embeds the wrapped client, so any method that is not traced | ||
| // (e.g. Publish, IAM helpers, Close) is forwarded to the underlying client unchanged. | ||
| type TopicAdminClient struct { | ||
| *vkit.TopicAdminClient |
There was a problem hiding this comment.
it seems this client supports adding grpc interceptors, so could we instead of wrapping, implementing tracing for this client via a grpc unary interceptor? This would make this more simple, specially on the orchestrion side of things.
You can add the new interceptor with:
client, err := apiv1.NewTopicAdminClient(ctx,
option.WithGRPCDialOption(
grpc.WithChainUnaryInterceptor(tracingInterceptor),
),
)
What does this PR do?
Implements instrumentation for admin endpoints across v1 and v2 listed in the tables below
Common Span Tags (All Admin Operations)
All admin operations are traced via
TraceAdminincontrib/cloud.google.com/go/pubsubtrace/tracing.goand share these tags:span.typeworkerext.SpanTypeWorkerspan.kindclientext.SpanKindClientmessaging.systemgooglepubsubext.MessagingSystemGCPPubsubcomponentcloud.google.com/go/pubsub(v1) orcloud.google.com/go/pubsub/v2(v2)pubsub.method"CreateTopic","DeleteSubscription"resource.name"<method> <resourcePath>"<method>if path is emptygcloud.project_id"projects/"trueWithMeasured()requestSpanNameinstr.OperationName(ComponentClient, nil)V1 vs V2 Client Type Mapping
PublisherClient(cloud.google.com/go/pubsub/apiv1)TopicAdminClient(cloud.google.com/go/pubsub/v2/apiv1)SubscriberClient(cloud.google.com/go/pubsub/apiv1)SubscriptionAdminClient(cloud.google.com/go/pubsub/v2/apiv1)SchemaClient(cloud.google.com/go/pubsub/apiv1)SchemaClient(cloud.google.com/go/pubsub/v2/apiv1)Topic Operations
pubsub.methodgcloud.project_idset?CreateTopic"CreateTopic"req.GetName()TraceCreateTopicV1TraceCreateTopicUpdateTopic"UpdateTopic"req.GetTopic().GetName()TraceUpdateTopicV1TraceUpdateTopicGetTopic"GetTopic"req.GetTopic()TraceGetTopicV1TraceGetTopicListTopics"ListTopics"req.GetProject()"projects/...")TraceListTopicsV1TraceListTopicsListTopicSubscriptions"ListTopicSubscriptions"req.GetTopic()TraceListTopicSubscriptionsV1TraceListTopicSubscriptionsListTopicSnapshots"ListTopicSnapshots"req.GetTopic()TraceListTopicSnapshotsV1TraceListTopicSnapshotsDeleteTopic"DeleteTopic"req.GetTopic()TraceDeleteTopicV1TraceDeleteTopicDetachSubscription"DetachSubscription"req.GetSubscription()TraceDetachSubscriptionV1TraceDetachSubscriptionSubscription Operations
pubsub.methodgcloud.project_idset?CreateSubscription"CreateSubscription"req.GetName()TraceCreateSubscriptionV1TraceCreateSubscriptionGetSubscription"GetSubscription"req.GetSubscription()TraceGetSubscriptionV1TraceGetSubscriptionUpdateSubscription"UpdateSubscription"req.GetSubscription().GetName()TraceUpdateSubscriptionV1TraceUpdateSubscriptionListSubscriptions"ListSubscriptions"req.GetProject()"projects/...")TraceListSubscriptionsV1TraceListSubscriptionsDeleteSubscription"DeleteSubscription"req.GetSubscription()TraceDeleteSubscriptionV1TraceDeleteSubscriptionModifyPushConfig"ModifyPushConfig"req.GetSubscription()TraceModifyPushConfigV1TraceModifyPushConfigSeek"Seek"req.GetSubscription()TraceSeekV1TraceSeekSnapshot Operations
pubsub.methodgcloud.project_idset?GetSnapshot"GetSnapshot"req.GetSnapshot()TraceGetSnapshotV1TraceGetSnapshotListSnapshots"ListSnapshots"req.GetProject()"projects/...")TraceListSnapshotsV1TraceListSnapshotsCreateSnapshot"CreateSnapshot"req.GetName()TraceCreateSnapshotV1TraceCreateSnapshotUpdateSnapshot"UpdateSnapshot"req.GetSnapshot().GetName()TraceUpdateSnapshotV1TraceUpdateSnapshotDeleteSnapshot"DeleteSnapshot"req.GetSnapshot()TraceDeleteSnapshotV1TraceDeleteSnapshotSchema Operations
pubsub.methodgcloud.project_idset?CreateSchema"CreateSchema"req.GetParent()"projects/...")TraceCreateSchemaV1TraceCreateSchemaGetSchema"GetSchema"req.GetName()TraceGetSchemaV1TraceGetSchemaListSchemas"ListSchemas"req.GetParent()"projects/...")TraceListSchemasV1TraceListSchemasListSchemaRevisions"ListSchemaRevisions"req.GetName()TraceListSchemaRevisionsV1TraceListSchemaRevisionsCommitSchema"CommitSchema"req.GetName()TraceCommitSchemaV1TraceCommitSchemaRollbackSchema"RollbackSchema"req.GetName()TraceRollbackSchemaV1TraceRollbackSchemaDeleteSchemaRevision"DeleteSchemaRevision"req.GetName()TraceDeleteSchemaRevisionV1TraceDeleteSchemaRevisionDeleteSchema"DeleteSchema"req.GetName()TraceDeleteSchemaV1TraceDeleteSchemaValidateSchema"ValidateSchema"req.GetParent()"projects/...")TraceValidateSchemaV1TraceValidateSchemaValidateMessage"ValidateMessage"req.GetParent()"projects/...")TraceValidateMessageV1TraceValidateMessageMotivation
APMSVLS-536
view @pablomartinezbernardo's python implementation here
Questions:
Should we be instrumenting v1? Its being deprecated by google
Reviewer's Checklist
make lintlocally.make testlocally.make generatelocally.make fix-moduleslocally.Unsure? Have a question? Request a review!