@telemetry-dev/sdk 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -5
- package/dist/index.d.mts +160 -7
- package/dist/index.mjs +315 -14
- package/package.json +8 -8
- package/src/capture.ts +3 -2
- package/src/client.ts +8 -4
- package/src/config.ts +6 -6
- package/src/index.ts +19 -0
- package/src/prompts.ts +701 -0
- package/src/span.ts +15 -6
package/README.md
CHANGED
|
@@ -78,16 +78,27 @@ other string attribute is cut at the cap without a marker, except that a cap of
|
|
|
78
78
|
`exportTimeoutMillis` 30000), `spanFilter`, `resourceAttributes`, `logLevel` (SDK diagnostics,
|
|
79
79
|
default `"warn"`), `fetch`, `waitUntil`, `onError`.
|
|
80
80
|
|
|
81
|
+
Core SDK error recording keeps failure status, error type, and an exception event. It includes
|
|
82
|
+
`exception.message` and `exception.stacktrace` only when both effective `captureInput` and
|
|
83
|
+
`captureOutput` are true, including per-span overrides: exceptions can echo either inputs or
|
|
84
|
+
outputs. The policy is per span: when an error propagates to an enclosing span whose capture is on,
|
|
85
|
+
that span records its message and stack. Included fields pass through `mask` with their exception
|
|
86
|
+
attribute keys, then serialization and truncation. A throwing mask drops the affected field and reports a generic error to `onError`
|
|
87
|
+
and SDK diagnostics without the hook's original message or cause. The original application error
|
|
88
|
+
is rethrown unchanged. These controls do not scrub error type names, metadata, identifiers, resource
|
|
89
|
+
attributes, or events written directly through raw OpenTelemetry APIs.
|
|
90
|
+
|
|
81
91
|
`captureInput: false` and `captureOutput: false` omit captured content. Provider integrations may
|
|
82
92
|
still record non-content metadata such as response IDs and models, finish reasons, usage, timing,
|
|
83
|
-
and
|
|
84
|
-
|
|
93
|
+
and error types. Capture flags do not gate stop sequences, tool descriptions and definitions
|
|
94
|
+
(`gen_ai.tool.description`, `gen_ai.tool.definitions`), caller-supplied metadata or raw attributes;
|
|
95
|
+
redact those separately when needed.
|
|
85
96
|
|
|
86
97
|
`mask` receives input and output content, system instructions, log messages, log attributes
|
|
87
98
|
other than numbers and booleans, and content that integrations pass to
|
|
88
|
-
`handle.serializeContent
|
|
89
|
-
span or propagated `metadata
|
|
90
|
-
those separately.
|
|
99
|
+
`handle.serializeContent`, including captured exception messages and stack traces. `ctx.key` names
|
|
100
|
+
the attribute being written. It does not receive span or propagated `metadata` or raw `attributes`;
|
|
101
|
+
redact those separately. Log masking is independent of span capture flags.
|
|
91
102
|
|
|
92
103
|
Root spans remain independent by default. `init({ sessionMode: "process" })` groups otherwise
|
|
93
104
|
uncorrelated spans and logs using a fresh opaque UUID for each enabled SDK initialization.
|
|
@@ -100,6 +111,69 @@ The default is parent-based always-on. Session roots keep the configured root po
|
|
|
100
111
|
Nested spans and explicitly parented spans keep the real parent's policy.
|
|
101
112
|
The SDK installs the [session sampling wrapper](https://github.com/telemetry-dev/telemetry/blob/main/packages/otel/README.md#correlation-attributes) on its provider. This includes the global provider that Eve uses.
|
|
102
113
|
|
|
114
|
+
## Prompts
|
|
115
|
+
|
|
116
|
+
`getPrompt` fetches a prompt that you manage in telemetry.dev. Fetch it by its label, so that you
|
|
117
|
+
deploy a version when you move the label, without a change to the code:
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
import OpenAI from "openai";
|
|
121
|
+
import { getPrompt, init, withPrompt } from "@telemetry-dev/sdk";
|
|
122
|
+
import { wrapOpenAI } from "@telemetry-dev/openai";
|
|
123
|
+
|
|
124
|
+
init();
|
|
125
|
+
const openai = wrapOpenAI(new OpenAI());
|
|
126
|
+
|
|
127
|
+
const prompt = await getPrompt("support/reply", { label: "production" });
|
|
128
|
+
const messages = prompt.compile({ customer_message, tone });
|
|
129
|
+
|
|
130
|
+
const response = await withPrompt(prompt, () =>
|
|
131
|
+
openai.chat.completions.create({ model: prompt.model?.name ?? "gpt-4o", messages }),
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
// Pin one version, as in a test:
|
|
135
|
+
const pinned = await getPrompt("support/reply", { version: 13 });
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
- Without `label` and `version`, getPrompt fetches the `production` label. A text prompt needs
|
|
139
|
+
`type: "text"`; getPrompt rejects a prompt of the other type.
|
|
140
|
+
- `compile(variables)` puts the values in place of `{{name}}`. A missing value becomes an empty
|
|
141
|
+
text, and a value that is not a string becomes JSON. In a chat prompt, a placeholder message
|
|
142
|
+
becomes the list of messages in its variable. A text prompt compiles to a string.
|
|
143
|
+
- The prompt also has `model`, `parameters`, `tools`, and `responseFormat` of its version.
|
|
144
|
+
- getPrompt keeps each prompt. When the copy is older than `cacheTtlSeconds` (default 60), a call
|
|
145
|
+
returns it at once and fetches a new copy in the background. Only a call with no copy waits for a
|
|
146
|
+
fetch, for 10 seconds at most. Calls for the same prompt share one fetch.
|
|
147
|
+
- If a fetch fails, getPrompt returns the last copy that it fetched and reports the error through
|
|
148
|
+
`onError`. With no copy, it returns the `fallback` option (`version` is `null` and `isFallback`
|
|
149
|
+
is `true`). With no fallback, it rejects with a `PromptError` whose `code` tells why, for
|
|
150
|
+
example `prompt_not_found`, `label_not_found`, `insufficient_scope`, `missing_api_key`, or
|
|
151
|
+
`timeout`. A response with a different status and no API error gives `http_<status>`, for
|
|
152
|
+
example `http_302` for a redirect. getPrompt does not send the request to the location of a
|
|
153
|
+
redirect, thus your key does not go to a different host. With no copy, the calls of the next 10
|
|
154
|
+
seconds (or the TTL, if it is shorter) get the same result without a fetch. This is the one SDK
|
|
155
|
+
function that can reject: your app cannot run without its prompt.
|
|
156
|
+
- getPrompt uses the API key and base URL of an enabled `init()`, or `TELEMETRY_DEV_API_KEY` and
|
|
157
|
+
`TELEMETRY_DEV_BASE_URL`, or its own `apiKey`, `baseUrl`, and `fetch` options. It reads the same
|
|
158
|
+
host that telemetry goes to, `https://ingest.telemetry.dev` by default. The key needs the read
|
|
159
|
+
scope for prompts.
|
|
160
|
+
- When a label sends part of the traffic to a second version, each session keeps one version: the
|
|
161
|
+
choice uses the session id of `propagateAttributes` (or of `sessionMode: "process"`). Without a
|
|
162
|
+
session id, each call chooses at random.
|
|
163
|
+
|
|
164
|
+
`withPrompt(prompt, fn)` records the prompt on each model call that starts inside `fn`:
|
|
165
|
+
`td.prompt.name`, `td.prompt.version`, and `td.prompt.label` (only for a prompt fetched by label).
|
|
166
|
+
When input capture is on, `td.prompt.variables` holds the JSON of the variables of the last
|
|
167
|
+
`compile()` of that prompt object before `withPrompt` starts, or of the last `compile()` inside
|
|
168
|
+
`fn`, after `mask` and truncation. If tasks that run at the same time share one prompt object, call
|
|
169
|
+
`compile()` in `withPrompt`, or call getPrompt in each task. getPrompt returns a new object from
|
|
170
|
+
the cache. If you do not, a task can record the variables of a different task. Model calls are the
|
|
171
|
+
spans of type `generation` (operations `chat`, `text_completion`, and `generate_content`),
|
|
172
|
+
including the spans of the provider integrations that use this SDK: OpenAI, Anthropic, Amazon
|
|
173
|
+
Bedrock, Google GenAI, and OpenRouter. Spans from the AI SDK and TanStack AI integrations, and from
|
|
174
|
+
other OpenTelemetry tracers, do not get the attributes. Messages from `compile()` that you pass to
|
|
175
|
+
a model call outside `withPrompt` are not recorded.
|
|
176
|
+
|
|
103
177
|
## API
|
|
104
178
|
|
|
105
179
|
- `init(options?)` — create the client (isolated OTel TracerProvider by default).
|
|
@@ -119,6 +193,8 @@ The SDK installs the [session sampling wrapper](https://github.com/telemetry-dev
|
|
|
119
193
|
- `updateActiveSpan(fields)` — update the innermost active span.
|
|
120
194
|
- `propagateAttributes({ userId, sessionId, metadata }, fn)` — stamps `user.id`,
|
|
121
195
|
`gen_ai.conversation.id`, and `td.metadata.*` on every span and log record in scope.
|
|
196
|
+
- `getPrompt(name, options?)` — fetch a prompt by label or version; see [Prompts](#prompts).
|
|
197
|
+
- `withPrompt(prompt, fn)` — record the prompt on each model call in `fn`.
|
|
122
198
|
- `log(message, { level, eventName, attributes }?)` — log record correlated to the active trace.
|
|
123
199
|
- `getTraceparent()` — W3C traceparent of the active span (pass to other services; accept it via
|
|
124
200
|
`startSpan(name, { parent })`).
|
package/dist/index.d.mts
CHANGED
|
@@ -7,8 +7,8 @@ import { PushMetricExporter } from "@opentelemetry/sdk-metrics";
|
|
|
7
7
|
//#region src/config.d.ts
|
|
8
8
|
/**
|
|
9
9
|
* Redaction hook applied to captured content (input/output, log messages and attributes, and
|
|
10
|
-
* content passed to `SpanHandle.serializeContent`)
|
|
11
|
-
* metadata or raw attributes.
|
|
10
|
+
* content passed to `SpanHandle.serializeContent`), including exception messages/stacks, before
|
|
11
|
+
* JSON stringification. Not applied to metadata or raw attributes.
|
|
12
12
|
*/
|
|
13
13
|
type MaskFn<T = unknown> = (value: T, ctx: {
|
|
14
14
|
key: string;
|
|
@@ -16,7 +16,7 @@ type MaskFn<T = unknown> = (value: T, ctx: {
|
|
|
16
16
|
interface TelemetryOptions {
|
|
17
17
|
/** telemetry.dev ingest key (`td_live_…`). Falls back to `TELEMETRY_DEV_API_KEY`. When absent the SDK is a no-op. */
|
|
18
18
|
apiKey?: string;
|
|
19
|
-
/**
|
|
19
|
+
/** Base URL for telemetry export and getPrompt. Falls back to `TELEMETRY_DEV_BASE_URL`, then `https://ingest.telemetry.dev`. */
|
|
20
20
|
baseUrl?: string;
|
|
21
21
|
/** Deployment environment label. Falls back to `TELEMETRY_DEV_ENVIRONMENT`, then `production`. */
|
|
22
22
|
environment?: string;
|
|
@@ -32,9 +32,9 @@ interface TelemetryOptions {
|
|
|
32
32
|
exportMode?: ExportMode$1;
|
|
33
33
|
/** OTel sampling policy. Defaults to OTEL_TRACES_SAMPLER / OTEL_TRACES_SAMPLER_ARG. */
|
|
34
34
|
sampler?: Sampler;
|
|
35
|
-
/** Capture span inputs (args, prompts)
|
|
35
|
+
/** Capture span inputs (args, prompts). False also omits exception messages/stacks. Default true. */
|
|
36
36
|
captureInput?: boolean;
|
|
37
|
-
/** Capture span outputs (results, completions)
|
|
37
|
+
/** Capture span outputs (results, completions). False also omits exception messages/stacks. Default true. */
|
|
38
38
|
captureOutput?: boolean;
|
|
39
39
|
/** Redaction hook run on captured content before stringify/truncate. */
|
|
40
40
|
mask?: MaskFn;
|
|
@@ -57,7 +57,7 @@ interface TelemetryOptions {
|
|
|
57
57
|
fetch?: typeof fetch;
|
|
58
58
|
/** Serverless extender (e.g. Cloudflare `ctx.waitUntil`). When provided, `flush()` does not await exports. */
|
|
59
59
|
waitUntil?: (p: Promise<unknown>) => void;
|
|
60
|
-
/** Receives errors raised while emitting telemetry; repeated instrumentation failures from one stream may be coalesced into one report. The SDK never throws into user code. */
|
|
60
|
+
/** Receives errors raised while emitting telemetry; repeated instrumentation failures from one stream may be coalesced into one report. A series of failed exports is reported once, and the next failure after an export reaches the ingest is reported again. The SDK never throws into user code. */
|
|
61
61
|
onError?: (cause: Error) => void;
|
|
62
62
|
/** Header value for a custom telemetry.dev integration. */
|
|
63
63
|
sdkName?: string;
|
|
@@ -257,4 +257,157 @@ interface ObserveOptions extends StartSpanOptions {
|
|
|
257
257
|
*/
|
|
258
258
|
declare function observe<TThis, TArgs extends unknown[], TReturn>(fn: (this: TThis, ...args: TArgs) => TReturn, options?: ObserveOptions): (...args: TArgs) => TReturn;
|
|
259
259
|
//#endregion
|
|
260
|
-
|
|
260
|
+
//#region src/prompts.d.ts
|
|
261
|
+
/** A message of a chat prompt. A placeholder stands for a list of messages that the app passes. */
|
|
262
|
+
type PromptMessage = {
|
|
263
|
+
readonly role: "system" | "user" | "assistant";
|
|
264
|
+
readonly content: string;
|
|
265
|
+
} | {
|
|
266
|
+
readonly role: "placeholder";
|
|
267
|
+
readonly name: string;
|
|
268
|
+
};
|
|
269
|
+
/** A message that `compile()` makes from a prompt message. */
|
|
270
|
+
interface ChatMessage {
|
|
271
|
+
role: "system" | "user" | "assistant";
|
|
272
|
+
content: string;
|
|
273
|
+
}
|
|
274
|
+
interface PromptModel {
|
|
275
|
+
readonly provider: string;
|
|
276
|
+
readonly name: string;
|
|
277
|
+
}
|
|
278
|
+
/** The parameters that are set in the version. A parameter that is not set is absent. */
|
|
279
|
+
interface PromptParameters {
|
|
280
|
+
readonly temperature?: number;
|
|
281
|
+
readonly topP?: number;
|
|
282
|
+
readonly maxTokens?: number;
|
|
283
|
+
readonly frequencyPenalty?: number;
|
|
284
|
+
readonly presencePenalty?: number;
|
|
285
|
+
readonly stop?: readonly string[];
|
|
286
|
+
readonly seed?: number;
|
|
287
|
+
readonly toolChoice?: "auto" | "none" | "required" | {
|
|
288
|
+
readonly tool: string;
|
|
289
|
+
};
|
|
290
|
+
readonly parallelToolCalls?: boolean;
|
|
291
|
+
}
|
|
292
|
+
interface PromptTool {
|
|
293
|
+
readonly name: string;
|
|
294
|
+
readonly description: string;
|
|
295
|
+
/** JSON schema of the tool arguments. */
|
|
296
|
+
readonly parameters: Readonly<Record<string, unknown>>;
|
|
297
|
+
readonly strict: boolean;
|
|
298
|
+
}
|
|
299
|
+
type PromptResponseFormat = {
|
|
300
|
+
readonly type: "text";
|
|
301
|
+
} | {
|
|
302
|
+
readonly type: "json_object";
|
|
303
|
+
} | {
|
|
304
|
+
readonly type: "json_schema";
|
|
305
|
+
readonly name: string;
|
|
306
|
+
readonly schema: Readonly<Record<string, unknown>>;
|
|
307
|
+
readonly strict: boolean;
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* Values for `{{name}}` variables. A missing value, null, or undefined becomes an empty text, and a
|
|
311
|
+
* value that is not a string becomes JSON. A placeholder message takes a list of messages.
|
|
312
|
+
*/
|
|
313
|
+
type PromptVariables<M = ChatMessage> = Readonly<Record<string, string | number | boolean | null | undefined | readonly M[]>>;
|
|
314
|
+
interface PromptBase {
|
|
315
|
+
readonly name: string;
|
|
316
|
+
/** The version that the app got; null for the fallback. */
|
|
317
|
+
readonly version: number | null;
|
|
318
|
+
/** The label that the prompt was fetched by; null when it was fetched by version. */
|
|
319
|
+
readonly label: string | null;
|
|
320
|
+
/** Null for the fallback. */
|
|
321
|
+
readonly model: PromptModel | null;
|
|
322
|
+
readonly parameters: PromptParameters;
|
|
323
|
+
readonly tools: readonly PromptTool[];
|
|
324
|
+
readonly responseFormat: PromptResponseFormat;
|
|
325
|
+
/** True when getPrompt could not fetch the prompt and returned the `fallback` option. */
|
|
326
|
+
readonly isFallback: boolean;
|
|
327
|
+
}
|
|
328
|
+
interface ChatPrompt extends PromptBase {
|
|
329
|
+
readonly type: "chat";
|
|
330
|
+
readonly messages: readonly PromptMessage[];
|
|
331
|
+
readonly text: null;
|
|
332
|
+
/**
|
|
333
|
+
* Fills in the variables and replaces each placeholder message with the messages in its
|
|
334
|
+
* variable. `withPrompt` records the variables of the last call before it starts or inside it.
|
|
335
|
+
*/
|
|
336
|
+
compile<M = ChatMessage>(variables?: PromptVariables<M>): (ChatMessage | M)[];
|
|
337
|
+
}
|
|
338
|
+
interface TextPrompt extends PromptBase {
|
|
339
|
+
readonly type: "text";
|
|
340
|
+
readonly messages: readonly [];
|
|
341
|
+
readonly text: string;
|
|
342
|
+
/**
|
|
343
|
+
* Fills in the variables. `withPrompt` records the variables of the last call before it starts
|
|
344
|
+
* or inside it.
|
|
345
|
+
*/
|
|
346
|
+
compile(variables?: PromptVariables): string;
|
|
347
|
+
}
|
|
348
|
+
type Prompt = ChatPrompt | TextPrompt;
|
|
349
|
+
interface GetPromptOptionsBase {
|
|
350
|
+
/** Fetch the version that this label points to. Default "production" when `version` is not set. */
|
|
351
|
+
label?: string;
|
|
352
|
+
/** Fetch this version number. Do not set it together with `label`. */
|
|
353
|
+
version?: number;
|
|
354
|
+
/** Seconds before a call fetches a kept prompt again, in the background. Default 60. */
|
|
355
|
+
cacheTtlSeconds?: number;
|
|
356
|
+
/** API key with the prompts:read scope. Falls back to the initialized client, then `TELEMETRY_DEV_API_KEY`. */
|
|
357
|
+
apiKey?: string;
|
|
358
|
+
/** Falls back to the initialized client, then `TELEMETRY_DEV_BASE_URL`, then `https://ingest.telemetry.dev`. */
|
|
359
|
+
baseUrl?: string;
|
|
360
|
+
/** Falls back to the initialized client's `fetch`, then `globalThis.fetch`. */
|
|
361
|
+
fetch?: typeof fetch;
|
|
362
|
+
}
|
|
363
|
+
interface GetChatPromptOptions extends GetPromptOptionsBase {
|
|
364
|
+
/** Default "chat". getPrompt rejects a prompt of the other type. */
|
|
365
|
+
type?: "chat";
|
|
366
|
+
/** Messages to use when the prompt cannot be fetched and no copy of it is kept. */
|
|
367
|
+
fallback?: readonly PromptMessage[];
|
|
368
|
+
}
|
|
369
|
+
interface GetTextPromptOptions extends GetPromptOptionsBase {
|
|
370
|
+
type: "text";
|
|
371
|
+
/** Text to use when the prompt cannot be fetched and no copy of it is kept. */
|
|
372
|
+
fallback?: string;
|
|
373
|
+
}
|
|
374
|
+
type GetPromptOptions = GetChatPromptOptions | GetTextPromptOptions;
|
|
375
|
+
/**
|
|
376
|
+
* Why getPrompt failed. `code` is the code of the API error (`prompt_not_found`,
|
|
377
|
+
* `label_not_found`, `insufficient_scope`, `invalid_api_key`, …), or `missing_api_key`,
|
|
378
|
+
* `timeout`, `network_error`, `invalid_response`, or `type_mismatch`. A response with a different
|
|
379
|
+
* status and no API error gives `http_<status>`, for example `http_302` for a redirect: getPrompt
|
|
380
|
+
* does not go to the location of a redirect.
|
|
381
|
+
*/
|
|
382
|
+
declare class PromptError extends Error {
|
|
383
|
+
readonly code: string;
|
|
384
|
+
readonly status?: number | undefined;
|
|
385
|
+
readonly name = "PromptError";
|
|
386
|
+
constructor(code: string, message: string, status?: number | undefined, options?: {
|
|
387
|
+
cause?: unknown;
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Fetches a prompt version from telemetry.dev and keeps it. When the copy is older than
|
|
392
|
+
* `cacheTtlSeconds`, a call returns it at once and fetches a new one in the background. Only a call
|
|
393
|
+
* with no copy waits for a fetch, at most 10 seconds. Calls for the same prompt share one fetch.
|
|
394
|
+
* When a fetch fails, getPrompt returns the last copy that it kept; with no copy it returns
|
|
395
|
+
* `fallback`. With neither it rejects with a `PromptError`: unlike the telemetry functions,
|
|
396
|
+
* getPrompt cannot fail open, because the app cannot run without the prompt. With no copy, the
|
|
397
|
+
* calls of the next 10 seconds (or the TTL, if it is shorter) fail the same way without a fetch.
|
|
398
|
+
*
|
|
399
|
+
* A label with a gradual rollout gives each session one version: the choice uses the session id
|
|
400
|
+
* of `propagateAttributes`, or a random choice per call without one.
|
|
401
|
+
*/
|
|
402
|
+
declare function getPrompt(name: string, options: GetTextPromptOptions): Promise<TextPrompt>;
|
|
403
|
+
declare function getPrompt(name: string, options?: GetChatPromptOptions): Promise<ChatPrompt>;
|
|
404
|
+
/**
|
|
405
|
+
* Runs `fn` with `prompt` as the prompt of each model call (generation span) that starts inside
|
|
406
|
+
* it: the spans get `td.prompt.name`, `td.prompt.version`, `td.prompt.label`, and, when input
|
|
407
|
+
* capture is on, `td.prompt.variables`. The variables are those of the last `compile()` of this
|
|
408
|
+
* prompt object before withPrompt starts, or of the last `compile()` inside `fn`, so a compile in
|
|
409
|
+
* another task does not change them once withPrompt runs.
|
|
410
|
+
*/
|
|
411
|
+
declare function withPrompt<T>(prompt: Prompt, fn: () => T): T;
|
|
412
|
+
//#endregion
|
|
413
|
+
export { type AgentFields, type BatchOptions, type BoundedCaptureDetails, type BoundedCaptureOptions, type BoundedCaptureResult, type ChatMessage, type ChatPrompt, type ClientOverrides, type ExportMode, type GenerationFields, type GetChatPromptOptions, type GetPromptOptions, type GetTextPromptOptions, type LogLevel, type LogOptions, type MaskFn, type ObserveOptions, type ParentRef, type Prompt, PromptError, type PromptMessage, type PromptModel, type PromptParameters, type PromptResponseFormat, type PromptTool, type PromptVariables, type PropagatedAttributes, SCOPE_NAME, type SdkLogLevel, type SpanCapturePolicy, type SpanFields, type SpanHandle, type SpanType, type StartSpanOptions, type TelemetryClient, type TelemetryOptions, TelemetrySpanProcessor, type TelemetrySpanProcessorOptions, type TextPrompt, type TokenUsage, type ToolFields, activeContext, boundedCapture, boundedCaptureDetails, captureEnabled, captureMasked, extractW3cContext, flush, getPrompt, getTraceparent, init, injectW3cContext, log, observe, propagateAttributes, shutdown, startActiveSpan, startSpan, updateActiveSpan, withContext, withPrompt };
|