Skip to content

Commit d67a514

Browse files
committed
merge from main
2 parents f372865 + 26eac90 commit d67a514

48 files changed

Lines changed: 3295 additions & 4620 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/docs-test.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Documentation tests
2+
3+
on:
4+
schedule:
5+
- cron: '0 6 * * 1'
6+
workflow_dispatch:
7+
8+
permissions:
9+
contents: read
10+
11+
jobs:
12+
docs-test:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
18+
with:
19+
persist-credentials: false
20+
- uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0
21+
with:
22+
cache: 'npm'
23+
cache-dependency-path: |
24+
package-lock.json
25+
node-version: ^26.3.0
26+
27+
- name: Bootstrap
28+
run: npm ci --ignore-scripts
29+
30+
- name: Build documentation
31+
run: |
32+
npm run compile
33+
NODE_OPTIONS=--max-old-space-size=6144 npm run docs
34+
35+
- name: Check documentation links
36+
run: npm run docs:test

.github/workflows/lint.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,3 @@ jobs:
3333
run: |
3434
npm run lint
3535
npm run lint:examples
36-
37-
- name: Lint doc files
38-
run: |
39-
npm run compile
40-
NODE_OPTIONS=--max-old-space-size=6144 npm run docs
41-
npm run docs:test

.github/workflows/ossf-scorecard.yml

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,40 +8,12 @@ on:
88
- cron: "44 18 * * 6" # once a week
99
workflow_dispatch:
1010

11-
permissions: read-all
11+
permissions: {}
1212

1313
jobs:
1414
analysis:
15-
runs-on: ubuntu-latest
1615
permissions:
17-
# Needed for Code scanning upload
18-
security-events: write
19-
# Needed for GitHub OIDC token if publish_results is true
20-
id-token: write
21-
steps:
22-
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0
23-
with:
24-
persist-credentials: false
25-
26-
- uses: ossf/scorecard-action@2d1146689b8cda280b9bc96326124645441f03bc # v2.4.4
27-
with:
28-
results_file: results.sarif
29-
results_format: sarif
30-
publish_results: true
31-
32-
# Upload the results as artifacts (optional). Commenting out will disable
33-
# uploads of run results in SARIF format to the repository Actions tab.
34-
# https://docs.github.com/en/actions/advanced-guides/storing-workflow-data-as-artifacts
35-
- name: "Upload artifact"
36-
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
37-
with:
38-
name: SARIF file
39-
path: results.sarif
40-
retention-days: 5
41-
42-
# Upload the results to GitHub's code scanning dashboard (optional).
43-
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
44-
- name: "Upload to code-scanning"
45-
uses: github/codeql-action/upload-sarif@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
46-
with:
47-
sarif_file: results.sarif
16+
contents: read # for actions/checkout
17+
id-token: write # for Scorecard to publish results
18+
security-events: write # for the SARIF upload to code scanning
19+
uses: open-telemetry/shared-workflows/.github/workflows/scorecard.yml@f13d0cb656d7244ca8c1638b6996dbaef1083bdd # v0.6.0

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2
1515
### :rocket: Features
1616

