Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/pwa-kit-react-sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## v3.11.0-dev.0 (May 23, 2025)
- Fix the performance logging so that it'll capture all SSR queries, even those that result in errors [#2486](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2486)
- Created an opentelemetry server for SSR tracer intialization [#2617](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2617)

## v3.10.0 (May 22, 2025)
- Fix the performance logging util to use the correct delimiter for the server-timing header. [#2225](https://github.com/SalesforceCommerceCloud/pwa-kit/pull/2295)
Expand Down
173 changes: 173 additions & 0 deletions packages/pwa-kit-react-sdk/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions packages/pwa-kit-react-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
"@loadable/babel-plugin": "^5.15.3",
"@loadable/server": "^5.15.3",
"@loadable/webpack-plugin": "^5.15.2",
"@opentelemetry/api": "^1.4.1",
"@opentelemetry/propagator-b3": "^1.15.1",
"@opentelemetry/resources": "^1.15.1",
"@opentelemetry/sdk-trace-base": "^1.15.1",
"@opentelemetry/sdk-trace-node": "^1.15.1",
"@opentelemetry/semantic-conventions": "^1.15.1",
"@salesforce/pwa-kit-runtime": "3.11.0-dev.0",
"@tanstack/react-query": "^4.28.0",
"cross-env": "^5.2.1",
Expand Down
103 changes: 103 additions & 0 deletions packages/pwa-kit-react-sdk/src/ssr/server/opentelemetry-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright (c) 2025, Salesforce, Inc.
* All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/

import {NodeTracerProvider} from '@opentelemetry/sdk-trace-node'
import {SimpleSpanProcessor} from '@opentelemetry/sdk-trace-base'
import {B3Propagator} from '@opentelemetry/propagator-b3'
import {Resource} from '@opentelemetry/resources'
import {propagation} from '@opentelemetry/api'
import logger from '../../utils/logger-instance'

const DEFAULT_SERVICE_NAME = 'pwa-kit-react-sdk'

let provider = null

/**
* Initialize OpenTelemetry tracing for server-side rendering
* @param {Object} options
* @param {string} [options.serviceName]
* @param {string} [options.serviceVersion]
* @param {boolean} [options.enabled]
* @returns {NodeTracerProvider|null}
*/
export const initializeServerTracing = (options = {}) => {
const {
serviceName = process.env.OTEL_SERVICE_NAME || DEFAULT_SERVICE_NAME,
serviceVersion = process.env.npm_package_version,
Copy link
Contributor

Choose a reason for hiding this comment

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

@larnelleankunda Thanks for adding the telemetry options! It was my bad for not clarifying the code I shared was just an example of possible configuration options. Since process.env.npm_package_version will always be undefined, let’s remove it for now. We can explore a better way to include it later if needed.

Suggested change
serviceVersion = process.env.npm_package_version,

enabled = process.env.OTEL_SDK_ENABLED === 'true'
} = options

// If tracing is disabled, return null without initializing
if (!enabled) {
return null
}

try {
// Build resource attributes
const resourceAttributes = {
'service.name': serviceName
}

// Add service version if provided
if (serviceVersion) {
resourceAttributes['service.version'] = serviceVersion
}

// Initialize the tracer provider
provider = new NodeTracerProvider({
resource: new Resource(resourceAttributes),
spanProcessor: new SimpleSpanProcessor()
})

// Add B3 propagator
propagation.setGlobalPropagator(new B3Propagator())
provider.register()

return provider
} catch (error) {
// Log errors from OpenTelemetry initialization
logger.error('Failed to initialize OpenTelemetry provider', {
namespace: 'opentelemetry-server.initializeServerTracing',
additionalProperties: {error: error.message}
})
return null
}
}

/**
* Shutdown OpenTelemetry tracing and clean up resources
* @returns {Promise<void>}
*/
export const shutdownServerTracing = async () => {
if (provider) {
try {
await provider.shutdown()
provider = null // Clean up after successful shutdown
} catch (error) {
logger.warn('Failed to shutdown OpenTelemetry provider', {
namespace: 'opentelemetry-server.shutdownServerTracing',
additionalProperties: {error: error.message}
})
}
}
}

/**
* Get the current OpenTelemetry provider instance
* @returns {NodeTracerProvider|null} The current provider or null if not initialized
*/
export const getServerTracingProvider = () => {
return provider
}

/**
* Check if OpenTelemetry tracing is currently initialized
* @returns {boolean} True if tracing is initialized, false otherwise
*/
export const isServerTracingInitialized = () => {
return provider !== null
}
Loading
Loading