From a3b6c16f59b6bfc33f4607aae2e16e18fcbd2919 Mon Sep 17 00:00:00 2001 From: "lukexian.bryce" Date: Mon, 7 Apr 2025 14:35:02 +0800 Subject: [PATCH 1/3] chore(@cozeloop/ai): adjust code details --- .../cozeloop-ai-node/src/api/api-client.ts | 1 - examples/cozeloop-ai-node/src/prompt/hub.ts | 1 - .../cozeloop-ai-node/src/tracer/README.md | 1 - examples/cozeloop-ai-node/src/tracer/basic.ts | 40 ++++++++++ examples/cozeloop-ai-node/src/tracer/index.ts | 5 +- .../cozeloop-ai-node/src/tracer/large-text.ts | 2 +- .../src/tracer/{simple.ts => llm.ts} | 78 +------------------ .../src/tracer/multi-modality.ts | 2 +- examples/cozeloop-ai-node/src/tracer/root.ts | 20 +++++ examples/cozeloop-ai-node/src/tracer/utils.ts | 22 ++++++ .../__tests__/tracer/traceable.test.ts | 5 -- 11 files changed, 89 insertions(+), 88 deletions(-) create mode 100644 examples/cozeloop-ai-node/src/tracer/basic.ts rename examples/cozeloop-ai-node/src/tracer/{simple.ts => llm.ts} (54%) create mode 100644 examples/cozeloop-ai-node/src/tracer/root.ts create mode 100644 examples/cozeloop-ai-node/src/tracer/utils.ts diff --git a/examples/cozeloop-ai-node/src/api/api-client.ts b/examples/cozeloop-ai-node/src/api/api-client.ts index b106245..de9beff 100644 --- a/examples/cozeloop-ai-node/src/api/api-client.ts +++ b/examples/cozeloop-ai-node/src/api/api-client.ts @@ -23,7 +23,6 @@ export async function run() { // axiosOptions: {}, /** Custom headers */ // headers: {}; - headers: { 'x-tt-env': 'boe_commercial' }, // TODO: remove }); const resp = await apiClient.post<{ code: number }>('/v1/loop/prompts/mget', { diff --git a/examples/cozeloop-ai-node/src/prompt/hub.ts b/examples/cozeloop-ai-node/src/prompt/hub.ts index 4fd1651..08550c8 100644 --- a/examples/cozeloop-ai-node/src/prompt/hub.ts +++ b/examples/cozeloop-ai-node/src/prompt/hub.ts @@ -9,7 +9,6 @@ export async function run() { apiClient: { // baseURL: 'api_base_url', // token: 'your_api_token', - headers: { 'x-tt-env': 'boe_commercial' }, // TODO: remove }, }); diff --git a/examples/cozeloop-ai-node/src/tracer/README.md b/examples/cozeloop-ai-node/src/tracer/README.md index 57b4401..562a797 100644 --- a/examples/cozeloop-ai-node/src/tracer/README.md +++ b/examples/cozeloop-ai-node/src/tracer/README.md @@ -17,7 +17,6 @@ loopTracer.initialize({ apiClient: { // baseURL: 'https://api.coze.cn', // token: 'your_api_token', - headers: { 'x-tt-env': 'boe_commercial' }, // TODO: remove }, /** Allow ultra long text report */ // ultraLargeReport: true, diff --git a/examples/cozeloop-ai-node/src/tracer/basic.ts b/examples/cozeloop-ai-node/src/tracer/basic.ts new file mode 100644 index 0000000..97f1096 --- /dev/null +++ b/examples/cozeloop-ai-node/src/tracer/basic.ts @@ -0,0 +1,40 @@ +import { cozeLoopTracer } from '@cozeloop/ai'; + +import { doSomething } from './utils'; + +export async function runCustom() { + // Wrap any function to make it traceable + await cozeLoopTracer.traceable( + async parentSpan => { + // Manually set input + cozeLoopTracer.setInput(parentSpan, 'xxx'); + + // Invoke any function, if it throws error, error will be caught and automatically set span as error + const result = await doSomething(); + + // Or, you can manually set error + cozeLoopTracer.setError(parentSpan, 'custom error message'); + + // You can also trace nested span, the parent-child relationship of span will be automatically concatenated + await cozeLoopTracer.traceable( + async childSpan => { + // Set custom tags + childSpan.setAttribute('custom-tag', 'xxx'); + + await doSomething(); + }, + { + name: 'TestCustomChildSpan', + type: 'MyCustomType', + }, + ); + + // Automatically set return value as output + return result; + }, + { + name: 'TestCustomParentSpan', + type: 'MyCustomType', + }, + ); +} diff --git a/examples/cozeloop-ai-node/src/tracer/index.ts b/examples/cozeloop-ai-node/src/tracer/index.ts index 2e5fb47..97e172b 100644 --- a/examples/cozeloop-ai-node/src/tracer/index.ts +++ b/examples/cozeloop-ai-node/src/tracer/index.ts @@ -1,8 +1,10 @@ import { cozeLoopTracer } from '@cozeloop/ai'; -import { runModel, runRoot, runCustom } from './simple'; +import { runRoot } from './root'; import { runMultiModality } from './multi-modality'; +import { runModel } from './llm'; import { runLargeText } from './large-text'; +import { runCustom } from './basic'; // initialize tracer globally cozeLoopTracer.initialize({ @@ -11,7 +13,6 @@ cozeLoopTracer.initialize({ apiClient: { // baseURL: 'https://api.coze.cn', // token: 'your_api_token', - headers: { 'x-tt-env': 'boe_commercial' }, // TODO: remove }, /** Allow ultra long text report */ ultraLargeReport: true, diff --git a/examples/cozeloop-ai-node/src/tracer/large-text.ts b/examples/cozeloop-ai-node/src/tracer/large-text.ts index 89e92db..40e2513 100644 --- a/examples/cozeloop-ai-node/src/tracer/large-text.ts +++ b/examples/cozeloop-ai-node/src/tracer/large-text.ts @@ -21,7 +21,7 @@ export async function runLargeText() { await cozeLoopTracer.traceable( async span => { // Reporting of ultra-long texts will only take effect when the - // input satisfies the LoopTraceLLMCallInput structure + // input / output satisfies the LoopTraceLLMCallInput / LoopTraceLLMCallOutput structure const input: LoopTraceLLMCallInput = { messages: [ { diff --git a/examples/cozeloop-ai-node/src/tracer/simple.ts b/examples/cozeloop-ai-node/src/tracer/llm.ts similarity index 54% rename from examples/cozeloop-ai-node/src/tracer/simple.ts rename to examples/cozeloop-ai-node/src/tracer/llm.ts index 5121ef4..e444146 100644 --- a/examples/cozeloop-ai-node/src/tracer/simple.ts +++ b/examples/cozeloop-ai-node/src/tracer/llm.ts @@ -1,85 +1,11 @@ -import { setTimeout } from 'node:timers/promises'; - +import { SpanKind } from '@cozeloop/ai'; import { COZELOOP_TRACE_BUSINESS_TAGS, cozeLoopTracer, type LoopTraceLLMCallInput, - type LoopTraceLLMCallOutput, - SpanKind, } from '@cozeloop/ai'; -async function doSomething() { - await setTimeout(2000, 'result'); -} - -async function fakeLLMCall(): Promise { - return await setTimeout(2000, { - choices: [ - { - index: 0, - finish_reason: 'stop', - message: { - role: 'assistant', - content: "hi, I'm xx model", - }, - }, - ], - }); -} - -export async function runRoot() { - // We recommend concatenating a complete user request into a trace, - // so the recommended approach is to report a root span at the entrance of the entire execution - await cozeLoopTracer.traceable( - async () => { - // execute your method - const result = await doSomething(); - - return result; - }, - { - name: 'TestRootSpan', - type: 'RootSpanType', - }, - ); -} - -export async function runCustom() { - // Wrap any function to make it traceable - await cozeLoopTracer.traceable( - async parentSpan => { - // Manually set input - cozeLoopTracer.setInput(parentSpan, 'xxx'); - - // Invoke any function, if it throws error, error will be caught and automatically set span as error - const result = await doSomething(); - - // Or, you can manually set error - cozeLoopTracer.setError(parentSpan, 'custom error message'); - - // You can also trace nested span, the parent-child relationship of span will be automatically concatenated - await cozeLoopTracer.traceable( - async childSpan => { - // Set custom tags - childSpan.setAttribute('custom-tag', 'xxx'); - - await doSomething(); - }, - { - name: 'TestCustomChildSpan', - type: 'MyCustomType', - }, - ); - - // Automatically set return value as output - return result; - }, - { - name: 'TestCustomParentSpan', - type: 'MyCustomType', - }, - ); -} +import { fakeLLMCall } from './utils'; export async function runModel() { // Wrap model invoke function to make it traceable diff --git a/examples/cozeloop-ai-node/src/tracer/multi-modality.ts b/examples/cozeloop-ai-node/src/tracer/multi-modality.ts index 8100c25..94d5c7c 100644 --- a/examples/cozeloop-ai-node/src/tracer/multi-modality.ts +++ b/examples/cozeloop-ai-node/src/tracer/multi-modality.ts @@ -14,7 +14,7 @@ export async function runMultiModality() { await cozeLoopTracer.traceable( async span => { // Reporting of multi modality will only take effect when the - // input satisfies the LoopTraceLLMCallInput structure + // input / output satisfies the LoopTraceLLMCallInput / LoopTraceLLMCallOutput structure const input: LoopTraceLLMCallInput = { messages: [ { diff --git a/examples/cozeloop-ai-node/src/tracer/root.ts b/examples/cozeloop-ai-node/src/tracer/root.ts new file mode 100644 index 0000000..3927ebe --- /dev/null +++ b/examples/cozeloop-ai-node/src/tracer/root.ts @@ -0,0 +1,20 @@ +import { cozeLoopTracer } from '@cozeloop/ai'; + +import { doSomething } from './utils'; + +export async function runRoot() { + // We recommend concatenating a complete user request into a trace, + // so the recommended approach is to report a root span at the entrance of the entire execution + await cozeLoopTracer.traceable( + async () => { + // execute your method + const result = await doSomething(); + + return result; + }, + { + name: 'TestRootSpan', + type: 'RootSpanType', + }, + ); +} diff --git a/examples/cozeloop-ai-node/src/tracer/utils.ts b/examples/cozeloop-ai-node/src/tracer/utils.ts new file mode 100644 index 0000000..5725c3a --- /dev/null +++ b/examples/cozeloop-ai-node/src/tracer/utils.ts @@ -0,0 +1,22 @@ +import { setTimeout } from 'node:timers/promises'; + +import { type LoopTraceLLMCallOutput } from '@cozeloop/ai'; + +export async function doSomething() { + await setTimeout(2000, 'result'); +} + +export async function fakeLLMCall(): Promise { + return await setTimeout(2000, { + choices: [ + { + index: 0, + finish_reason: 'stop', + message: { + role: 'assistant', + content: "hi, I'm xx model", + }, + }, + ], + }); +} diff --git a/packages/cozeloop-ai/__tests__/tracer/traceable.test.ts b/packages/cozeloop-ai/__tests__/tracer/traceable.test.ts index e6565a9..e165cd6 100644 --- a/packages/cozeloop-ai/__tests__/tracer/traceable.test.ts +++ b/packages/cozeloop-ai/__tests__/tracer/traceable.test.ts @@ -15,11 +15,6 @@ config(); cozeLoopTracer.initialize({ apiClient: { baseURL: 'https://api.coze.cn', - token: process.env.COZELOOP_API_TOKEN || '', - headers: { - // TODO remove - 'x-tt-env': 'boe_commercial', - }, logger: simpleConsoleLogger, }, workspaceId: '7480474966061006892', From 34961bcb9f8845c633e07d90fdc5c99f1e92302a Mon Sep 17 00:00:00 2001 From: "lukexian.bryce" Date: Mon, 7 Apr 2025 21:36:01 +0800 Subject: [PATCH 2/3] feat(@cozeloop/ai): support reporting the baggage field --- .../cozeloop-ai/src/tracer/constants/index.ts | 21 ++++- .../src/tracer/exporter/loop/index.ts | 85 +++++++++++++++++-- packages/cozeloop-ai/src/tracer/initialize.ts | 17 +++- .../src/tracer/types/initialize.ts | 2 +- .../cozeloop-ai/src/tracer/types/wrapper.ts | 17 ++++ packages/cozeloop-ai/src/tracer/wrapper.ts | 33 ++++++- 6 files changed, 159 insertions(+), 16 deletions(-) diff --git a/packages/cozeloop-ai/src/tracer/constants/index.ts b/packages/cozeloop-ai/src/tracer/constants/index.ts index 39978bd..e6b8110 100644 --- a/packages/cozeloop-ai/src/tracer/constants/index.ts +++ b/packages/cozeloop-ai/src/tracer/constants/index.ts @@ -1,9 +1,22 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates + +import { createContextKey } from '@opentelemetry/api'; + // SPDX-License-Identifier: MIT export const ROOT_SPAN_PARENT_ID = '0'; export const COZELOOP_LOGGER_TRACER_TAG = 'Tracer'; +export const COZELOOP_TRACE_SPAN_USER_ID_KEY = createContextKey( + 'cozeloop.trace.span.user_id', +); +export const COZELOOP_TRACE_SPAN_MESSAGE_ID_KEY = createContextKey( + 'cozeloop.trace.span.message_id', +); +export const COZELOOP_TRACE_SPAN_THREAD_ID_KEY = createContextKey( + 'cozeloop.trace.span.thread_id', +); + export enum COZELOOP_TRACE_IDENTIFIER { LOOP = 'cozeloop-js', } @@ -23,9 +36,6 @@ export enum COZELOOP_TRACE_BASIC_TAGS { SPAN_ULTRA_LARGE_REPORT = 'cozeloop_ultra_large_report', // Reserved tags - SPAN_USER_ID = 'cozeloop_user_id', - SPAN_MESSAGE_ID = 'cozeloop_message_id', - SPAN_THREAD_ID = 'cozeloop_thread_id', SPAN_LOG_ID = 'cozeloop_span_log_id', SPAN_PSM = 'cozeloop_psm', SPAN_METHOD = 'cozeloop_method', @@ -33,6 +43,11 @@ export enum COZELOOP_TRACE_BASIC_TAGS { } export enum COZELOOP_TRACE_BUSINESS_TAGS { + // Common tags + USER_ID = 'user_id', + MESSAGE_ID = 'message_id', + THREAD_ID = 'thread_id', + // Tags for Model span /** The timestamp of the model's first response when using stream response. The unit is microseconds. */ START_TIME_FIRST_RESP = 'start_time_first_resp', diff --git a/packages/cozeloop-ai/src/tracer/exporter/loop/index.ts b/packages/cozeloop-ai/src/tracer/exporter/loop/index.ts index c0e20f0..0ff15db 100644 --- a/packages/cozeloop-ai/src/tracer/exporter/loop/index.ts +++ b/packages/cozeloop-ai/src/tracer/exporter/loop/index.ts @@ -1,13 +1,20 @@ // Copyright (c) 2025 Bytedance Ltd. and/or its affiliates // SPDX-License-Identifier: MIT import { + type SpanProcessor, type ReadableSpan, type SpanExporter, } from '@opentelemetry/sdk-trace-node'; +import { context, type Span, trace } from '@opentelemetry/api'; +import { type BaggageAttributes } from '../../types/wrapper'; import { COZELOOP_LOGGER_TRACER_TAG, + COZELOOP_TRACE_BUSINESS_TAGS, COZELOOP_TRACE_IDENTIFIER, + COZELOOP_TRACE_SPAN_MESSAGE_ID_KEY, + COZELOOP_TRACE_SPAN_THREAD_ID_KEY, + COZELOOP_TRACE_SPAN_USER_ID_KEY, } from '../../constants'; import { CozeLoopTraceClient } from '../../client'; import { @@ -38,6 +45,12 @@ export class CozeLoopTraceExporter { protected _workspaceId: string; protected _loopTraceClient: CozeLoopTraceClient; + protected _activeSpanMap: Map< + string, + { + baggageAttributes?: BaggageAttributes; + } + >; constructor(options: LoopTraceExporterOptions) { const { workspaceId, apiClient, logger } = options; @@ -48,18 +61,78 @@ export class CozeLoopTraceExporter workspaceId: this._workspaceId, logger, }); + this._activeSpanMap = new Map(); + } + + private _onStart( + span: Span, + parentSpan?: ReadableSpan, + baggageAttributes?: BaggageAttributes, + ) { + const { spanId } = span.spanContext(); + const parentSpanId = parentSpan?.spanContext().spanId; + const { baggageAttributes: parentBaggageAttributes } = + this._activeSpanMap.get(parentSpanId ?? '') || {}; + + const mergedBaggageAttributes: BaggageAttributes = { + ...baggageAttributes, + ...parentBaggageAttributes, + }; + + this._activeSpanMap.set(spanId, { + baggageAttributes: mergedBaggageAttributes, + }); + + const { userId, messageId, threadId } = mergedBaggageAttributes; + + span.setAttributes({ + [COZELOOP_TRACE_BUSINESS_TAGS.USER_ID]: userId, + [COZELOOP_TRACE_BUSINESS_TAGS.MESSAGE_ID]: messageId, + [COZELOOP_TRACE_BUSINESS_TAGS.THREAD_ID]: threadId, + }); + } + + handleSpanStart(spanProcessor: SpanProcessor) { + spanProcessor.onStart = (span, parentContext) => { + const customUserId = context + .active() + .getValue(COZELOOP_TRACE_SPAN_USER_ID_KEY) as string | undefined; + const customMessageId = context + .active() + .getValue(COZELOOP_TRACE_SPAN_MESSAGE_ID_KEY) as string | undefined; + const customThreadId = context + .active() + .getValue(COZELOOP_TRACE_SPAN_THREAD_ID_KEY) as string | undefined; + + const parentSpan = trace.getSpan(parentContext) as + | ReadableSpan + | undefined; + + const baggageAttributes: BaggageAttributes = { + userId: customUserId, + messageId: customMessageId, + threadId: customThreadId, + }; + + this._onStart(span, parentSpan, baggageAttributes); + }; } export(spans: ReadableSpan[]): void { - this._loopTraceClient.endSpans( - spans.filter( - span => - span.instrumentationLibrary.name === COZELOOP_TRACE_IDENTIFIER.LOOP, - ), - ); + const cozeLoopSpans = spans.filter(span => { + const { spanId } = span.spanContext(); + this._activeSpanMap.delete(spanId); + return ( + span.instrumentationLibrary.name === COZELOOP_TRACE_IDENTIFIER.LOOP + ); + }); + + this._loopTraceClient.endSpans(cozeLoopSpans); } async shutdown(): Promise { + this._activeSpanMap.clear(); + await this.loopLogger.warn('Shutdown CozeLoopTraceExporter'); } diff --git a/packages/cozeloop-ai/src/tracer/initialize.ts b/packages/cozeloop-ai/src/tracer/initialize.ts index 0f5927d..ac83023 100644 --- a/packages/cozeloop-ai/src/tracer/initialize.ts +++ b/packages/cozeloop-ai/src/tracer/initialize.ts @@ -68,11 +68,24 @@ export const tracerInitModule = (function () { instrumentations, } = options; - const traceExporter = - exporter ?? new CozeLoopTraceExporter({ apiClient, workspaceId }); + let cozeloopTraceExporter: CozeLoopTraceExporter | undefined; + let traceExporter: SpanExporter; + + if (exporter) { + traceExporter = exporter; + } else { + cozeloopTraceExporter = new CozeLoopTraceExporter({ + apiClient, + workspaceId, + }); + traceExporter = cozeloopTraceExporter; + } _spanProcessor = instantiateProcessor(processor, traceExporter); + cozeloopTraceExporter && + cozeloopTraceExporter.handleSpanStart(_spanProcessor); + const spanProcessors: SpanProcessor[] = [_spanProcessor]; if (extraProcessors?.length) { diff --git a/packages/cozeloop-ai/src/tracer/types/initialize.ts b/packages/cozeloop-ai/src/tracer/types/initialize.ts index 7a39883..453f856 100644 --- a/packages/cozeloop-ai/src/tracer/types/initialize.ts +++ b/packages/cozeloop-ai/src/tracer/types/initialize.ts @@ -18,7 +18,7 @@ export interface LoopTraceInitializeOptions { */ apiClient: LoopApiClient; /** - * CozeLoop workspace ID + * CozeLoop workspace ID, use process.env.COZELOOP_WORKSPACE_ID when unprovided */ workspaceId?: string; /** diff --git a/packages/cozeloop-ai/src/tracer/types/wrapper.ts b/packages/cozeloop-ai/src/tracer/types/wrapper.ts index 57ebd90..e908ce4 100644 --- a/packages/cozeloop-ai/src/tracer/types/wrapper.ts +++ b/packages/cozeloop-ai/src/tracer/types/wrapper.ts @@ -13,6 +13,18 @@ export interface LoopTraceWrapperOptions { * The type of the span */ type: SpanType; + /** + * Business custom user id, after setting up, the child span will automatically inherit this attribute + */ + userId?: string; + /** + * Business custom message id, after setting up, the child span will automatically inherit this attribute + */ + messageId?: string; + /** + * Business custom thread id, after setting up, the child span will automatically inherit this attribute + */ + threadId?: string; /** * Any tag that needs to be reported */ @@ -42,3 +54,8 @@ export interface LoopTraceWrapperOptions { */ endWhenDone?: boolean; } + +export type BaggageAttributes = Pick< + LoopTraceWrapperOptions, + 'userId' | 'messageId' | 'threadId' +>; diff --git a/packages/cozeloop-ai/src/tracer/wrapper.ts b/packages/cozeloop-ai/src/tracer/wrapper.ts index ab80db5..14be919 100644 --- a/packages/cozeloop-ai/src/tracer/wrapper.ts +++ b/packages/cozeloop-ai/src/tracer/wrapper.ts @@ -7,7 +7,13 @@ import { type Span, context } from '@opentelemetry/api'; import { setError } from './utils/tags'; import { getTracer, serializeTagValue } from './utils'; import { type LoopTraceWrapperOptions } from './types'; -import { COZELOOP_TRACE_OPTIONS, COZELOOP_TRACE_BASIC_TAGS } from './constants'; +import { + COZELOOP_TRACE_OPTIONS, + COZELOOP_TRACE_BASIC_TAGS, + COZELOOP_TRACE_SPAN_USER_ID_KEY, + COZELOOP_TRACE_SPAN_MESSAGE_ID_KEY, + COZELOOP_TRACE_SPAN_THREAD_ID_KEY, +} from './constants'; function isAsyncFunc) => ReturnType>( fn: F, @@ -42,6 +48,9 @@ function traceData) => ReturnType>( const { name, type, + userId, + messageId, + threadId, disableTracing, attributes, ultraLargeReport, @@ -52,9 +61,25 @@ function traceData) => ReturnType>( let activeContext = context.active(); - if (disableTracing) { - activeContext = suppressTracing(context.active()); - } + userId && + (activeContext = activeContext.setValue( + COZELOOP_TRACE_SPAN_USER_ID_KEY, + userId, + )); + + messageId && + (activeContext = activeContext.setValue( + COZELOOP_TRACE_SPAN_MESSAGE_ID_KEY, + messageId, + )); + + threadId && + (activeContext = activeContext.setValue( + COZELOOP_TRACE_SPAN_THREAD_ID_KEY, + threadId, + )); + + disableTracing && (activeContext = suppressTracing(context.active())); return context.with(activeContext, () => getTracer().startActiveSpan( From 9e832194a96eb76f1e649ee422c1279cf501fe39 Mon Sep 17 00:00:00 2001 From: "lukexian.bryce" Date: Mon, 7 Apr 2025 21:43:51 +0800 Subject: [PATCH 3/3] chore(@cozeloop/ai): trace demo --- examples/cozeloop-ai-node/src/tracer/index.ts | 24 +++++++++---------- examples/cozeloop-ai-node/src/tracer/root.ts | 5 ++++ .../__tests__/tracer/traceable.test.ts | 3 +-- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/examples/cozeloop-ai-node/src/tracer/index.ts b/examples/cozeloop-ai-node/src/tracer/index.ts index 97e172b..35201af 100644 --- a/examples/cozeloop-ai-node/src/tracer/index.ts +++ b/examples/cozeloop-ai-node/src/tracer/index.ts @@ -6,19 +6,19 @@ import { runModel } from './llm'; import { runLargeText } from './large-text'; import { runCustom } from './basic'; -// initialize tracer globally -cozeLoopTracer.initialize({ - /** workspace id, use process.env.COZELOOP_WORKSPACE_ID when unprovided */ - // workspaceId: 'your_workspace_id', - apiClient: { - // baseURL: 'https://api.coze.cn', - // token: 'your_api_token', - }, - /** Allow ultra long text report */ - ultraLargeReport: true, -}); - export async function run() { + // initialize tracer globally + cozeLoopTracer.initialize({ + /** workspace id, use process.env.COZELOOP_WORKSPACE_ID when unprovided */ + // workspaceId: 'your_workspace_id', + apiClient: { + // baseURL: 'https://api.coze.cn', + // token: 'your_api_token', + }, + /** Allow ultra long text report */ + ultraLargeReport: true, + }); + await Promise.all([ runRoot(), runCustom(), diff --git a/examples/cozeloop-ai-node/src/tracer/root.ts b/examples/cozeloop-ai-node/src/tracer/root.ts index 3927ebe..dd6dcd5 100644 --- a/examples/cozeloop-ai-node/src/tracer/root.ts +++ b/examples/cozeloop-ai-node/src/tracer/root.ts @@ -15,6 +15,11 @@ export async function runRoot() { { name: 'TestRootSpan', type: 'RootSpanType', + // you can set your own baggage fields (eg. userId), + // these fields will be automatically passed through and set in all sub-spans + userId: 'uid-123', + messageId: 'msg-123', + threadId: 'thread-123', }, ); } diff --git a/packages/cozeloop-ai/__tests__/tracer/traceable.test.ts b/packages/cozeloop-ai/__tests__/tracer/traceable.test.ts index e165cd6..ab31f3f 100644 --- a/packages/cozeloop-ai/__tests__/tracer/traceable.test.ts +++ b/packages/cozeloop-ai/__tests__/tracer/traceable.test.ts @@ -14,10 +14,8 @@ config(); cozeLoopTracer.initialize({ apiClient: { - baseURL: 'https://api.coze.cn', logger: simpleConsoleLogger, }, - workspaceId: '7480474966061006892', ultraLargeReport: true, }); @@ -131,6 +129,7 @@ describe('Test Trace Report', { timeout: 50_000 }, () => { { name: 'TestParent', type: SpanKind.PromptTemplate, + userId: 'test-user-id', attributes: { string_tag: 'string', boolean_tag: true,