Skip to content

@W-18760780 Integrate opentelemetry into performance.js#2722

Merged
jeremy-jung1 merged 28 commits intofeature/opentelemetryfrom
W-18760780-performancejs
Jul 16, 2025
Merged

@W-18760780 Integrate opentelemetry into performance.js#2722
jeremy-jung1 merged 28 commits intofeature/opentelemetryfrom
W-18760780-performancejs

Conversation

@jeremy-jung1
Copy link
Collaborator

@jeremy-jung1 jeremy-jung1 commented Jul 2, 2025

Integrating opentelemetry spans into performance.js

Description

Types of Changes

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Documentation update
  • Breaking change (could cause existing functionality to not work as expected)
  • Other changes (non-breaking changes that does not fit any of the above)

Breaking changes include:

  • Removing a public function or component or prop
  • Adding a required argument to a function
  • Changing the data type of a function parameter or return value
  • Adding a new peer dependency to package.json

Changes

  • (change1) Added opentelemetry span usage and some cleanups in react-rendering to prevent memory leak
  • (change2) Modified the OTEL config so that it doesn't throw in the browser

How to Test-Drive This PR

  • (step1) pull this branch locally
  • (step2) go to pwa-kit-react-sdk and do npm run build
  • (step3) then go to template-retail-react-app and do export OTEL_SDK_ENABLED=true && npm start
  • (step3) Go to http://localhost:3000/?__server_timing. See that you can see logs of spans:
Screenshot 2025-07-11 at 12 27 51 AM

Checklists

General

  • Changes are covered by test cases
  • CHANGELOG.md updated with a short description of changes (not required for documentation updates)

Accessibility Compliance

You must check off all items in one of the follow two lists:

  • There are no changes to UI

or...

Localization

  • Changes include a UI text update in the Retail React App (which requires translation)

@jeremy-jung1 jeremy-jung1 requested a review from a team as a code owner July 2, 2025 22:58
@cc-prodsec
Copy link
Collaborator

cc-prodsec commented Jul 2, 2025

🎉 Snyk checks have passed. No issues have been found so far.

security/snyk check is complete. No issues have been found. (View Details)

license/snyk check is complete. No issues have been found. (View Details)

@jeremy-jung1 jeremy-jung1 changed the title @W-18760780 performance.js @W-18760780 Integrate opentelemetry into performance.js Jul 10, 2025
@jeremy-jung1 jeremy-jung1 changed the base branch from feature/opentelemetry to W-18759774-opentelemetry-util July 10, 2025 22:18
Comment on lines +34 to +46
delete process.env.OTEL_SERVICE_NAME
delete process.env.OTEL_SDK_ENABLED
delete process.env.OTEL_B3_TRACING_ENABLED

const {getOTELConfig} = mockModule()
const config = getOTELConfig()

expect(config).toEqual({
serviceName: 'pwa-kit-react-sdk',
enabled: false,
b3TracingEnabled: false
})
})
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: insead of testing the combination of all the env variables would we consider having separate tests for each config?

  • should return service name when OTEL_SERVICE_NAME is set
  • should return default service when OTEL_SERVICE_NAME is not set
  • should return enabled when OTEL_SDK_ENABLED is set
  • should return disabled when OTEL_SDK_ENABLED is not set
    ...

That way if additional configs are added in the future each property is isolated

Copy link
Collaborator

@hajinsuha1 hajinsuha1 left a comment

Choose a reason for hiding this comment

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

one nit comment but followed the test steps and can see the open telemetry logs

Image

@jeremy-jung1 jeremy-jung1 changed the base branch from W-18759774-opentelemetry-util to feature/opentelemetry July 14, 2025 06:12
}, this.maxSpanDuration)
this.spanTimeouts.set(name, timeoutId)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we log a warning in case we attempt to create a duplicate span name?

endMark,
namespace: 'PerformanceTimer.mark'
})
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we also call cleanup in case of catching an error?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The timed out automatic cleanup made for each span on creation would clean them up eventually. Even when endSpan logs an error within itself.

