@W-18759774 - Created opentelemetry.js file with utility functions to log OTel spans and metrics#2705
Conversation
…s and metricsas well as creates a test file for it
🎉 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) |
Signed-off-by: Larnelle Ankunda <lankunda@salesforce.com>
| import {hrTimeToMilliseconds, hrTimeToTimeStamp} from '@opentelemetry/core' | ||
| import logger from './logger-instance' | ||
|
|
||
| const SERVICE_NAME = 'pwa-kit-react-sdk' |
There was a problem hiding this comment.
We have now have two different places where we are defining the service name value, one in the /utils/opentelemetry.js file and another one in the /server/opentelemetry-server.js file:
What do you think if we keep the opentelemetry config in the /utils/opentelemetry.js file as the source of truth, so we consistently use the same config values in the opentelemetry utils and opetelemetry server initialization files?
Example:
//utils/opentelemetry.js
const DEFAULT_SERVICE_NAME = 'pwa-kit-react-sdk'
export const OTEL_CONFIG = {
serviceName: process.env.OTEL_SERVICE_NAME || DEFAULT_SERVICE_NAME,
enabled: process.env.OTEL_SDK_ENABLED === 'true',
b3TracingEnabled: process.env.OTEL_B3_TRACING_ENABLED === 'true',
}
export const getServiceName = () => OTEL_CONFIG.serviceName
Re-use the config in the opentelemetry-server.js file:
//server/opentelemetry-server.js
import {OTEL_CONFIG} from '../../utils/opentelemetry'
export const initializeServerTracing = (options = {}) => {
const config = { ...OTEL_CONFIG, ...options }
...
}
Later, in future PRs we can use the config like this:
//server/react-rendering.js
import {OTEL_CONFIG} from '../../utils/opentelemetry'
import {initializeServerTracing} from './opentelemetry-server'
initializeServerTracing(OTEL_CONFIG)
...
There was a problem hiding this comment.
As I actually use the opentelemetry.js in peformance.js in development which gets it closer to working end-to-end. I see that the app errors out with an uncaught exception that process is not defined.
I believe this is because process.env, when accessed from this config in the top-level portion of this file outside of any functions, is in the context of the browser environment where it doesn't have the scope for process. Webpack includes the opentelemetry.js in the app bundle and the browser executes the top-level code. We might want to keep any usage of process.env within functions that are called server-side.
I'll make some changes to this in my performance.js PR
| timestamp: hrTimeToTimeStamp(startTime), | ||
| duration: duration, | ||
| attributes: { | ||
| 'service.name': SERVICE_NAME, |
There was a problem hiding this comment.
If you agree with the previous comment we need to replace all references of SERVICE_NAME:
| 'service.name': SERVICE_NAME, | |
| 'service.name': getServiceName(), |
| links: [], | ||
| start_time: startTime, | ||
| end_time: endTime, | ||
| forwardTrace: process.env.DISABLE_B3_TRACING !== 'true' |
There was a problem hiding this comment.
| forwardTrace: process.env.DISABLE_B3_TRACING !== 'true' | |
| forwardTrace: OTEL_CONFIG.b3TracingEnabled |
|
|
||
| const SERVICE_NAME = 'pwa-kit-react-sdk' | ||
|
|
||
| function logSpanData(span, event = 'start', res = null) { |
There was a problem hiding this comment.
Can we use the arrow function pattern used throughout the codebase instead of regular function for consistency?
| function logSpanData(span, event = 'start', res = null) { | |
| const logSpanData = (span, event = 'start', res = null) => { |
| * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause | ||
| */ | ||
| /* eslint-disable @typescript-eslint/no-var-requires */ | ||
| const base = require('internal-lib-build/configs/jest/jest.config') |
There was a problem hiding this comment.
Nit: Do we need this change?
There was a problem hiding this comment.
+1 on this nit. It may not seem like a big deal that a change like this that doesn't do anything goes in the PR, but one downside is in the future if someone wants to do a git blame to see "hey who added this line about requiring jest.config here and why did they do that" then they will see this PR instead of the originating PR.
|
|
||
| export const OTEL_CONFIG = { | ||
| serviceName: process.env.OTEL_SERVICE_NAME || DEFAULT_SERVICE_NAME, | ||
| enabled: process.env.OTEL_SDK_ENABLED === 'true', |
There was a problem hiding this comment.
I see we have an enabled flag in the CONFIG but are we reading this in anywhere? Or will this be used in future PR's when we make changes to performance and react-rendering?
|
|
||
| export const getServiceName = () => OTEL_CONFIG.serviceName | ||
|
|
||
| const SERVICE_NAME = OTEL_CONFIG.serviceName |
There was a problem hiding this comment.
| const SERVICE_NAME = OTEL_CONFIG.serviceName |
We don't need this line. As Adam mentioned, we can replace all instances of SERVICE_NAME with getServiceName()
| */ | ||
| export const createSpan = (name, options = {}) => { | ||
| try { | ||
| const tracer = trace.getTracer(SERVICE_NAME) |
There was a problem hiding this comment.
For example, we would replace it here:
| const tracer = trace.getTracer(SERVICE_NAME) | |
| const tracer = trace.getTracer(getServiceName()) |
| const ctx = context.active() | ||
| // Note: parentSpan is not used in this implementation |
There was a problem hiding this comment.
Do we need these 2 lines if ctx is not used anywhere?
| /* | ||
| * 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 | ||
| */ |
There was a problem hiding this comment.
Duplicate
| /* | |
| * 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 | |
| */ |
adamraya
left a comment
There was a problem hiding this comment.
Thanks for making the changes. LGTM
|
|
||
| const DEFAULT_SERVICE_NAME = 'pwa-kit-react-sdk' | ||
|
|
||
| export const OTEL_CONFIG = { |
There was a problem hiding this comment.
Let's use the OTEL_CONFIG in packages/pwa-kit-react-sdk/src/utils/opentelemetry-server.js file.
Remove the DEFAULT_SERVICE_NAME constant from opentelemetry-server.js:
And replace it with getServiceName:
import {getServiceName, OTEL_CONFIG} from '../../utils/opentelemetry'
const serviceName = options.serviceName || getServiceName()
...
Created opentelemetry.js file with utility functions to log OTel spans and metrics as well as creates a test file for it
Description
Types of Changes
Changes
How to Test-Drive This PR
Checklists
General
Accessibility Compliance
You must check off all items in one of the follow two lists:
or...
Localization