上下文
The content of this page may be outdated and some links may be invalid.
A newer version of this page exists in
English. To see the changes to the English page since this page was last updated: visit
GitHub compare 2c3d80ca..801b996d
and search for More information ...
content/en/docs/languages/js/context.md.
要使 OpenTelemetry 正常工作,它必须对关键遥测数据进行存储与传递。 例如,当系统接收到请求并启动一个追踪 Span 时,该 Span 必须能够被后续创建其子 Span 的组件所访问。 为解决该问题,OpenTelemetry 会将追踪 Span 存储在上下文中。 本文档介绍了适用于 JavaScript 的 OpenTelemetry 上下文 API,以及具体使用方法。
上下文管理器
上下文 API 依赖于上下文管理器才能工作。 本文档中的示例将假设你已经配置好了一个上下文管理器。 通常上下文管理器由你的 SDK 提供,但是也可以直接注册一个,如下所示:
import * as api from '@opentelemetry/api';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
const contextManager = new AsyncHooksContextManager();
contextManager.enable();
api.context.setGlobalContextManager(contextManager);
Root 上下文
ROOT_CONTEXT 是一个空上下文。
如果当前没有活跃上下文,ROOT_CONTEXT 就会成为活跃上下文。
关于活跃上下文的详细信息,请参考活跃上下文。
上下文键
上下文条目是键值对。
键可以通过调用 api.createContextKey(description) 来创建。
import * as api from '@opentelemetry/api';
const key1 = api.createContextKey('My first key');
const key2 = api.createContextKey('My second key');
基本操作
获取条目
条目可以通过 context.getValue(key) 方法来访问。
import * as api from '@opentelemetry/api';
const key = api.createContextKey('some key');
// ROOT_CONTEXT 是一个空上下文
const ctx = api.ROOT_CONTEXT;
const value = ctx.getValue(key);
设置条目
条目可以通过 context.setValue(key, value) 方法来创建。
设置上下文条目会创建一个新上下文,其中包含前一个上下文的所有条目,但包含新条目。
设置上下文条目不会修改前一个上下文。
import * as api from '@opentelemetry/api';
const key = api.createContextKey('some key');
const ctx = api.ROOT_CONTEXT;
// 添加一个新条目
const ctx2 = ctx.setValue(key, 'context 2');
// ctx2 包含新条目
console.log(ctx2.getValue(key)); // "context 2"
// ctx 未被修改
console.log(ctx.getValue(key)); // undefined
删除条目
条目可以通过调用 context.deleteValue(key) 方法来删除。
删除上下文条目会创建一个新上下文,其中包含前一个上下文的所有条目,但不包含被标识为键的条目。
删除上下文条目不会修改前一个上下文。
import * as api from '@opentelemetry/api';
const key = api.createContextKey('some key');
const ctx = api.ROOT_CONTEXT;
const ctx2 = ctx.setValue(key, 'context 2');
// 删除条目
const ctx3 = ctx2.deleteValue(key);
// ctx3 不包含条目
console.log(ctx3.getValue(key)); // undefined
// ctx2 未被修改
console.log(ctx2.getValue(key)); // "context 2"
// ctx 未被修改
console.log(ctx.getValue(key)); // undefined
活跃上下文
IMPORTANT: 此假设你已经配置了上下文管理器。如果没有配置,api.context.active() 将始终返回 ROOT_CONTEXT。
活跃上下文是指由 api.context.active() 返回的上下文。
上下文对象包含一些条目,这些条目允许追踪组件在追踪单个执行线程时相互通信,并确保追踪成功创建。
例如,当创建一个 Span 时,它可以添加到上下文中。
之后,当创建另一个 Span 时,它可以使用上下文中的 Span 作为其父 Span。
这一能力,是通过各类机制实现的,Node.js 环境下借助
async_hooks 或
AsyncLocalStorage,浏览器环境下则依托
zone.js,以此确保上下文能在单次执行链路中完成传递。
如果没有上下文处于活跃状态,则返回 ROOT_CONTEXT,它只是一个空的上下文对象。
获取活跃上下文
活跃上下文,是指由 api.context.active() 返回的上下文。
import * as api from '@opentelemetry/api';
// 返回当前活跃上下文
// 如果没有活跃上下文,返回 ROOT_CONTEXT
const ctx = api.context.active();
设置活跃上下文
可以使用 api.context.with(ctx, callback) 来激活一个上下文。在执行
callback 回调期间,传递给 with 的上下文将成为 context.active 的返回值。
import * as api from '@opentelemetry/api';
const key = api.createContextKey('Key to store a value');
const ctx = api.context.active();
api.context.with(ctx.setValue(key, 'context 2'), async () => {
// "context 2" 是活跃上下文
console.log(api.context.active().getValue(key)); // "context 2"
});
api.context.with(context, callback) 的返回值,是回调的返回值。回调总是同步调用。
import * as api from '@opentelemetry/api';
const name = await api.context.with(api.context.active(), async () => {
const row = await db.getSomeValue();
return row['name'];
});
console.log(name); // 数据库返回的 name
活跃上下文执行可能是嵌套的。
import * as api from '@opentelemetry/api';
const key = api.createContextKey('Key to store a value');
const ctx = api.context.active();
// 没有活跃上下文
console.log(api.context.active().getValue(key)); // undefined
api.context.with(ctx.setValue(key, 'context 2'), () => {
// "context 2" 是活跃上下文
console.log(api.context.active().getValue(key)); // "context 2"
api.context.with(ctx.setValue(key, 'context 3'), () => {
// "context 3" 是活跃上下文
console.log(api.context.active().getValue(key)); // "context 3"
});
// "context 2" 是活跃上下文
console.log(api.context.active().getValue(key)); // "context 2"
});
// 没有活跃上下文
console.log(api.context.active().getValue(key)); // undefined
示例
这个更复杂的示例展示了上下文如何不被修改,而是创建新的上下文对象。
import * as api from '@opentelemetry/api';
const ctx = api.context.active(); // 当没有活跃上下文时返回 ROOT_CONTEXT
const ctx2 = ctx.setValue(key, 'context 2'); // 不会修改 ctx
console.log(ctx.getValue(key)); //? undefined
console.log(ctx2.getValue(key)); //? "context 2"
const ret = api.context.with(ctx2, () => {
const ctx3 = api.context.active().setValue(key, 'context 3');
console.log(api.context.active().getValue(key)); //? "context 2"
console.log(ctx.getValue(key)); //? undefined
console.log(ctx2.getValue(key)); //? "context 2"
console.log(ctx3.getValue(key)); //? "context 3"
api.context.with(ctx3, () => {
console.log(api.context.active().getValue(key)); //? "context 3"
});
console.log(api.context.active().getValue(key)); //? "context 2"
return 'return value';
});
// 回调返回的值会返回给调用方
console.log(ret); //? "return value"
意见反馈
这个页面对您有帮助吗?
Thank you. Your feedback is appreciated!
Please let us know how we can improve this page. Your feedback is appreciated!