mark(name, type, options = {}) {
if (!this.enabled) {
const {detail = ''} = options
if (!name || !type || !this.enabled) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we keep checking if enabled first, then validate inputs?

Suggested change
if (!name || !type || !this.enabled) {
if (!this.enabled || !name || !type) {

Copy link
Contributor

Choose a reason for hiding this comment

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

Following the steps to test the changes I see in the logs we have a few "No parent span found" warnings and it looks like each span is using a different traceId instead of all spans sharing the same traceId.

...
pwa-kit-react-sdk.opentelemetry.logSpanData INFO OpenTelemetry span data {"traceId":"d8acdf23f3344d04d9da11e4dc6a6fed","name":"ssr.render-to-string","id":"e0a43b64a9e330bd","kind":0,"timestamp":"2025-07-16T02:09:20.417000000Z","duration":0,"attributes":{"service.name":"pwa-kit-react-sdk","performance_type":"start","performance.mark":"ssr.render-to-string","performance.type":"start","performance.detail":"","event":"start"},"status":{"code":0},"events":[],"links":[],"start_time":[1752631760,417000000],"end_time":[1752631760,417000000],"forwardTrace":false}
pwa-kit-react-sdk.opentelemetry.logSpanData INFO OpenTelemetry span data {"traceId":"d8acdf23f3344d04d9da11e4dc6a6fed","name":"ssr.render-to-string","id":"e0a43b64a9e330bd","kind":0,"timestamp":"2025-07-16T02:09:20.417000000Z","duration":68.30075,"attributes":{"service.name":"pwa-kit-react-sdk","performance_type":"start","performance.mark":"ssr.render-to-string","performance.type":"start","performance.detail":"","event":"end"},"status":{"code":1},"events":[],"links":[],"start_time":[1752631760,417000000],"end_time":[1752631760,485300750],"forwardTrace":false}
pwa-kit-react-sdk.opentelemetry.logSpanData INFO OpenTelemetry span data {"traceId":"714bd3edf17e826c55ed0dabb8f2cc38","name":"ssr.total","id":"31e2c7b3b61ff8f1","kind":0,"timestamp":"2025-07-16T02:09:19.220000000Z","duration":1266.033834,"attributes":{"service.name":"pwa-kit-react-sdk","performance_type":"start","performance.mark":"ssr.total","performance.type":"start","performance.detail":"","event":"end"},"status":{"code":1},"events":[],"links":[],"start_time":[1752631759,220000000],"end_time":[1752631760,486033834],"forwardTrace":false}
pwa-kit-react-sdk.opentelemetry WARN No parent span found in context {"metricName":"ssr.route-matching"}
pwa-kit-react-sdk.opentelemetry WARN No parent span found in context {"metricName":"ssr.load-component"}
pwa-kit-react-sdk.opentelemetry WARN No parent span found in context {"metricName":"ssr.fetch-strategies.react-query.pre-render"}
pwa-kit-react-sdk.opentelemetry WARN No parent span found in context {"metricName":"ssr.fetch-strategies.react-query.use-query.1"}
pwa-kit-react-sdk.opentelemetry WARN No parent span found in context {"metricName":"ssr.fetch-strategies.react-query.use-query.useCategory-0"}
pwa-kit-react-sdk.opentelemetry WARN No parent span found in context {"metricName":"ssr.fetch-strategies.react-query.use-query.useProductSearch-2"}
pwa-kit-react-sdk.opentelemetry WARN No parent span found in context {"metricName":"ssr.fetch-strategies"}
pwa-kit-react-sdk.opentelemetry WARN No parent span found in context {"metricName":"ssr.render-to-string"}
pwa-kit-react-sdk.opentelemetry WARN No parent span found in context {"metricName":"ssr.total"}

Are we missing wrapping the render function with a root span? Is this something we plan to do in a separated ticket?
https://github.com/SalesforceCommerceCloud/pwa-kit/blob/W-18129479-spike-o11y/packages/pwa-kit-react-sdk/src/ssr/server/react-rendering.js#L136

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@jeremy-jung1 jeremy-jung1 merged commit 0d75e65 into feature/opentelemetry Jul 16, 2025
35 checks passed
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.

4 participants