dd-trace-js icon indicating copy to clipboard operation
dd-trace-js copied to clipboard

[SVLS-7168] Create GCP PubSub Push Subscriptions Plugin

Open nina9753 opened this issue 4 months ago • 11 comments

What does this PR do?

This PR adds comprehensive support for Google Cloud Pub/Sub push subscriptions, enabling distributed tracing for messages delivered via HTTP webhooks. Unlike pull subscriptions, where the application pulls for messages using the SDK, push subscriptions have GCP Pub/Sub POST messages directly to an HTTP endpoint.

New Plugin: pubsub-push-subscription.js

  • Creates pubsub.delivery spans for incoming push subscription HTTP requests
  • Intercepts HTTP requests with GCP-specific headers:
    • User-Agent: APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)
    • x-goog-pubsub-subscription-name
    • x-goog-pubsub-message-id
  • Extracts trace context from message attributes (injected by producer)
  • Parses message metadata (subscription name, topic, publish time)
  • Finishes span when HTTP response completes

Modified: packages/datadog-instrumentations/src/http.js

  • So the push subscription plugin must subscribe to apm:http:server:request:start before the HTTP server plugin
    • Detect Pub/Sub push requests early
    • Create pubsub.delivery span as active parent
    • Ensure web framework spans (Express, Fastify, etc.) become children of the delivery span

Next PR in the batch is #6782

Motivation

An inferred span for the push subscription HTTP POST request to the Cloud Run service from a pub/sub topic Example full Push Distributed Trace of a cloud run service triggering another service using a push subscription

Plugin Checklist

Additional Notes

Critical for Distributed Tracing: When creating or updating a GCP Pub/Sub push subscription, you must include the --push-no-wrapper-write-metadata flag to enable trace context propagation. By default, GCP Pub/Sub wraps push messages in a JSON envelope and does not include message attributes as HTTP headers. We do not currently read the req.body for pubsub distributed tracing

Additional information can be found in this doc

image

nina9753 avatar Aug 11 '25 17:08 nina9753

Overall package size

Self size: 4.39 MB Deduped: 5.21 MB No deduping: 5.21 MB

Dependency sizes | name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 2.0.0 | 68.46 kB | 797.03 kB | | dc-polyfill | 0.1.10 | 26.73 kB | 26.73 kB |

🤖 This report was automatically generated by heaviest-objects-in-the-universe

github-actions[bot] avatar Aug 11 '25 17:08 github-actions[bot]

Codecov Report

:x: Patch coverage is 57.07965% with 97 lines in your changes missing coverage. Please review. :white_check_mark: Project coverage is 84.49%. Comparing base (4b40f00) to head (89ad695). :warning: Report is 5 commits behind head on master.

Files with missing lines Patch % Lines
...oogle-cloud-pubsub/src/pubsub-push-subscription.js 7.40% 75 Missing :warning:
...datadog-plugin-google-cloud-pubsub/src/producer.js 56.86% 22 Missing :warning:
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6260      +/-   ##
==========================================
- Coverage   84.77%   84.49%   -0.29%     
==========================================
  Files         522      523       +1     
  Lines       22233    22445     +212     
==========================================
+ Hits        18849    18964     +115     
- Misses       3384     3481      +97     

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

:rocket: New features to boost your workflow:
  • :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

codecov[bot] avatar Aug 11 '25 17:08 codecov[bot]

Benchmarks

Benchmark execution time: 2025-12-20 19:33:31

Comparing candidate commit 89ad6956f0179bd6553988b69345f04a6225baee in PR branch nina.rei/SVLS-7168/gcp-push-pubsub-plugin with baseline commit 4b40f00f7860d074ad4346a17b164b5c57e409a4 in branch master.

Found 0 performance improvements and 2 performance regressions! Performance is the same for 288 metrics, 30 unstable metrics.

scenario:plugin-http-server-querystring-obfuscation-22

  • 🟥 execution_time [+34.626ms; +38.625ms] or [+5.265%; +5.873%]

scenario:plugin-http-server-querystring-obfuscation-24

  • 🟥 execution_time [+32.084ms; +35.046ms] or [+5.387%; +5.884%]

