Skip to content

Commit 49e5bb8

Browse files
committed
fix custom
1 parent 34a5be2 commit 49e5bb8

File tree

4 files changed

+50
-26
lines changed

4 files changed

+50
-26
lines changed

packages/sample-app/src/sample_associations.ts

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,35 +32,42 @@ class ChatbotWithAssociations {
3232
console.log(`User ID: ${this.userId}`);
3333
console.log(`Session ID: ${this.sessionId}\n`);
3434

35-
// Set associations at the beginning of the conversation
35+
// Set standard associations at the beginning of the conversation
3636
// These will be automatically attached to all spans within this context
3737
traceloop.Associations.set([
3838
[traceloop.AssociationProperty.CONVERSATION_ID, this.conversationId],
3939
[traceloop.AssociationProperty.USER_ID, this.userId],
4040
[traceloop.AssociationProperty.SESSION_ID, this.sessionId],
4141
]);
4242

43-
// First message
44-
const greeting = await this.sendMessage(
45-
"Hello! What's the weather like today?",
43+
// Use withAssociationProperties to add custom properties
44+
// Custom properties (like chat_subject) will be prefixed with traceloop.association.properties
45+
return traceloop.withAssociationProperties(
46+
{ chat_subject: "general" },
47+
async () => {
48+
// First message
49+
const greeting = await this.sendMessage(
50+
"Hello! What's the weather like today?",
51+
);
52+
console.log(`Bot: ${greeting}\n`);
53+
54+
// Second message in the same conversation
55+
const followup = await this.sendMessage(
56+
"What should I wear for that weather?",
57+
);
58+
console.log(`Bot: ${followup}\n`);
59+
60+
// Third message
61+
const final = await this.sendMessage("Thanks for the advice!");
62+
console.log(`Bot: ${final}\n`);
63+
64+
return {
65+
greeting,
66+
followup,
67+
final,
68+
};
69+
},
4670
);
47-
console.log(`Bot: ${greeting}\n`);
48-
49-
// Second message in the same conversation
50-
const followup = await this.sendMessage(
51-
"What should I wear for that weather?",
52-
);
53-
console.log(`Bot: ${followup}\n`);
54-
55-
// Third message
56-
const final = await this.sendMessage("Thanks for the advice!");
57-
console.log(`Bot: ${final}\n`);
58-
59-
return {
60-
greeting,
61-
followup,
62-
final,
63-
};
6471
}
6572

6673
/**
@@ -138,7 +145,7 @@ async function main() {
138145
console.log("============================================");
139146

140147
try {
141-
// Example 1: Multi-turn chatbot conversation
148+
// Example 1: Multi-turn chatbot conversation with custom properties
142149
const chatbot = new ChatbotWithAssociations(
143150
"conv-abc-123", // conversation_id
144151
"user-alice-456", // user_id
@@ -155,7 +162,7 @@ async function main() {
155162
"Check your Traceloop dashboard to see the associations attached to traces!",
156163
);
157164
console.log(
158-
"You can filter and search by conversation_id, user_id, session_id, or customer_id.",
165+
"You can filter and search by conversation_id, user_id, session_id, customer_id, or custom properties like chat_subject.",
159166
);
160167
} catch (error) {
161168
console.error("Error running demo:", error);

packages/traceloop-sdk/src/lib/tracing/ai-sdk-transformations.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {
33
SpanAttributes,
44
TraceloopSpanKindValues,
55
} from "@traceloop/ai-semantic-conventions";
6+
import { STANDARD_ASSOCIATION_PROPERTIES } from "./associations";
67

78
const AI_GENERATE_TEXT = "ai.generateText";
89
const AI_STREAM_TEXT = "ai.streamText";
@@ -601,8 +602,11 @@ const transformTelemetryMetadata = (
601602
const stringValue = typeof value === "string" ? value : String(value);
602603
metadataAttributes[metadataKey] = stringValue;
603604

604-
// Also set as association property attribute
605-
attributes[metadataKey] = stringValue;
605+
// Standard properties are set directly, custom properties get prefix
606+
const attributeKey = STANDARD_ASSOCIATION_PROPERTIES.has(metadataKey)
607+
? metadataKey
608+
: `${SpanAttributes.TRACELOOP_ASSOCIATION_PROPERTIES}.${metadataKey}`;
609+
attributes[attributeKey] = stringValue;
606610
}
607611
}
608612
}

packages/traceloop-sdk/src/lib/tracing/associations.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ export enum AssociationProperty {
1212
SESSION_ID = "session_id",
1313
}
1414

15+
/**
16+
* Set of standard association property keys (without prefix).
17+
* Use this to check if a property should be set directly or with the TRACELOOP_ASSOCIATION_PROPERTIES prefix.
18+
*/
19+
export const STANDARD_ASSOCIATION_PROPERTIES = new Set<string>(
20+
Object.values(AssociationProperty)
21+
);
22+
1523
/**
1624
* Type alias for a single association
1725
*/

packages/traceloop-sdk/src/lib/tracing/span-processor.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
transformAiSdkSpanNames,
2121
} from "./ai-sdk-transformations";
2222
import { parseKeyPairsIntoRecord } from "./baggage-utils";
23+
import { STANDARD_ASSOCIATION_PROPERTIES } from "./associations";
2324

2425
export const ALL_INSTRUMENTATION_LIBRARIES = "all" as const;
2526
type AllInstrumentationLibraries = typeof ALL_INSTRUMENTATION_LIBRARIES;
@@ -197,7 +198,11 @@ const onSpanStart = (span: Span): void => {
197198
.getValue(ASSOCATION_PROPERTIES_KEY);
198199
if (associationProperties) {
199200
for (const [key, value] of Object.entries(associationProperties)) {
200-
span.setAttribute(key, value);
201+
// Standard properties are set directly, custom properties get prefix
202+
const attributeKey = STANDARD_ASSOCIATION_PROPERTIES.has(key)
203+
? key
204+
: `${SpanAttributes.TRACELOOP_ASSOCIATION_PROPERTIES}.${key}`;
205+
span.setAttribute(attributeKey, value);
201206
}
202207
}
203208

0 commit comments

Comments
 (0)