Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
63 changes: 63 additions & 0 deletions .github/workflows/backcompat.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Old Node.js Compatibility
on:
push:
branches:
- main
paths:
- 'api/**'
- '.github/workflows/backcompat.yml'
pull_request:
paths:
- 'api/**'
- '.github/workflows/backcompat.yml'
merge_group:
paths:
- 'api/**'
- '.github/workflows/backcompat.yml'

permissions:
contents: read

jobs:
backcompat:
name: 'backcompat: ${{ matrix.package }} on Node.js ${{ matrix.node-version }}'
strategy:
fail-fast: false
matrix:
include:
- package: api
node-version: '8'
script: test/backcompat/node8-compat.js
runs-on: ubuntu-latest
env:
PACKAGE: ${{ matrix.package }}
NODE_VERSION: ${{ matrix.node-version }}
SCRIPT: ${{ matrix.script }}
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

# Use a modern Node.js to install dependencies and compile TypeScript.
- name: Setup Node.js (compile)
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version: '22'
cache: 'npm'
cache-dependency-path: package-lock.json

- name: Bootstrap
run: npm ci --ignore-scripts

- name: Compile
run: npm run compile

# Switch to the target old Node.js and run the standalone plain-JS smoke
# test. Package is already compiled and dependencies are already installed.
- name: Setup Node.js ${{ env.NODE_VERSION }} (test)
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6
with:
node-version: ${{ env.NODE_VERSION }}

- name: Run compatibility smoke test
run: node "$SCRIPT"
working-directory: ${{ env.PACKAGE }}
1 change: 1 addition & 0 deletions api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.
* fix(api): update diag `consoleLogger` to use original console methods to prevent infinite loop when a console instrumentation is present [#6395](https://github.com/open-telemetry/opentelemetry-js/pull/6395)
* fix(api): use `Attributes` instead of deprecated `SpanAttributes` in `SpanOptions` [#6478](https://github.com/open-telemetry/opentelemetry-js/pull/6478) @overbalance
* fix(diag): change types in `DiagComponentLogger` from `any` to `unknown`[#5478](https://github.com/open-telemetry/opentelemetry-js/pull/5478) @loganrosen
* fix(api): re-introduce fallback chain for global utils [#6523](https://github.com/open-telemetry/opentelemetry-js/pull/6523/) @pichlermarc

### :books: (Refine Doc)

Expand Down
1 change: 1 addition & 0 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"lint": "eslint . --ext .ts && npm run cycle-check",
"test:browser": "karma start --single-run",
"test": "nyc mocha 'test/**/*.test.ts'",
"test:node8-compat": "node test/backcompat/node8-compat.js",
"test:webworker": "karma start karma.worker.js --single-run",
"cycle-check": "dpdm --exit-code circular:1 src/index.ts",
"version": "node ../scripts/version-update.js",
Expand Down
16 changes: 15 additions & 1 deletion api/src/internal/global-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,21 @@ const GLOBAL_OPENTELEMETRY_API_KEY = Symbol.for(
`opentelemetry.js.api.${major}`
);

const _global = globalThis as OTelGlobal;
declare const self: unknown;
declare const window: unknown;
declare const global: unknown;

const _global = (
typeof globalThis === 'object'
? globalThis
: typeof self === 'object'
? self
: typeof window === 'object'
? window
: typeof global === 'object'
? global
: {}
) as OTelGlobal;

export function registerGlobal<Type extends keyof OTelGlobalAPI>(
type: Type,
Expand Down
81 changes: 81 additions & 0 deletions api/test/backcompat/node8-compat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright The OpenTelemetry Authors
* SPDX-License-Identifier: Apache-2.0
*/

/**
* Simple Node.js v8 compatibility smoke test. Intentionally avoids dependencies
* so that we can keep updating tooling used for unit and integration tests.
*
* Intended to be run directly with node node8-compat.js
*/

const assert = require('assert');

const GLOBAL_API_SYMBOL = Symbol.for('opentelemetry.js.api.1');

function clearGlobal() {
delete global[GLOBAL_API_SYMBOL];
}

function freshApi() {
// Evict every cached module so each call returns a brand-new instance.
Object.keys(require.cache).forEach(function (key) {
delete require.cache[key];
});
return require('../../build/src/index.js');
}

// Test 1: test global registration (the global used must exist)
clearGlobal();
const api = freshApi();

// this will throw or return false if registration fails.
const result = api.diag.setLogger(
new api.DiagConsoleLogger(),
api.DiagLogLevel.ALL
);
assert.strictEqual(
result,
true,
'Test 1 failed: diag.setLogger should return true'
);

// Test 2: test that multiple loads share the same global state (e.g. logger)
clearGlobal();

const api1 = freshApi();
const api2 = freshApi(); // fresh load – different module object, same _global

const infoMessages = [];
const sharedLogger = {
error: function () {},
warn: function () {},
info: function (msg) {
infoMessages.push(msg);
},
debug: function () {},
verbose: function () {},
};

const ok = api1.diag.setLogger(sharedLogger, api1.DiagLogLevel.ALL);
assert.strictEqual(
ok,
true,
'Test 2 setup failed: api1.diag.setLogger should return true'
);

api2.diag.info('shared-state-check');
assert.strictEqual(
infoMessages.length,
1,
'Test 2 failed: api2 should forward logs to the logger registered via api1'
);
assert.strictEqual(
infoMessages[0],
'shared-state-check',
'Test 2 failed: unexpected log message received'
);

// clean-up
clearGlobal();
Loading