pr-commenter[bot] avatar Aug 11 '25 18:08 pr-commenter[bot]

⚠️ Tests

Fix all issues with Cursor

⚠️ Warnings

🧪 1 Test failed

OpenFeature "before all" hook for "should not crash build after installing with yarn" from OpenFeature (Datadog) (Fix with Cursor)
Command failed: yarn
error https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.13.1.tgz: Request failed "500 Internal Server Error"
error Error: ENOENT: no such file or directory, open '/home/runner/.cache/yarn/v6/npm-@datadog-pprof-5.13.1-51c540d75cf4471806db65d0686cbe0a96125ce2-integrity/node_modules/@datadog/pprof/.yarn-metadata.json'

Error: Command failed: yarn
error https://registry.yarnpkg.com/@datadog/pprof/-/pprof-5.13.1.tgz: Request failed "500 Internal Server Error"
error Error: ENOENT: no such file or directory, open '/home/runner/.cache/yarn/v6/npm-@datadog-pprof-5.13.1-51c540d75cf4471806db65d0686cbe0a96125ce2-integrity/node_modules/@datadog/pprof/.yarn-metadata.json'

    at genericNodeError (node:internal/errors:985:15)
    at wrappedFn (node:internal/errors:539:14)
...

ℹ️ Info

❄️ No new flaky tests detected

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 89ad695 | Docs | Datadog PR Page | Was this helpful? Give us feedback!

datadog-official[bot] avatar Sep 10 '25 16:09 datadog-official[bot]

@codex review

nina9753 avatar Nov 04 '25 23:11 nina9753

@codex review

nina9753 avatar Nov 17 '25 16:11 nina9753

@codex review

nina9753 avatar Nov 19 '25 16:11 nina9753

We're definitely going to want a test with this.

For example we should simulate the situation where an HTTP request is received and it contains the Google pub sub user agent and headers and makes the appropriate span. Is the intent to only have the google pub sub span or also have an HTTP span with it? And which one is the parent? That's all stuff that should be a part of the test.

tlhunter avatar Nov 19 '25 22:11 tlhunter

We're definitely going to want a test with this.

For example we should simulate the situation where an HTTP request is received and it contains the Google pub sub user agent and headers and makes the appropriate span. Is the intent to only have the google pub sub span or also have an HTTP span with it? And which one is the parent? That's all stuff that should be a part of the test.

I've tested many different situations, but an HTTP request will only ever include the Google PubSub headers and user agent when the request originates from PubSub with the flag as stated in Google's documentation, which means we need to handle that. I have another PR in progress to test all these changes, and I’ve already deployed the code to org 2 to verify the traces and ensure distributed traces are functioning correctly across different scenarios. I’ve specifically tested multiple frameworks and direct HTTP requests, both with and without the --push-no-wrapper-write-metadata flag, as well as all deployment methods for a Cloud Run service using Pub/Sub. I can update the test PR with more examples beyond what’s currently included in the other PRs' details.

nina9753 avatar Nov 24 '25 16:11 nina9753

As discused on Zoom please add an experimental env var to enable this functionality. Here's a recent example that shows the two config files that need updating and how to access the config in code:

https://github.com/DataDog/dd-trace-js/pull/6733

tlhunter avatar Dec 03 '25 18:12 tlhunter

/merge

nina9753 avatar Dec 19 '25 22:12 nina9753

View all feedbacks in Devflow UI.

2025-12-19 22:58:29 UTC :information_source: Start processing command /merge


2025-12-19 22:58:44 UTC :information_source: MergeQueue: waiting for PR to be ready

This pull request is not mergeable according to GitHub. Common reasons include pending required checks, missing approvals, or merge conflicts — but it could also be blocked by other repository rules or settings. It will be added to the queue as soon as checks pass and/or get approvals. Note: if you pushed new commits since the last approval, you may need additional approval. You can remove it from the waiting list with /remove command.


2025-12-20 02:59:15 UTC :warning: MergeQueue: This merge request was unqueued

devflow unqueued this merge request: It did not become mergeable within the expected time