weflayr 0.24.0 → 0.26.1

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 (235) hide show
  1. package/README.md +2 -2
  2. package/dist/package.json +51 -0
  3. package/dist/{api → src/api}/generated/facade.gen.d.ts +86 -12
  4. package/dist/{api → src/api}/generated/facade.gen.js +4 -2
  5. package/dist/src/api/generated/index.d.ts +2 -0
  6. package/dist/{api → src/api}/generated/index.js +3 -1
  7. package/dist/{api → src/api}/generated/sdk.gen.d.ts +11 -3
  8. package/dist/{api → src/api}/generated/sdk.gen.js +34 -4
  9. package/{src/api/generated/types.gen.ts → dist/src/api/generated/types.gen.d.ts} +436 -153
  10. package/dist/{api → src/api}/makeEndpoint.js +1 -3
  11. package/dist/src/auto-instrument.d.ts +42 -0
  12. package/dist/src/auto-instrument.js +156 -0
  13. package/dist/src/index.d.ts +9 -0
  14. package/dist/src/index.js +49 -0
  15. package/dist/src/instrumentation/anthropic/get_cache_and_reasoning_telemetry.d.ts +20 -0
  16. package/dist/src/instrumentation/anthropic/get_cache_and_reasoning_telemetry.js +114 -0
  17. package/dist/src/instrumentation/anthropic/get_cache_config_telemetry.d.ts +28 -0
  18. package/dist/src/instrumentation/anthropic/get_cache_config_telemetry.js +92 -0
  19. package/dist/src/instrumentation/anthropic/get_streaming_accumulation_telemetry.d.ts +25 -0
  20. package/dist/src/instrumentation/anthropic/get_streaming_accumulation_telemetry.js +141 -0
  21. package/dist/src/instrumentation/anthropic/get_structured_output_schema_telemetry.d.ts +9 -0
  22. package/dist/src/instrumentation/anthropic/get_structured_output_schema_telemetry.js +17 -0
  23. package/dist/src/instrumentation/anthropic/get_tool_definitions_telemetry.d.ts +15 -0
  24. package/dist/src/instrumentation/anthropic/get_tool_definitions_telemetry.js +50 -0
  25. package/dist/src/instrumentation/anthropic/set_telemetry_attributes.d.ts +15 -0
  26. package/dist/src/instrumentation/anthropic/set_telemetry_attributes.js +39 -0
  27. package/dist/src/instrumentation/bedrock/get_cache_config_telemetry.d.ts +22 -0
  28. package/dist/src/instrumentation/bedrock/get_cache_config_telemetry.js +97 -0
  29. package/dist/src/instrumentation/bedrock/get_cache_telemetry.d.ts +22 -0
  30. package/dist/src/instrumentation/bedrock/get_cache_telemetry.js +102 -0
  31. package/dist/src/instrumentation/bedrock/get_input_message_content_telemetry.d.ts +15 -0
  32. package/dist/src/instrumentation/bedrock/get_input_message_content_telemetry.js +91 -0
  33. package/dist/src/instrumentation/bedrock/get_model_id_telemetry.d.ts +21 -0
  34. package/dist/src/instrumentation/bedrock/get_model_id_telemetry.js +54 -0
  35. package/dist/src/instrumentation/bedrock/get_reasoning_output_telemetry.d.ts +19 -0
  36. package/dist/src/instrumentation/bedrock/get_reasoning_output_telemetry.js +81 -0
  37. package/dist/src/instrumentation/bedrock/get_streaming_output_message_telemetry.d.ts +27 -0
  38. package/dist/src/instrumentation/bedrock/get_streaming_output_message_telemetry.js +126 -0
  39. package/dist/src/instrumentation/bedrock/get_tool_call_output_telemetry.d.ts +17 -0
  40. package/dist/src/instrumentation/bedrock/get_tool_call_output_telemetry.js +85 -0
  41. package/dist/src/instrumentation/bedrock/get_tool_definitions_telemetry.d.ts +15 -0
  42. package/dist/src/instrumentation/bedrock/get_tool_definitions_telemetry.js +68 -0
  43. package/dist/src/instrumentation/bedrock/set_telemetry_attributes.d.ts +18 -0
  44. package/dist/src/instrumentation/bedrock/set_telemetry_attributes.js +47 -0
  45. package/dist/src/instrumentation/cohere/get_chat_telemetry.d.ts +23 -0
  46. package/dist/src/instrumentation/cohere/get_chat_telemetry.js +77 -0
  47. package/dist/src/instrumentation/cohere/get_embeddings_telemetry.d.ts +18 -0
  48. package/dist/src/instrumentation/cohere/get_embeddings_telemetry.js +88 -0
  49. package/dist/src/instrumentation/cohere/get_structured_output_schema_telemetry.d.ts +12 -0
  50. package/dist/src/instrumentation/cohere/get_structured_output_schema_telemetry.js +18 -0
  51. package/dist/src/instrumentation/cohere/get_tool_call_output_telemetry.d.ts +31 -0
  52. package/dist/src/instrumentation/cohere/get_tool_call_output_telemetry.js +106 -0
  53. package/dist/src/instrumentation/cohere/get_tool_definitions_telemetry.d.ts +27 -0
  54. package/dist/src/instrumentation/cohere/get_tool_definitions_telemetry.js +75 -0
  55. package/dist/src/instrumentation/cohere/set_telemetry_attributes.d.ts +17 -0
  56. package/dist/src/instrumentation/cohere/set_telemetry_attributes.js +44 -0
  57. package/dist/src/instrumentation/elevenlabs/full_instrumentation.d.ts +28 -0
  58. package/dist/src/instrumentation/elevenlabs/full_instrumentation.js +209 -0
  59. package/dist/src/instrumentation/google/get_audio_telemetry.d.ts +9 -0
  60. package/dist/src/instrumentation/google/get_audio_telemetry.js +28 -0
  61. package/dist/src/instrumentation/google/get_cache_operations_telemetry.d.ts +23 -0
  62. package/dist/src/instrumentation/google/get_cache_operations_telemetry.js +154 -0
  63. package/dist/src/instrumentation/google/get_cache_telemetry.d.ts +16 -0
  64. package/{src → dist/src}/instrumentation/google/get_cache_telemetry.js +18 -19
  65. package/dist/src/instrumentation/google/get_embeddings_telemetry.d.ts +12 -0
  66. package/dist/src/instrumentation/google/get_embeddings_telemetry.js +85 -0
  67. package/dist/src/instrumentation/google/get_provider_name.d.ts +11 -0
  68. package/{src → dist/src}/instrumentation/google/get_provider_name.js +11 -12
  69. package/{src/instrumentation/google/get_reasoning_telemetry.js → dist/src/instrumentation/google/get_reasoning_telemetry.d.ts} +1 -11
  70. package/dist/src/instrumentation/google/get_reasoning_telemetry.js +21 -0
  71. package/dist/src/instrumentation/google/get_structured_output_schema_telemetry.d.ts +12 -0
  72. package/dist/src/instrumentation/google/get_structured_output_schema_telemetry.js +19 -0
  73. package/dist/src/instrumentation/google/set_telemetry_attributes.d.ts +18 -0
  74. package/dist/src/instrumentation/google/set_telemetry_attributes.js +98 -0
  75. package/dist/src/instrumentation/openai/get_audio_telemetry.d.ts +25 -0
  76. package/dist/src/instrumentation/openai/get_audio_telemetry.js +123 -0
  77. package/dist/src/instrumentation/openai/get_bedrock_mantle_telemetry.d.ts +35 -0
  78. package/dist/src/instrumentation/openai/get_bedrock_mantle_telemetry.js +148 -0
  79. package/dist/src/instrumentation/openai/get_cache_and_reasoning_telemetry.d.ts +27 -0
  80. package/dist/src/instrumentation/openai/get_cache_and_reasoning_telemetry.js +72 -0
  81. package/dist/src/instrumentation/openai/get_cache_config_telemetry.d.ts +28 -0
  82. package/dist/src/instrumentation/openai/get_cache_config_telemetry.js +91 -0
  83. package/dist/src/instrumentation/openai/get_embeddings_telemetry.d.ts +18 -0
  84. package/dist/src/instrumentation/openai/get_embeddings_telemetry.js +86 -0
  85. package/dist/src/instrumentation/openai/get_streaming_usage.d.ts +21 -0
  86. package/dist/src/instrumentation/openai/get_streaming_usage.js +74 -0
  87. package/dist/src/instrumentation/openai/get_structured_output_schema_telemetry.d.ts +12 -0
  88. package/dist/src/instrumentation/openai/get_structured_output_schema_telemetry.js +20 -0
  89. package/dist/src/instrumentation/openai/set_telemetry_attributes.d.ts +17 -0
  90. package/dist/src/instrumentation/openai/set_telemetry_attributes.js +47 -0
  91. package/dist/src/instrumentation/shared/get_structured_output_schema_telemetry.d.ts +35 -0
  92. package/dist/src/instrumentation/shared/get_structured_output_schema_telemetry.js +76 -0
  93. package/dist/src/instrumentation/vercel/full_instrumentation.d.ts +3 -0
  94. package/dist/src/instrumentation/vercel/full_instrumentation.js +54 -0
  95. package/dist/src/instrumentation/vercel/get_cache_creation_telemetry.d.ts +22 -0
  96. package/dist/src/instrumentation/vercel/get_cache_creation_telemetry.js +66 -0
  97. package/dist/src/instrumentation/vercel/get_structured_output_schema_telemetry.d.ts +24 -0
  98. package/dist/src/instrumentation/vercel/get_structured_output_schema_telemetry.js +84 -0
  99. package/dist/src/logger.d.ts +1 -0
  100. package/dist/src/logger.js +6 -0
  101. package/dist/src/otel/exporter.d.ts +19 -0
  102. package/dist/src/otel/exporter.js +94 -0
  103. package/dist/src/otel/propagation.d.ts +46 -0
  104. package/dist/src/otel/propagation.js +110 -0
  105. package/dist/src/otel/span-filter.d.ts +3 -0
  106. package/dist/src/otel/span-filter.js +61 -0
  107. package/dist/src/otel/span-processor.d.ts +55 -0
  108. package/dist/src/otel/span-processor.js +169 -0
  109. package/dist/src/otel/vercel-ai-sdk-span-filter.d.ts +12 -0
  110. package/dist/src/otel/vercel-ai-sdk-span-filter.js +88 -0
  111. package/dist/src/setup.d.ts +50 -0
  112. package/dist/src/setup.js +155 -0
  113. package/package.json +12 -5
  114. package/.prettierignore +0 -2
  115. package/.prettierrc.json +0 -7
  116. package/LICENSE-MIT +0 -21
  117. package/NOTICE +0 -12
  118. package/dist/api/generated/index.d.ts +0 -2
  119. package/dist/api/generated/types.gen.d.ts +0 -1005
  120. package/eslint.config.mjs +0 -36
  121. package/index.d.ts +0 -170
  122. package/openapi-ts.config.mjs +0 -9
  123. package/scripts/generate_facade.mjs +0 -86
  124. package/src/api/caseConversion.ts +0 -58
  125. package/src/api/generated/client/client.gen.ts +0 -277
  126. package/src/api/generated/client/index.ts +0 -27
  127. package/src/api/generated/client/types.gen.ts +0 -218
  128. package/src/api/generated/client/utils.gen.ts +0 -316
  129. package/src/api/generated/client.gen.ts +0 -16
  130. package/src/api/generated/core/auth.gen.ts +0 -48
  131. package/src/api/generated/core/bodySerializer.gen.ts +0 -82
  132. package/src/api/generated/core/params.gen.ts +0 -178
  133. package/src/api/generated/core/pathSerializer.gen.ts +0 -171
  134. package/src/api/generated/core/queryKeySerializer.gen.ts +0 -117
  135. package/src/api/generated/core/serverSentEvents.gen.ts +0 -242
  136. package/src/api/generated/core/types.gen.ts +0 -110
  137. package/src/api/generated/core/utils.gen.ts +0 -140
  138. package/src/api/generated/facade.gen.ts +0 -104
  139. package/src/api/generated/index.ts +0 -4
  140. package/src/api/generated/sdk.gen.ts +0 -175
  141. package/src/api/index.ts +0 -45
  142. package/src/api/makeEndpoint.ts +0 -54
  143. package/src/auto-instrument.js +0 -172
  144. package/src/index.js +0 -19
  145. package/src/instrumentation/anthropic/get_cache_and_reasoning_telemetry.js +0 -118
  146. package/src/instrumentation/anthropic/get_cache_config_telemetry.js +0 -90
  147. package/src/instrumentation/anthropic/get_streaming_stop_reason_telemetry.js +0 -121
  148. package/src/instrumentation/anthropic/get_tool_definitions_telemetry.js +0 -55
  149. package/src/instrumentation/anthropic/set_telemetry_attributes.js +0 -39
  150. package/src/instrumentation/bedrock/get_cache_config_telemetry.js +0 -106
  151. package/src/instrumentation/bedrock/get_cache_telemetry.js +0 -109
  152. package/src/instrumentation/bedrock/get_input_message_content_telemetry.js +0 -94
  153. package/src/instrumentation/bedrock/get_streaming_output_message_telemetry.js +0 -87
  154. package/src/instrumentation/bedrock/set_telemetry_attributes.js +0 -40
  155. package/src/instrumentation/cohere/get_chat_telemetry.js +0 -88
  156. package/src/instrumentation/cohere/get_embeddings_telemetry.js +0 -107
  157. package/src/instrumentation/cohere/set_telemetry_attributes.js +0 -32
  158. package/src/instrumentation/elevenlabs/full_instrumentation.js +0 -236
  159. package/src/instrumentation/google/get_audio_telemetry.js +0 -30
  160. package/src/instrumentation/google/get_cache_operations_telemetry.js +0 -171
  161. package/src/instrumentation/google/get_embeddings_telemetry.js +0 -99
  162. package/src/instrumentation/google/set_telemetry_attributes.js +0 -104
  163. package/src/instrumentation/openai/get_audio_telemetry.js +0 -149
  164. package/src/instrumentation/openai/get_cache_and_reasoning_telemetry.js +0 -71
  165. package/src/instrumentation/openai/get_cache_config_telemetry.js +0 -63
  166. package/src/instrumentation/openai/get_embeddings_telemetry.js +0 -107
  167. package/src/instrumentation/openai/get_streaming_usage.js +0 -81
  168. package/src/instrumentation/openai/set_telemetry_attributes.js +0 -41
  169. package/src/instrumentation/vercel/full_instrumentation.js +0 -52
  170. package/src/instrumentation/vercel/get_cache_creation_telemetry.js +0 -70
  171. package/src/logger.js +0 -8
  172. package/src/otel/exporter.js +0 -108
  173. package/src/otel/propagation.js +0 -146
  174. package/src/otel/span-filter.js +0 -69
  175. package/src/otel/span-processor.js +0 -170
  176. package/src/otel/vercel-ai-sdk-span-filter.js +0 -79
  177. package/src/setup.js +0 -167
  178. package/tests/api/index.test.js +0 -437
  179. package/tests/index.test.js +0 -884
  180. package/tests/instrumentation/anthropic/get_cache_and_reasoning_telemetry.test.js +0 -181
  181. package/tests/instrumentation/anthropic/get_cache_config_telemetry.test.js +0 -92
  182. package/tests/instrumentation/anthropic/get_streaming_stop_reason_telemetry.test.js +0 -117
  183. package/tests/instrumentation/anthropic/get_tool_definitions_telemetry.test.js +0 -97
  184. package/tests/instrumentation/bedrock/get_cache_config_telemetry.test.js +0 -107
  185. package/tests/instrumentation/bedrock/get_cache_telemetry.test.js +0 -118
  186. package/tests/instrumentation/bedrock/get_input_message_content_telemetry.test.js +0 -89
  187. package/tests/instrumentation/bedrock/get_streaming_output_message_telemetry.test.js +0 -87
  188. package/tests/instrumentation/cohere/get_chat_telemetry.test.js +0 -148
  189. package/tests/instrumentation/cohere/get_embeddings_telemetry.test.js +0 -132
  190. package/tests/instrumentation/elevenlabs/full_instrumentation.test.js +0 -258
  191. package/tests/instrumentation/google/get_cache_operations_telemetry.test.js +0 -130
  192. package/tests/instrumentation/google/get_embeddings_telemetry.test.js +0 -128
  193. package/tests/instrumentation/google/get_reasoning_telemetry.test.js +0 -41
  194. package/tests/instrumentation/google/set_telemetry_attributes.test.js +0 -219
  195. package/tests/instrumentation/openai/get_audio_telemetry.test.js +0 -170
  196. package/tests/instrumentation/openai/get_cache_and_reasoning_telemetry.test.js +0 -83
  197. package/tests/instrumentation/openai/get_cache_config_telemetry.test.js +0 -83
  198. package/tests/instrumentation/openai/get_embeddings_telemetry.test.js +0 -145
  199. package/tests/instrumentation/openai/get_streaming_usage.test.js +0 -105
  200. package/tests/instrumentation/vercel/full_instrumentation.test.js +0 -16
  201. package/tests/instrumentation/vercel/get_cache_creation_telemetry.test.js +0 -96
  202. package/tests/otel/vercel-ai-sdk-span-filter.test.js +0 -159
  203. package/tsconfig.json +0 -18
  204. /package/dist/{api → src/api}/caseConversion.d.ts +0 -0
  205. /package/dist/{api → src/api}/caseConversion.js +0 -0
  206. /package/dist/{api → src/api}/generated/client/client.gen.d.ts +0 -0
  207. /package/dist/{api → src/api}/generated/client/client.gen.js +0 -0
  208. /package/dist/{api → src/api}/generated/client/index.d.ts +0 -0
  209. /package/dist/{api → src/api}/generated/client/index.js +0 -0
  210. /package/dist/{api → src/api}/generated/client/types.gen.d.ts +0 -0
  211. /package/dist/{api → src/api}/generated/client/types.gen.js +0 -0
  212. /package/dist/{api → src/api}/generated/client/utils.gen.d.ts +0 -0
  213. /package/dist/{api → src/api}/generated/client/utils.gen.js +0 -0
  214. /package/dist/{api → src/api}/generated/client.gen.d.ts +0 -0
  215. /package/dist/{api → src/api}/generated/client.gen.js +0 -0
  216. /package/dist/{api → src/api}/generated/core/auth.gen.d.ts +0 -0
  217. /package/dist/{api → src/api}/generated/core/auth.gen.js +0 -0
  218. /package/dist/{api → src/api}/generated/core/bodySerializer.gen.d.ts +0 -0
  219. /package/dist/{api → src/api}/generated/core/bodySerializer.gen.js +0 -0
  220. /package/dist/{api → src/api}/generated/core/params.gen.d.ts +0 -0
  221. /package/dist/{api → src/api}/generated/core/params.gen.js +0 -0
  222. /package/dist/{api → src/api}/generated/core/pathSerializer.gen.d.ts +0 -0
  223. /package/dist/{api → src/api}/generated/core/pathSerializer.gen.js +0 -0
  224. /package/dist/{api → src/api}/generated/core/queryKeySerializer.gen.d.ts +0 -0
  225. /package/dist/{api → src/api}/generated/core/queryKeySerializer.gen.js +0 -0
  226. /package/dist/{api → src/api}/generated/core/serverSentEvents.gen.d.ts +0 -0
  227. /package/dist/{api → src/api}/generated/core/serverSentEvents.gen.js +0 -0
  228. /package/dist/{api → src/api}/generated/core/types.gen.d.ts +0 -0
  229. /package/dist/{api → src/api}/generated/core/types.gen.js +0 -0
  230. /package/dist/{api → src/api}/generated/core/utils.gen.d.ts +0 -0
  231. /package/dist/{api → src/api}/generated/core/utils.gen.js +0 -0
  232. /package/dist/{api → src/api}/generated/types.gen.js +0 -0
  233. /package/dist/{api → src/api}/index.d.ts +0 -0
  234. /package/dist/{api → src/api}/index.js +0 -0
  235. /package/dist/{api → src/api}/makeEndpoint.d.ts +0 -0