1717
* feat(resources): Deprecate `envDetector` in favor of separate `resourceAttributesEnvDetector` and `serviceNameEnvDetector`. Also mark `serviceInstanceIdDetector` as stable (the `service.instance.id` semconv attribute is now stable). [#6999](https://github.com/open-telemetry/opentelemetry-js/pull/6999) @trentm
18+
* feat(context-async-hooks): implement `attach()` on `AsyncLocalStorageContextManager` [#6845](https://github.com/open-telemetry/opentelemetry-js/pull/6845) @pichlermarc
19+
* On Node.js 25.9+, delegates to `AsyncLocalStorage.withScope()` returning a native `RunScope`. On older Node.js, falls back to `enterWith()` with a manual disposable wrapper.
1820
* feat(sdk-trace): allow configuring the force flush timeout per call #6929 @LarryHu0217
1921

2022
### :bug: Bug Fixes
@@ -23,6 +25,7 @@ For notes on migrating to 2.x / 0.200.x see [the upgrade guide](doc/upgrade-to-2
2325

2426
### :house: Internal
2527

28+
* chore(ci): run documentation tests on a weekly schedule [#6920](https://github.com/open-telemetry/opentelemetry-js/pull/6920) @LarryHu0217
2629
* chore(resources): Ensure that multiple uses of serviceInstanceIdDetector.detect() return the *same* value for `service.instance.id`
2730

2831
## 2.10.0

api/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,18 @@ All notable changes to this project will be documented in this file.
99

1010
### :rocket: Features
1111

12+
* feat(api): add imperative `context.attach()` for setting context across callback boundaries that `with()` cannot wrap. [#6845](https://github.com/open-telemetry/opentelemetry-js/pull/6845) @pichlermarc
13+
* `attach()` returns a `Token` whose `dispose()` method restores the previous context. Use `token.dispose()` to detach.
14+
* `attach` is an optional method on the `ContextManager` interface; when the active context manager does not implement it, `context.attach()` logs a warning and returns a no-op token.
15+
1216
### :bug: Bug Fixes
1317

1418
### :books: Documentation
1519

1620
### :house: Internal
1721

22+
* perf(api): add getGlobal fast-path [#6956](https://github.com/open-telemetry/opentelemetry-js/pull/6956) @legendecas
23+
1824
## 1.9.1
1925

2026
### :bug: (Bug Fix)

api/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"lint": "eslint . && npm run cycle-check",
2929
"test:browser": "karma start --single-run",
3030
"test": "nyc mocha 'test/**/*.test.ts'",
31+
"test:bench": "node test/performance/benchmark/internal-benchmarks.js && node test/performance/benchmark/public-benchmarks.js | tee .benchmark-results.txt",
3132
"test:node8-compat": "node test/backcompat/node8-compat.js",
3233
"test:webworker": "karma start karma.worker.js --single-run",
3334
"cycle-check": "dpdm --exit-code circular:1 src/index.ts",
@@ -73,7 +74,7 @@
7374
"@types/webpack": "5.28.5",
7475
"@types/webpack-env": "1.18.8",
7576
"babel-plugin-istanbul": "8.0.0",
76-
"dpdm": "4.2.0",
77+
"dpdm": "4.3.0",
7778
"karma": "6.4.4",
7879
"karma-chrome-launcher": "3.1.0",
7980
"karma-coverage": "2.2.1",

api/src/api/context.ts

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
*/
55

66
import { NoopContextManager } from '../context/NoopContextManager';
7-
import type { Context, ContextManager } from '../context/types';
7+
import type {
8+
Context,
9+
ContextManager,
10+
ContextManagementToken,
11+
} from '../context/types';
812
import {
913
getGlobal,
1014
registerGlobal,
@@ -14,6 +18,9 @@ import { DiagAPI } from './diag';
1418

1519
const API_NAME = 'context';
1620
const NOOP_CONTEXT_MANAGER = new NoopContextManager();
21+
const NOOP_TOKEN: ContextManagementToken = Object.freeze({
22+
dispose: () => {},
23+
});
1724

1825
/**
1926
* Singleton object which represents the entry point to the OpenTelemetry Context API
@@ -23,6 +30,12 @@ const NOOP_CONTEXT_MANAGER = new NoopContextManager();
2330
export class ContextAPI {
2431
private static _instance?: ContextAPI;
2532

33+
/**
34+
* Tracks whether we have already warned that the active ContextManager does
35+
* not implement attach(), so we warn at most once instead of on every call.
36+
*/
37+
private _attachUnsupportedWarned = false;
38+
2639
/** Empty private constructor prevents end users from constructing a new instance of the API */
2740
private constructor() {}
2841

@@ -78,6 +91,42 @@ export class ContextAPI {
7891
return this._getContextManager().bind(context, target);
7992
}
8093

94+
/**
95+
* Imperatively sets `context` as active, returning a {@link ContextManagementToken} whose
96+
* {@link ContextManagementToken.dispose} restores the previous context.
97+
*
98+
* This is a delicate, low-level API - prefer {@link with}/{@link bind}, which
99+
* restore context automatically. Use `attach` only to bridge callback
100+
* boundaries that `with` cannot wrap. Call `token.dispose()` when the
101+
* operation is done.
102+
*
103+
* **Caveat for async functions:** If called inside an async function before
104+
* the first `await`, the context change may leak into the caller's context
105+
* and remain active there. Prefer {@link with} for async code.
106+
*
107+
* Support is best-effort and varies by the active ContextManager (see
108+
* {@link ContextManager.attach}); if it does not implement `attach`, this logs
109+
* a warning and returns a no-op token.
110+
*
111+
* @param context The Context to attach
112+
* @returns A {@link ContextManagementToken} whose dispose() restores the previous Context
113+
* @since 1.10.0
114+
* @experimental This API is experimental and may change in minor releases without prior notice.
115+
*/
116+
public attach(context: Context): ContextManagementToken {
117+
const contextManager = this._getContextManager();
118+
if (contextManager.attach) {
119+
return contextManager.attach(context);
120+
}
121+
if (!this._attachUnsupportedWarned) {
122+
this._attachUnsupportedWarned = true;
123+
DiagAPI.instance().warn(
124+
'The current ContextManager does not implement attach(). The context will not be attached. Use a ContextManager that supports attach() (e.g. AsyncLocalStorageContextManager) or use with()/bind() instead.'
125+
);
126+
}
127+
return NOOP_TOKEN;
128+
}
129+
81130
private _getContextManager(): ContextManager {
82131
return getGlobal(API_NAME) || NOOP_CONTEXT_MANAGER;
83132
}

api/src/context/NoopContextManager.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,9 @@ export class NoopContextManager implements types.ContextManager {
3131
disable(): this {
3232
return this;
3333
}
34+
35+
/** @experimental This API is experimental and may change in minor releases without prior notice. */
36+
attach(_context: types.Context): types.ContextManagementToken {
37+
return { dispose() {} };
38+
}
3439
}

api/src/context/types.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ export interface Context {
3232
deleteValue(key: symbol): Context;
3333
}
3434

35+
/**
36+
* A scope token returned by {@link ContextManager.attach} that restores the previous
37+
* {@link Context} when disposed. Call `token.dispose()` to restore the previous context.
38+
*
39+
* @since 1.10.0
40+
* @experimental This API is experimental and may change in minor releases without prior notice.
41+
*/
42+
export interface ContextManagementToken {
43+
dispose(): void;
44+
}
45+
3546
/**
3647
* @since 1.0.0
3748
*/
@@ -71,4 +82,26 @@ export interface ContextManager {
7182
* Disable context management
7283
*/
7384
disable(): this;
85+
86+
/**
87+
* Imperatively sets `context` as active, returning a {@link ContextManagementToken} whose
88+
* {@link ContextManagementToken.dispose} method restores the previous context.
89+
*
90+
* This is a delicate, low-level API - prefer {@link with}/{@link bind}, which
91+
* restore context automatically. `attach` exists only to bridge callback
92+
* boundaries that `with` cannot wrap. The caller is responsible for disposing
93+
* the token via `token.dispose()` when the operation is complete. Support is
94+
* optional and best-effort; when omitted, {@link ContextAPI.attach} logs a
95+
* warning and returns a no-op token.
96+
*
97+
* **Caveat for async functions:** If called inside an async function before
98+
* the first `await`, the context change may leak into the caller's context
99+
* and remain active there. Prefer {@link with} for async code.
100+
*
101+
* @param context The Context to attach
102+
* @returns A {@link ContextManagementToken} whose dispose() restores the previous Context
103+
* @since 1.10.0
104+
* @experimental This API is experimental and may change in minor releases without prior notice.
105+
*/
106+
attach?(context: Context): ContextManagementToken;
74107
}

api/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ export type { Attributes, AttributeValue } from './common/Attributes';
1919

2020
// Context APIs
2121
export { createContextKey, ROOT_CONTEXT } from './context/context';
22-
export type { Context, ContextManager } from './context/types';
22+
export type {
23+
Context,
24+
ContextManager,
25+
ContextManagementToken,
26+
} from './context/types';
2327
export type { ContextAPI } from './api/context';
2428

2529
// Diag APIs

0 commit comments

Comments
 (0)