weflayr 0.21.0 → 0.22.0

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.
Files changed (28) hide show
  1. package/index.d.ts +1 -1
  2. package/package.json +1 -1
  3. package/src/instrumentation/anthropic/get_streaming_stop_reason_telemetry.js +121 -0
  4. package/src/instrumentation/anthropic/get_tool_definitions_telemetry.js +50 -0
  5. package/src/instrumentation/anthropic/set_telemetry_attributes.js +13 -3
  6. package/src/instrumentation/bedrock/get_input_message_content_telemetry.js +94 -0
  7. package/src/instrumentation/bedrock/get_streaming_output_message_telemetry.js +87 -0
  8. package/src/instrumentation/bedrock/set_telemetry_attributes.js +12 -3
  9. package/src/instrumentation/cohere/get_embeddings_telemetry.js +10 -0
  10. package/src/instrumentation/google/get_audio_telemetry.js +1 -2
  11. package/src/instrumentation/google/get_cache_telemetry.js +1 -3
  12. package/src/instrumentation/google/get_embeddings_telemetry.js +22 -1
  13. package/src/instrumentation/openai/get_embeddings_telemetry.js +12 -0
  14. package/src/otel/exporter.js +1 -6
  15. package/src/otel/span-processor.js +30 -1
  16. package/src/setup.js +1 -2
  17. package/tests/index.test.js +102 -0
  18. package/tests/instrumentation/anthropic/get_cache_and_reasoning_telemetry.test.js +33 -0
  19. package/tests/instrumentation/anthropic/get_streaming_stop_reason_telemetry.test.js +117 -0
  20. package/tests/instrumentation/anthropic/get_tool_definitions_telemetry.test.js +82 -0
  21. package/tests/instrumentation/bedrock/get_input_message_content_telemetry.test.js +89 -0
  22. package/tests/instrumentation/bedrock/get_streaming_output_message_telemetry.test.js +87 -0
  23. package/tests/instrumentation/cohere/get_embeddings_telemetry.test.js +3 -0
  24. package/tests/instrumentation/elevenlabs/full_instrumentation.test.js +18 -4
  25. package/tests/instrumentation/google/get_embeddings_telemetry.test.js +3 -0
  26. package/tests/instrumentation/google/set_telemetry_attributes.test.js +33 -1
  27. package/tests/instrumentation/openai/get_embeddings_telemetry.test.js +19 -0
  28. package/tests/instrumentation/openai/get_streaming_usage.test.js +29 -0
@@ -79,12 +79,31 @@ test('embeddings emits genai span with prompt tokens', async () => {
79
79
  assert.equal(span.attributes['gen_ai.request.model'], 'text-embedding-3-small');
80
80
  assert.equal(span.attributes['gen_ai.response.model'], 'text-embedding-3-small');
81
81
  assert.equal(span.attributes['gen_ai.usage.input_tokens'], 8);
82
+ assert.deepEqual(JSON.parse(span.attributes['gen_ai.input.messages']), [
83
+ { role: 'user', parts: [{ type: 'text', content: 'hello' }] },
84
+ ]);
82
85
  assert.equal(span.status.code, SpanStatusCode.UNSET);
83
86
  } finally {
84
87
  teardown();
85
88
  }
86
89
  });
87
90
 
91
+ test('embeddings emits one input message per element of a list input', async () => {
92
+ const teardown = instrumented();
93
+ try {
94
+ const client = new StubEmbeddings();
95
+ await client.create({ input: ['a', 'b'], model: 'text-embedding-3-small' });
96
+
97
+ const [span] = exporter.getFinishedSpans();
98
+ assert.deepEqual(JSON.parse(span.attributes['gen_ai.input.messages']), [
99
+ { role: 'user', parts: [{ type: 'text', content: 'a' }] },
100
+ { role: 'user', parts: [{ type: 'text', content: 'b' }] },
101
+ ]);
102
+ } finally {
103
+ teardown();
104
+ }
105
+ });
106
+
88
107
  test('embeddings records error status on failure', async () => {
89
108
  const teardown = instrumented();
90
109
  try {
@@ -69,6 +69,35 @@ test('backfills cached-prompt tokens from the streamed usage chunk', async () =>
69
69
  assert.equal(span.attrs['gen_ai.usage.cache_read_input_tokens'], 1536);
70
70
  });
71
71
 
72
+ test('re-yields every stream chunk unchanged — no telemetry collision with the payload', async () => {
73
+ const emitted = [
74
+ { choices: [{ delta: { content: 'hel' } }] },
75
+ { choices: [{ delta: { content: 'lo' } }] },
76
+ { usage: { prompt_tokens: 12, completion_tokens: 3, total_tokens: 15 } },
77
+ ];
78
+ const instrumentation = {
79
+ _streamingWrapPromise() {
80
+ return (async function* () {
81
+ for (const chunk of emitted) yield chunk;
82
+ })();
83
+ },
84
+ };
85
+ new OpenAIStreamingUsageInstrumentor().instrument(instrumentation);
86
+
87
+ const span = fakeSpan();
88
+ const collected = [];
89
+ for await (const chunk of instrumentation._streamingWrapPromise({ span })) {
90
+ collected.push(chunk);
91
+ }
92
+
93
+ // Same count, order, and object identity: backfillUsage re-yields each chunk by
94
+ // reference without copying or mutating it.
95
+ assert.equal(collected.length, emitted.length);
96
+ collected.forEach((chunk, index) => assert.equal(chunk, emitted[index]));
97
+ // …while still backfilling usage off the trailing chunk.
98
+ assert.equal(span.attrs['gen_ai.usage.output_tokens'], 3);
99
+ });
100
+
72
101
  test('is a no-op when the instrumentor has no _streamingWrapPromise', () => {
73
102
  const instrumentation = {};
74
103
  new OpenAIStreamingUsageInstrumentor().instrument(instrumentation);