@@ -1,149 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Hand-written OTel instrumentor for the OpenAI audio endpoints.
5
- *
6
- * The `@traceloop/instrumentation-openai` package wraps OpenAI's chat,
7
- * completions, responses and image endpoints, but not the audio ones, so this
8
- * ships inside weflayr to cover them. It wraps the Text-to-Speech and
9
- * Speech-to-Text entrypoints to emit one `gen_ai.*` span per call, which flows
10
- * through the standard span processor -> exporter with no new transport code. It
11
- * is registered alongside the traceloop instrumentor whenever
12
- * `autoInstrument({ aiSdks: 'openai' })` runs.
13
- *
14
- * The billable unit differs by API, so each span records the one OpenAI bills:
15
- * - Text-to-Speech is billed per input character -> `gen_ai.usage.input_characters`.
16
- * - Speech-to-Text is billed per second of audio -> `gen_ai.usage.input_seconds`.
17
- *
18
- * Both endpoints are request/response (unary): `audio.speech.create` resolves to
19
- * the full audio and `audio.transcriptions.create` to the transcription. The STT
20
- * audio length is only present when the call requests `response_format: 'verbose_json'`.
21
- */
22
-
23
- const { trace, SpanStatusCode } = require('@opentelemetry/api');
24
-
25
- const TRACER_NAME = 'weflayr.instrumentation.openai_audio';
26
- const TTS_OPERATION = 'text_to_speech';
27
- const STT_OPERATION = 'speech_to_text';
28
-
29
- // Return the gen_ai.system for this call, matching how the OpenAI chat
30
- // instrumentor attributes the vendor: Azure clients (reached via the same openai
31
- // SDK) report `azure.ai.openai`, everything else `openai`.
32
- function _detectSystem(instance) {
33
- const baseURL = (instance && instance._client && instance._client.baseURL) || '';
34
- return baseURL.toLowerCase().includes('openai.azure.com') ? 'azure.ai.openai' : 'openai';
35
- }
36
-
37
- function _startSpan(operation, body, system) {
38
- const span = trace.getTracer(TRACER_NAME).startSpan(operation);
39
- span.setAttribute('gen_ai.system', system);
40
- span.setAttribute('gen_ai.operation.name', operation);
41
- // `model` lives on the request body passed to both audio entrypoints.
42
- const model = body && body.model;
43
- if (model) {
44
- span.setAttribute('gen_ai.request.model', model);
45
- }
46
- return span;
47
- }
48
-
49
- function _setInputCharacters(span, body) {
50
- // `input` is the text passed to text_to_speech; the billable unit is its length.
51
- span.setAttribute('gen_ai.usage.input_characters', ((body && body.input) || '').length);
52
- }
53
-
54
- function _setAudioDuration(span, response) {
55
- // `duration` (seconds) is only present on a verbose transcription response;
56
- // it is the billable unit for speech-to-text.
57
- const durationSecs = response && response.duration;
58
- if (durationSecs != null) {
59
- span.setAttribute('gen_ai.usage.input_seconds', durationSecs);
60
- }
61
- }
62
-
63
- function _recordError(span, error) {
64
- span.setStatus({ code: SpanStatusCode.ERROR, message: error?.message ?? String(error) });
65
- span.recordException(error);
66
- }
67
-
68
- // Wrap a request/response entrypoint: the span spans the single call, and any
69
- // response-derived billable unit is read off the result.
70
- function _consumeUnary(span, responsePromise, setResponseAttributes) {
71
- return responsePromise.then(
72
- (response) => {
73
- if (setResponseAttributes) {
74
- setResponseAttributes(span, response);
75
- }
76
- span.end();
77
- return response;
78
- },
79
- (error) => {
80
- _recordError(span, error);
81
- span.end();
82
- throw error;
83
- }
84
- );
85
- }
86
-
87
- class OpenAIAudioInstrumentor {
88
- constructor() {
89
- // [ownerPrototype, methodName, originalFunction] for uninstrument().
90
- this._patched = [];
91
- }
92
-
93
- instrument() {
94
- let Speech;
95
- let Transcriptions;
96
- try {
97
- ({ Speech } = require('openai/resources/audio/speech'));
98
- ({ Transcriptions } = require('openai/resources/audio/transcriptions'));
99
- } catch (err) {
100
- throw new Error(
101
- 'weflayr.autoInstrument(OPENAI): the openai client is not installed. ' +
102
- 'Install it with: npm install openai\n' +
103
- `Underlying error: ${err.message}`
104
- );
105
- }
106
-
107
- // TTS — request body is the 1st arg; billed per character.
108
- this._wrap(Speech.prototype, {
109
- operation: TTS_OPERATION,
110
- setRequestAttributes: _setInputCharacters,
111
- setResponseAttributes: null,
112
- });
113
-
114
- // STT — request body is the 1st arg; billed per second of audio.
115
- this._wrap(Transcriptions.prototype, {
116
- operation: STT_OPERATION,
117
- setRequestAttributes: null,
118
- setResponseAttributes: _setAudioDuration,
119
- });
120
- }
121
-
122
- uninstrument() {
123
- for (const [owner, methodName, original] of this._patched) {
124
- owner[methodName] = original;
125
- }
126
- this._patched = [];
127
- }
128
-
129
- _wrap(owner, { operation, setRequestAttributes, setResponseAttributes }) {
130
- const original = owner.create;
131
-
132
- function wrapper(body, ...rest) {
133
- const span = _startSpan(operation, body, _detectSystem(this));
134
- if (setRequestAttributes) {
135
- setRequestAttributes(span, body);
136
- }
137
- return _consumeUnary(
138
- span,
139
- Promise.resolve(original.call(this, body, ...rest)),
140
- setResponseAttributes
141
- );
142
- }
143
-
144
- owner.create = wrapper;
145
- this._patched.push([owner, 'create', original]);
146
- }
147
- }
148
-
149
- module.exports = { OpenAIAudioInstrumentor };
@@ -1,71 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Cached-prompt token enrichment complement for the non-streamed OpenAI chat path.
5
- *
6
- * `@traceloop/instrumentation-openai` records `gen_ai.usage.{input,output}_tokens`
7
- * for non-streamed calls but never reads `usage.prompt_tokens_details.cached_tokens`,
8
- * so spans for prompt-cache hits carry no cached-token count. The Python
9
- * OpenLLMetry instrumentor sets `gen_ai.usage.cache_read_input_tokens` from that
10
- * field, so this brings the Node SDK to parity.
11
- *
12
- * It wraps the instrumentor instance's `_endSpan({ span, type, result })`, which
13
- * finalizes the span after the response resolves, letting us stamp the
14
- * cached-token count off `result.usage` while the span is still open. OpenAI has
15
- * no separate cache-write count, so only `cache_read_input_tokens` is set.
16
- *
17
- * The same hook surfaces the reasoning-token count: reasoning models report it as
18
- * `usage.completion_tokens_details.reasoning_tokens` (a subset of output_tokens)
19
- * which the Node instrumentor drops, so this stamps the flat `reasoning_tokens`
20
- * attribute (the form the Python instrumentor emits and the normalizer reads).
21
- */
22
-
23
- const CACHE_READ_INPUT_TOKENS_ATTR = 'gen_ai.usage.cache_read_input_tokens';
24
- const REASONING_TOKENS_ATTR = 'gen_ai.usage.reasoning_tokens';
25
-
26
- class OpenAIPromptCachingInstrumentor {
27
- constructor() {
28
- // [instrumentation, methodName, originalFunction] for uninstrument().
29
- this._patched = [];
30
- }
31
-
32
- // No-op (and never throws) if the instrumentor's internals have changed shape —
33
- // the worst case is a missing cached-token count, never a crash.
34
- instrument(instrumentation) {
35
- const original = instrumentation && instrumentation._endSpan;
36
- if (typeof original !== 'function') return;
37
-
38
- instrumentation._endSpan = function endSpanWithCache(args) {
39
- try {
40
- const span = args && args.span;
41
- const usage = args && args.result && args.result.usage;
42
- const recording = span && span.isRecording && span.isRecording();
43
- const cachedTokens =
44
- usage && usage.prompt_tokens_details && usage.prompt_tokens_details.cached_tokens;
45
- if (cachedTokens && recording) {
46
- span.setAttribute(CACHE_READ_INPUT_TOKENS_ATTR, cachedTokens);
47
- }
48
- const reasoningTokens =
49
- usage &&
50
- usage.completion_tokens_details &&
51
- usage.completion_tokens_details.reasoning_tokens;
52
- if (reasoningTokens && recording) {
53
- span.setAttribute(REASONING_TOKENS_ATTR, reasoningTokens);
54
- }
55
- } catch {
56
- // Never break span finalization over an enrichment failure.
57
- }
58
- return original.call(this, args);
59
- };
60
- this._patched.push([instrumentation, '_endSpan', original]);
61
- }
62
-
63
- uninstrument() {
64
- for (const [owner, methodName, original] of this._patched) {
65
- owner[methodName] = original;
66
- }
67
- this._patched = [];
68
- }
69
- }
70
-
71
- module.exports = { OpenAIPromptCachingInstrumentor };
@@ -1,63 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Request-side prompt-caching config capture for OpenAI chat spans.
5
- *
6
- * OpenAI callers influence the (automatic, server-side) prompt cache with
7
- * request parameters the traceloop instrumentor never records:
8
- * `prompt_cache_key` (a client-chosen routing key — requests sharing a key are
9
- * routed to the same cache shard) and the retention tuning —
10
- * `prompt_cache_retention` ("in_memory" / "24h") on older models, replaced by
11
- * `prompt_cache_options: { ttl }` ("30m") on GPT-5.6+.
12
- *
13
- * Wrap `startSpan({ type, params })` (covering the streamed and non-streamed
14
- * paths) to stamp the values as `weflayr.cache.key` / `weflayr.cache.retention`
15
- * (raw retention/ttl string; the normalizer owns the vocabulary).
16
- */
17
-
18
- const CACHE_KEY_ATTR = 'weflayr.cache.key';
19
- const CACHE_RETENTION_ATTR = 'weflayr.cache.retention';
20
-
21
- class OpenAICacheConfigInstrumentor {
22
- constructor() {
23
- // [instrumentation, methodName, originalFunction] for uninstrument().
24
- this._patched = [];
25
- }
26
-
27
- // No-op (and never throws) if the instrumentor's internals have changed shape —
28
- // the worst case is missing cache-config capture, never a crash.
29
- instrument(instrumentation) {
30
- if (!instrumentation) return;
31
- const startSpanOriginal = instrumentation.startSpan;
32
- if (typeof startSpanOriginal !== 'function') return;
33
-
34
- instrumentation.startSpan = function startSpanWithCacheConfig(request) {
35
- const span = startSpanOriginal.call(this, request);
36
- try {
37
- const params = (request && request.params) || {};
38
- if (params.prompt_cache_key) {
39
- span.setAttribute(CACHE_KEY_ATTR, String(params.prompt_cache_key));
40
- }
41
- const retention =
42
- params.prompt_cache_retention ||
43
- (params.prompt_cache_options && params.prompt_cache_options.ttl);
44
- if (retention) {
45
- span.setAttribute(CACHE_RETENTION_ATTR, String(retention));
46
- }
47
- } catch {
48
- // Never break span creation over an enrichment failure.
49
- }
50
- return span;
51
- };
52
- this._patched.push([instrumentation, 'startSpan', startSpanOriginal]);
53
- }
54
-
55
- uninstrument() {
56
- for (const [owner, methodName, original] of this._patched) {
57
- owner[methodName] = original;
58
- }
59
- this._patched = [];
60
- }
61
- }
62
-
63
- module.exports = { OpenAICacheConfigInstrumentor };
@@ -1,107 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Hand-written OTel instrumentor for the OpenAI embeddings endpoint.
5
- *
6
- * `@traceloop/instrumentation-openai` (the package weflayr uses for OpenAI on
7
- * Node) does not wrap the embeddings endpoint, so this ships inside weflayr to
8
- * cover it. The Python SDK gets embeddings for free from OpenLLMetry's
9
- * instrumentor, so there is no Python counterpart to this file — but the span it
10
- * emits is shaped to normalize identically. It is registered alongside the
11
- * traceloop instrumentor whenever `autoInstrument({ aiSdks: 'openai' })` runs.
12
- *
13
- * Embeddings are billed per input token, so the span records the prompt tokens
14
- * read off the response under `gen_ai.usage.input_tokens`; there is no completion.
15
- */
16
-
17
- const { trace, SpanStatusCode } = require('@opentelemetry/api');
18
-
19
- const TRACER_NAME = 'weflayr.instrumentation.openai_embeddings';
20
- const EMBEDDINGS_OPERATION = 'embeddings';
21
-
22
- // Return the gen_ai.system for this call, matching how the OpenAI chat
23
- // instrumentor attributes the vendor: Azure clients (reached via the same openai
24
- // SDK) report `azure.ai.openai`, everything else `openai`.
25
- function _detectSystem(instance) {
26
- const baseURL = (instance && instance._client && instance._client.baseURL) || '';
27
- return baseURL.toLowerCase().includes('openai.azure.com') ? 'azure.ai.openai' : 'openai';
28
- }
29
-
30
- function _recordError(span, error) {
31
- span.setStatus({ code: SpanStatusCode.ERROR, message: error?.message ?? String(error) });
32
- span.recordException(error);
33
- }
34
-
35
- class OpenAIEmbeddingsInstrumentor {
36
- constructor() {
37
- // [ownerPrototype, methodName, originalFunction] for uninstrument().
38
- this._patched = [];
39
- }
40
-
41
- instrument() {
42
- let Embeddings;
43
- try {
44
- ({ Embeddings } = require('openai/resources/embeddings'));
45
- } catch (err) {
46
- throw new Error(
47
- 'weflayr.autoInstrument(OPENAI): the openai client is not installed. ' +
48
- 'Install it with: npm install openai\n' +
49
- `Underlying error: ${err.message}`
50
- );
51
- }
52
-
53
- const owner = Embeddings.prototype;
54
- const original = owner.create;
55
-
56
- function wrapper(body, ...rest) {
57
- const span = trace.getTracer(TRACER_NAME).startSpan(EMBEDDINGS_OPERATION);
58
- span.setAttribute('gen_ai.system', _detectSystem(this));
59
- span.setAttribute('gen_ai.operation.name', EMBEDDINGS_OPERATION);
60
- if (body && body.model) {
61
- span.setAttribute('gen_ai.request.model', body.model);
62
- }
63
- // One user message per input element, matching the shape the chat
64
- // instrumentors emit. The span processor strips it when message-content
65
- // capture is disabled.
66
- if (body && body.input != null) {
67
- const inputs = Array.isArray(body.input) ? body.input : [body.input];
68
- span.setAttribute(
69
- 'gen_ai.input.messages',
70
- JSON.stringify(
71
- inputs.map((content) => ({ role: 'user', parts: [{ type: 'text', content }] }))
72
- )
73
- );
74
- }
75
- return Promise.resolve(original.call(this, body, ...rest)).then(
76
- (response) => {
77
- if (response && response.model) {
78
- span.setAttribute('gen_ai.response.model', response.model);
79
- }
80
- const promptTokens = response && response.usage && response.usage.prompt_tokens;
81
- if (promptTokens != null) {
82
- span.setAttribute('gen_ai.usage.input_tokens', promptTokens);
83
- }
84
- span.end();
85
- return response;
86
- },
87
- (error) => {
88
- _recordError(span, error);
89
- span.end();
90
- throw error;
91
- }
92
- );
93
- }
94
-
95
- owner.create = wrapper;
96
- this._patched.push([owner, 'create', original]);
97
- }
98
-
99
- uninstrument() {
100
- for (const [owner, methodName, original] of this._patched) {
101
- owner[methodName] = original;
102
- }
103
- this._patched = [];
104
- }
105
- }
106
-
107
- module.exports = { OpenAIEmbeddingsInstrumentor };
@@ -1,81 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Streamed token-usage enrichment complement for the OpenAI chat path.
5
- *
6
- * `@traceloop/instrumentation-openai` does not record token usage for streamed
7
- * calls: its stream handler accumulates `choices[].delta` but never reads the
8
- * final usage chunk OpenAI sends when the request sets
9
- * `stream_options: { include_usage: true }`. Non-streaming calls work because
10
- * OpenAI returns `usage` in the response body, which the instrumentor reads
11
- * directly. The Python OpenLLMetry instrumentor reads the streamed usage, so
12
- * this gap is Node-only.
13
- *
14
- * It wraps the instrumentor instance's `_streamingWrapPromise`: that handler
15
- * hands us the span and ends it only after its chunk loop, so when the usage
16
- * chunk arrives the span is still open and we set the same `gen_ai.usage.*`
17
- * attributes the instrumentor sets for non-streaming calls.
18
- */
19
-
20
- const USAGE_INPUT_TOKENS_ATTR = 'gen_ai.usage.input_tokens';
21
- const USAGE_OUTPUT_TOKENS_ATTR = 'gen_ai.usage.output_tokens';
22
- const USAGE_TOTAL_TOKENS_ATTR = 'gen_ai.usage.total_tokens';
23
- const CACHE_READ_INPUT_TOKENS_ATTR = 'gen_ai.usage.cache_read_input_tokens';
24
-
25
- function _setUsageAttributes(span, usage) {
26
- if (typeof usage.prompt_tokens === 'number') {
27
- span.setAttribute(USAGE_INPUT_TOKENS_ATTR, usage.prompt_tokens);
28
- }
29
- if (typeof usage.completion_tokens === 'number') {
30
- span.setAttribute(USAGE_OUTPUT_TOKENS_ATTR, usage.completion_tokens);
31
- }
32
- if (typeof usage.total_tokens === 'number') {
33
- span.setAttribute(USAGE_TOTAL_TOKENS_ATTR, usage.total_tokens);
34
- }
35
- // Cached-prompt tokens ride in the same streamed usage chunk; mirror the
36
- // non-streamed cache backfill in get_cache_and_reasoning_telemetry.js.
37
- const cachedTokens = usage.prompt_tokens_details && usage.prompt_tokens_details.cached_tokens;
38
- if (cachedTokens) {
39
- span.setAttribute(CACHE_READ_INPUT_TOKENS_ATTR, cachedTokens);
40
- }
41
- }
42
-
43
- class OpenAIStreamingUsageInstrumentor {
44
- constructor() {
45
- // [instrumentation, methodName, originalFunction] for uninstrument().
46
- this._patched = [];
47
- }
48
-
49
- // No-op if the instrumentor's internals have changed shape — the worst case is
50
- // streamed spans without token counts, never a crash.
51
- instrument(instrumentation) {
52
- const original = instrumentation && instrumentation._streamingWrapPromise;
53
- if (typeof original !== 'function') return;
54
-
55
- instrumentation._streamingWrapPromise = function streamingWrapWithUsage(streamArgs) {
56
- const span = streamArgs && streamArgs.span;
57
- const wrappedStream = original.call(this, streamArgs);
58
- if (!span) return wrappedStream;
59
-
60
- return (async function* backfillUsage() {
61
- for await (const chunk of wrappedStream) {
62
- const usage = chunk && chunk.usage;
63
- if (usage && span.isRecording()) {
64
- _setUsageAttributes(span, usage);
65
- }
66
- yield chunk;
67
- }
68
- })();
69
- };
70
- this._patched.push([instrumentation, '_streamingWrapPromise', original]);
71
- }
72
-
73
- uninstrument() {
74
- for (const [owner, methodName, original] of this._patched) {
75
- owner[methodName] = original;
76
- }
77
- this._patched = [];
78
- }
79
- }
80
-
81
- module.exports = { OpenAIStreamingUsageInstrumentor };
@@ -1,41 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * OpenAI telemetry complement — the registered orchestrator.
5
- *
6
- * Wires every weflayr-supplied patch the traceloop OpenAI instrumentor misses:
7
- * - the audio (TTS/STT) and embeddings endpoints it doesn't cover, and
8
- * - usage it drops on the chat endpoint it does cover: streamed token usage and
9
- * non-streamed cached-prompt tokens (these enrich the traceloop instrumentor
10
- * instance, hence the `instrumentation` argument).
11
- */
12
-
13
- const { OpenAIAudioInstrumentor } = require('./get_audio_telemetry');
14
- const { OpenAICacheConfigInstrumentor } = require('./get_cache_config_telemetry');
15
- const { OpenAIEmbeddingsInstrumentor } = require('./get_embeddings_telemetry');
16
- const { OpenAIStreamingUsageInstrumentor } = require('./get_streaming_usage');
17
- const { OpenAIPromptCachingInstrumentor } = require('./get_cache_and_reasoning_telemetry');
18
-
19
- class OpenAITelemetryInstrumentor {
20
- constructor() {
21
- this._subInstrumentors = [
22
- new OpenAIAudioInstrumentor(),
23
- new OpenAIEmbeddingsInstrumentor(),
24
- new OpenAIStreamingUsageInstrumentor(),
25
- new OpenAIPromptCachingInstrumentor(),
26
- new OpenAICacheConfigInstrumentor(),
27
- ];
28
- }
29
-
30
- // The endpoint complements ignore `instrumentation`; the streaming/cache ones
31
- // patch its internal handlers.
32
- instrument(instrumentation) {
33
- for (const sub of this._subInstrumentors) sub.instrument(instrumentation);
34
- }
35
-
36
- uninstrument() {
37
- for (const sub of this._subInstrumentors) sub.uninstrument();
38
- }
39
- }
40
-
41
- module.exports = { OpenAITelemetryInstrumentor };
@@ -1,52 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Instrumentor for the Vercel AI SDK (`ai` package, v7+).
5
- *
6
- * The AI SDK ships its own OTel integration in `@ai-sdk/otel`; instrumenting
7
- * is registering it globally so every generateText/streamText/embed call emits
8
- * GenAI semconv spans through the tracer provider weflayr's setup() installed.
9
- * `usage: true` adds the `ai.usage.*` token details (reasoning tokens, uncached
10
- * input) that the semconv attributes do not carry; `providerMetadata: true`
11
- * opts into `ai.response.providerMetadata` on the spans that carry it.
12
- *
13
- * The aggregate spans the integration emits around each model call
14
- * (invoke_agent, agent_step, duplicated embeddings spans) are filtered out
15
- * before export by otel/vercel-ai-sdk-span-filter.js.
16
- */
17
- class VercelAiSdkInstrumentor {
18
- instrument() {
19
- let registerTelemetry;
20
- let OpenTelemetry;
21
- try {
22
- ({ registerTelemetry } = require('ai'));
23
- ({ OpenTelemetry } = require('@ai-sdk/otel'));
24
- } catch (err) {
25
- throw new Error(
26
- 'weflayr.autoInstrument("vercel_ai_gateway"): failed to load "ai" / "@ai-sdk/otel". ' +
27
- `Install them with: npm install ai @ai-sdk/otel\nUnderlying error: ${err.message}`
28
- );
29
- }
30
- // registerTelemetry only exists since v7.
31
- if (typeof registerTelemetry !== 'function') {
32
- throw new Error(
33
- 'weflayr.autoInstrument("vercel_ai_gateway") requires version 7+ of the Vercel AI SDK ' +
34
- '(the "ai" package), which added global telemetry registration. ' +
35
- 'Upgrade with: npm install ai@latest @ai-sdk/otel.\n' +
36
- 'On ai <= 6 telemetry can only be enabled per call: remove "vercel_ai_gateway" from ' +
37
- 'aiSdks (pass an empty list if no other sdks need to be instrumented). Instead, make sure ' +
38
- 'experimental_telemetry: { isEnabled: true } is passed on each generateText/streamText call.'
39
- );
40
- }
41
- const dispatcher = new OpenTelemetry({ usage: true, providerMetadata: true });
42
- // The integration never emits the raw provider usage, the only place the
43
- // written cache tokens per TTL (Anthropic's `cache_creation`) are
44
- // reported; this complement stamps it on the model-call span (see
45
- // get_cache_creation_telemetry).
46
- const { VercelCacheCreationInstrumentor } = require('./get_cache_creation_telemetry');
47
- new VercelCacheCreationInstrumentor().instrument(dispatcher);
48
- registerTelemetry(dispatcher);
49
- }
50
- }
51
-
52
- module.exports = { VercelAiSdkInstrumentor };
@@ -1,70 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * Cache-write capture for Vercel AI SDK (ai >= 7) model-call spans.
5
- *
6
- * Anthropic reports the written cache tokens per TTL in its raw usage
7
- * (`usage.cache_creation`, ephemeral_5m/1h buckets — billed at different
8
- * rates). ai >= 7 carries that verbatim on the model-call telemetry event as
9
- * `event.usage.raw` (a documented field of LanguageModelUsage), but the
10
- * `@ai-sdk/otel` integration never emits it, so the span loses it.
11
- *
12
- * Wrap the telemetry dispatcher's `onLanguageModelCallEnd(event)` (a public
13
- * callback of the telemetry interface) to read `usage.cache_creation` off the
14
- * raw usage and stamp it verbatim as `weflayr.cache.creation` on the
15
- * still-open model-call span (reached through the integration's call state)
16
- * before the original handler ends it; the normalizer owns the mapping to TTL
17
- * tiers.
18
- */
19
-
20
- const CACHE_CREATION_ATTR = 'weflayr.cache.creation';
21
-
22
- // The raw `usage.cache_creation` of a provider usage, or undefined when the
23
- // provider reports none (or reports only zeros — non-caching calls carry no
24
- // attribute).
25
- function cacheCreationFromRawUsage(rawUsage) {
26
- const cacheCreation = rawUsage && rawUsage.cache_creation;
27
- if (!cacheCreation) return undefined;
28
- return Object.values(cacheCreation).some(Boolean) ? cacheCreation : undefined;
29
- }
30
-
31
- class VercelCacheCreationInstrumentor {
32
- constructor() {
33
- // [owner, methodName, originalFunction] for uninstrument().
34
- this._patched = [];
35
- }
36
-
37
- // No-op (and never throws) if the interface is missing — the worst case is
38
- // the cache-write capture staying empty, exactly the pre-complement
39
- // behaviour.
40
- instrument(dispatcher) {
41
- if (!dispatcher || typeof dispatcher.onLanguageModelCallEnd !== 'function') return;
42
- const original = dispatcher.onLanguageModelCallEnd;
43
-
44
- dispatcher.onLanguageModelCallEnd = function onLanguageModelCallEndWithCacheCreation(event) {
45
- try {
46
- const cacheCreation = cacheCreationFromRawUsage(event && event.usage && event.usage.raw);
47
- if (cacheCreation) {
48
- const callState = this.getCallState && this.getCallState(event.callId);
49
- const span = callState && callState.inferenceSpan;
50
- if (span && typeof span.setAttribute === 'function') {
51
- span.setAttribute(CACHE_CREATION_ATTR, JSON.stringify(cacheCreation));
52
- }
53
- }
54
- } catch {
55
- // Never break span finalization over an enrichment failure.
56
- }
57
- return original.call(this, event);
58
- };
59
- this._patched.push([dispatcher, 'onLanguageModelCallEnd', original]);
60
- }
61
-
62
- uninstrument() {
63
- for (const [owner, methodName, original] of this._patched) {
64
- owner[methodName] = original;
65
- }
66
- this._patched = [];
67
- }
68
- }
69
-
70
- module.exports = { VercelCacheCreationInstrumentor, cacheCreationFromRawUsage };
package/src/logger.js DELETED
@@ -1,8 +0,0 @@
1
- 'use strict';
2
-
3
- const { debuglog } = require('node:util');
4
-
5
- // Enable with NODE_DEBUG=weflayr
6
- const debug = debuglog('weflayr');
7
-
8
- module.exports = { debug };