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,108 +0,0 @@
1
- 'use strict';
2
-
3
- const retry = require('async-retry');
4
- const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
5
-
6
- const { debug } = require('../logger');
7
-
8
- // OTLP-spec retryable statuses: rate-limit + transient server errors.
9
- const _RETRYABLE_STATUS = new Set([429, 502, 503, 504]);
10
-
11
- function _isNonRetryable(err) {
12
- // Tells async-retry's `bail` whether to give up: bail on 4xx (other than
13
- // 429); retry on retryable statuses and on transport errors (no status).
14
- const status = err?.exportResult?.error?.code;
15
- return status !== undefined && !_RETRYABLE_STATUS.has(status);
16
- }
17
-
18
- function _formatFailure(result, url) {
19
- const err = result?.error;
20
- const status = err?.code;
21
- const body = typeof err?.data === 'string' ? err.data.slice(0, 200) : undefined;
22
- const message = err?.message || String(err) || 'unknown error';
23
- let hint = '';
24
- if (status === 401 || status === 403) {
25
- hint = ' Check your apiKey / WEFLAYR_API_KEY.';
26
- } else if (status === 404) {
27
- hint = ' Check the baseUrl is correct.';
28
- } else if (!status && /ECONN|ENOTFOUND|timeout/i.test(message)) {
29
- hint = ' The endpoint is unreachable — check baseUrl and network.';
30
- }
31
- return (
32
- `Weflayr: failed to export telemetry to ${url}` +
33
- (status ? ` (HTTP ${status})` : '') +
34
- `: ${message}.${hint}` +
35
- (body ? ` Response: ${body}` : '')
36
- );
37
- }
38
-
39
- // Wrap a callback-style OTel exporter `export(spans, cb)` with retry. Retries
40
- // transport errors + retryable HTTP statuses; bails on other 4xx.
41
- function _exportWithRetry(originalExport, { maxRetries, maxRetryMs }) {
42
- return (spans, resultCallback) => {
43
- retry(
44
- async (bail) => {
45
- const result = await new Promise((resolve) => originalExport(spans, resolve));
46
- if (result?.code === 0) return result;
47
- const err = new Error(result?.error?.message || 'export failed');
48
- err.exportResult = result;
49
- if (_isNonRetryable(err)) {
50
- bail(err);
51
- return;
52
- }
53
- throw err;
54
- },
55
- { retries: maxRetries - 1, minTimeout: 50, maxRetryTime: maxRetryMs, factor: 2 }
56
- )
57
- .then((result) => resultCallback(result))
58
- .catch((err) => resultCallback(err.exportResult || { code: 1, error: err }));
59
- };
60
- }
61
-
62
- function buildExporter({
63
- baseUrl,
64
- apiKey,
65
- timeoutMs = 5000,
66
- warnOnExportError = true,
67
- maxRetries = 2,
68
- maxRetryMs = 1000,
69
- }) {
70
- const url = `${baseUrl.replace(/\/$/, '')}/`;
71
- const exporter = new OTLPTraceExporter({
72
- url,
73
- headers: {
74
- Authorization: `Bearer ${apiKey}`,
75
- },
76
- timeoutMillis: timeoutMs,
77
- });
78
- const originalExport = exporter.export.bind(exporter);
79
- const wrappedExport = _exportWithRetry(originalExport, { maxRetries, maxRetryMs });
80
- exporter.export = (spans, resultCallback) => {
81
- const start = Date.now();
82
- debug('exporter.export: posting count=%d', spans.length);
83
- wrappedExport(spans, (result) => {
84
- const ms = Date.now() - start;
85
- if (result && result.code === 0) {
86
- debug('exporter.export: ok count=%d elapsed_ms=%d', spans.length, ms);
87
- } else {
88
- debug(
89
- 'exporter.export: FAIL count=%d elapsed_ms=%d code=%s error=%s',
90
- spans.length,
91
- ms,
92
- result?.code,
93
- result?.error?.message || result?.error || '(none)'
94
- );
95
- if (warnOnExportError) {
96
- // console.warn writes to stderr synchronously. process.emitWarning
97
- // is queued for the next tick, so a caller doing process.exit() from
98
- // their error handler races past it and the warning is lost.
99
- console.warn(`[weflayr] ${_formatFailure(result, url)}`);
100
- }
101
- }
102
- resultCallback(result);
103
- });
104
- };
105
- return exporter;
106
- }
107
-
108
- module.exports = { buildExporter, _exportWithRetry, _RETRYABLE_STATUS };
@@ -1,146 +0,0 @@
1
- // Copyright 2024 Langfuse GmbH
2
- // Licensed under the MIT License.
3
- // Original source: https://github.com/langfuse/langfuse-js/blob/main/packages/core/src/propagation.ts
4
- //
5
- // Modifications copyright 2026 Weflayr
6
- // This file has been modified from its original form:
7
- // - Translated from TypeScript to JavaScript
8
- // - Replaced Langfuse's fixed schema with Weflayr's structured metadata
9
- // (featureName, customerName, providerNameOverride, extraTags) plus an
10
- // auto-generated per-call uuid
11
- // - Removed asBaggage cross-process propagation (not needed yet)
12
- // - Removed experiment framework keys
13
- // - Structured fields are written under stable `weflayr.*` span attribute
14
- // keys; extraTags entries are written verbatim
15
- //
16
- // See LICENSE-MIT in the package root for the full license text.
17
-
18
- 'use strict';
19
-
20
- const { randomUUID } = require('node:crypto');
21
- const { context: otelContext, trace, createContextKey } = require('@opentelemetry/api');
22
-
23
- const WEFLAYR_METADATA_CONTEXT_KEY = createContextKey('weflayr_metadata');
24
-
25
- const FEATURE_NAME_ATTR = 'weflayr.feature_name';
26
- const CUSTOMER_NAME_ATTR = 'weflayr.customer_name';
27
- const PROVIDER_NAME_ATTR = 'weflayr.provider_name';
28
- const UUID_ATTR = 'weflayr.uuid';
29
- // Prefix for user-supplied `extraTags` so downstream normalizers can pick
30
- // them out without colliding with instrumentor-set `gen_ai.*` attributes.
31
- const EXTRA_TAG_PREFIX = 'weflayr.tag.';
32
-
33
- function getMergedMetadataFromContext(parentContext) {
34
- const ctx = parentContext ?? otelContext.active();
35
- const existing = ctx.getValue(WEFLAYR_METADATA_CONTEXT_KEY);
36
- return existing && typeof existing === 'object' ? { ...existing } : {};
37
- }
38
-
39
- function _buildAttributes({
40
- featureName,
41
- customerName,
42
- providerNameOverride,
43
- extraTags,
44
- spanUuid,
45
- }) {
46
- const attributes = {
47
- [FEATURE_NAME_ATTR]: featureName,
48
- [CUSTOMER_NAME_ATTR]: customerName,
49
- [UUID_ATTR]: spanUuid,
50
- };
51
- for (const [key, value] of Object.entries(extraTags)) {
52
- attributes[`${EXTRA_TAG_PREFIX}${key}`] = value;
53
- }
54
- if (providerNameOverride !== undefined && providerNameOverride !== null) {
55
- attributes[PROVIDER_NAME_ATTR] = providerNameOverride;
56
- }
57
- return attributes;
58
- }
59
-
60
- /**
61
- * Attach Weflayr metadata to every LLM span created inside this scope.
62
- *
63
- * Callable form: `propagateMetadata(options, fn)` runs `fn` immediately.
64
- * Decorator form: `propagateMetadata(options)` returns a wrapper usable as a
65
- * function-decorator (`@propagateMetadata(...)` on class methods) or as a
66
- * plain `wrap(fn)` -> wrappedFn helper. Each invocation of the wrapped
67
- * function mints a fresh `uuid`, matching the callable form's "one uuid per
68
- * propagateMetadata call" contract.
69
- */
70
- function propagateMetadata(options, fn) {
71
- const { featureName, customerId, providerName } = options ?? {};
72
- let { customerName, providerNameOverride } = options ?? {};
73
- if (customerId != null) {
74
- process.emitWarning(
75
- 'propagateMetadata: `customerId` is deprecated, use `customerName`',
76
- 'DeprecationWarning'
77
- );
78
- customerName = customerName ?? customerId;
79
- }
80
- if (providerName != null) {
81
- process.emitWarning(
82
- 'propagateMetadata: `providerName` is deprecated, use `providerNameOverride`',
83
- 'DeprecationWarning'
84
- );
85
- providerNameOverride = providerNameOverride ?? providerName;
86
- }
87
- if (featureName == null || customerName == null) {
88
- throw new Error('propagateMetadata: `featureName` and `customerName` are required');
89
- }
90
- const normalizedOptions = { ...options, customerName, providerNameOverride };
91
-
92
- if (typeof fn === 'function') {
93
- return _runWithMetadata(normalizedOptions, fn);
94
- }
95
-
96
- return function decorator(target, key, descriptor) {
97
- if (descriptor && typeof descriptor.value === 'function') {
98
- const original = descriptor.value;
99
- descriptor.value = function wrapped(...args) {
100
- return _runWithMetadata(normalizedOptions, () => original.apply(this, args));
101
- };
102
- return descriptor;
103
- }
104
- if (typeof target === 'function') {
105
- return function wrapped(...args) {
106
- return _runWithMetadata(normalizedOptions, () => target.apply(this, args));
107
- };
108
- }
109
- return target;
110
- };
111
- }
112
-
113
- function _runWithMetadata(options, fn) {
114
- const { featureName, customerName, providerNameOverride, extraTags } = options;
115
- const attributes = _buildAttributes({
116
- featureName,
117
- customerName,
118
- providerNameOverride,
119
- extraTags: extraTags ?? {},
120
- spanUuid: randomUUID().replace(/-/g, ''),
121
- });
122
-
123
- const parent = otelContext.active();
124
- const merged = { ...getMergedMetadataFromContext(parent), ...attributes };
125
- const newContext = parent.setValue(WEFLAYR_METADATA_CONTEXT_KEY, merged);
126
-
127
- const activeSpan = trace.getActiveSpan();
128
- if (activeSpan && activeSpan.isRecording && activeSpan.isRecording()) {
129
- for (const [k, v] of Object.entries(attributes)) {
130
- activeSpan.setAttribute(k, v);
131
- }
132
- }
133
-
134
- return otelContext.with(newContext, fn);
135
- }
136
-
137
- module.exports = {
138
- propagateMetadata,
139
- getMergedMetadataFromContext,
140
- WEFLAYR_METADATA_CONTEXT_KEY,
141
- FEATURE_NAME_ATTR,
142
- CUSTOMER_NAME_ATTR,
143
- PROVIDER_NAME_ATTR,
144
- UUID_ATTR,
145
- EXTRA_TAG_PREFIX,
146
- };
@@ -1,69 +0,0 @@
1
- // Copyright 2024 Langfuse GmbH
2
- // Licensed under the MIT License.
3
- // Original source: https://github.com/langfuse/langfuse-js/blob/main/packages/otel/src/span-filter.ts
4
- //
5
- // Modifications copyright 2026 Weflayr
6
- // This file has been modified from its original form:
7
- // - Translated from TypeScript to JavaScript
8
- // - Dropped the LANGFUSE_TRACER_NAME special case (we have no SDK-internal tracer)
9
- // - Dropped isLangfuseSpan
10
- // - Export only spans from known LLM instrumentation scopes: general-purpose
11
- // APM SDKs (Sentry, Datadog, ...) also instrument LLM calls with gen_ai.*
12
- // attributes, so the original "any span with gen_ai.* attributes" check
13
- // exported the same call twice
14
- //
15
- // See LICENSE-MIT in the package root for the full license text.
16
-
17
- 'use strict';
18
-
19
- const KNOWN_LLM_INSTRUMENTATION_SCOPE_PREFIXES = [
20
- 'agent_framework',
21
- 'ai',
22
- 'gen_ai',
23
- 'haystack',
24
- 'langsmith',
25
- 'litellm',
26
- 'mistralai_sdk_tracer',
27
- 'openinference',
28
- 'opentelemetry.instrumentation.anthropic',
29
- 'opentelemetry.instrumentation.aws_bedrock',
30
- 'opentelemetry.instrumentation.bedrock',
31
- 'opentelemetry.instrumentation.cohere',
32
- 'opentelemetry.instrumentation.gemini',
33
- 'opentelemetry.instrumentation.google_genai',
34
- 'opentelemetry.instrumentation.google_generativeai',
35
- 'opentelemetry.instrumentation.openai',
36
- 'opentelemetry.instrumentation.openai_v2',
37
- 'opentelemetry.instrumentation.vertex_ai',
38
- 'opentelemetry.instrumentation.vertexai',
39
- 'weflayr.instrumentation',
40
- 'strands-agents',
41
- 'vllm',
42
- '@traceloop/instrumentation-openai',
43
- '@traceloop/instrumentation-anthropic',
44
- '@traceloop/instrumentation-bedrock',
45
- '@traceloop/instrumentation-cohere',
46
- '@traceloop/instrumentation-google-generativeai',
47
- '@traceloop/instrumentation-langchain',
48
- '@traceloop/instrumentation-llamaindex',
49
- '@traceloop/instrumentation-pinecone',
50
- '@traceloop/instrumentation-chromadb',
51
- '@traceloop/instrumentation-qdrant',
52
- '@traceloop/instrumentation-mcp',
53
- ];
54
-
55
- function isKnownLLMInstrumentor(span) {
56
- const scope = span.instrumentationScope.name;
57
- return KNOWN_LLM_INSTRUMENTATION_SCOPE_PREFIXES.some(
58
- (prefix) => scope === prefix || scope.startsWith(`${prefix}.`)
59
- );
60
- }
61
-
62
- function isDefaultExportSpan(span) {
63
- return isKnownLLMInstrumentor(span);
64
- }
65
-
66
- module.exports = {
67
- isKnownLLMInstrumentor,
68
- isDefaultExportSpan,
69
- };
@@ -1,170 +0,0 @@
1
- // Copyright 2024 Langfuse GmbH
2
- // Licensed under the MIT License.
3
- // Original source: https://github.com/langfuse/langfuse-js/blob/main/packages/otel/src/span-processor.ts
4
- //
5
- // Modifications copyright 2026 Weflayr
6
- // This file has been modified from its original form:
7
- // - Translated from TypeScript to JavaScript
8
- // - Removed MediaService integration (no media upload support yet)
9
- // - Removed LangfuseAPIClient / app-root marker logic (not used)
10
- // - Removed Langfuse-specific span attributes (TRACE_INPUT/OUTPUT/METADATA, IS_APP_ROOT, ENVIRONMENT, RELEASE)
11
- // - Mask hook now receives the full flat attribute bag, not a {data} envelope, and runs synchronously
12
- // - default_tags are applied as span attributes in onStart
13
- // - propagated tags come from Weflayr's tag bag (see propagation.js), not Langfuse's typed schema
14
- //
15
- // See LICENSE-MIT in the package root for the full license text.
16
-
17
- 'use strict';
18
-
19
- const { SpanStatusCode } = require('@opentelemetry/api');
20
- const { BatchSpanProcessor, SimpleSpanProcessor } = require('@opentelemetry/sdk-trace-base');
21
- const { EXTRA_TAG_PREFIX, getMergedMetadataFromContext } = require('./propagation');
22
- const { isDefaultExportSpan, isKnownLLMInstrumentor } = require('./span-filter');
23
- const {
24
- VercelAiSdkSpanFilter,
25
- stampVercelGatewayProviderName,
26
- } = require('./vercel-ai-sdk-span-filter');
27
- const { debug } = require('../logger');
28
-
29
- // setup({captureMessageContent: ...}) records the choice in this env var (the
30
- // official OTel GenAI one). Instrumentors gate content on their own knobs
31
- // (openllmetry reads its own config and captures by default), so the processor
32
- // enforces the flag itself: when the env var is "false", message content is
33
- // stripped from every span before export.
34
- const CONTENT_CAPTURE_ENV = 'OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT';
35
-
36
- // The new-semconv JSON message attributes and the legacy indexed
37
- // `gen_ai.prompt.{i}.*` / `gen_ai.completion.{i}.*` attributes.
38
- const CONTENT_ATTRIBUTES = [
39
- 'gen_ai.input.messages',
40
- 'gen_ai.output.messages',
41
- 'gen_ai.system_instructions',
42
- ];
43
- const CONTENT_ATTRIBUTE_PREFIXES = ['gen_ai.prompt.', 'gen_ai.completion.'];
44
-
45
- function _isContentAttribute(key) {
46
- return (
47
- CONTENT_ATTRIBUTES.includes(key) ||
48
- CONTENT_ATTRIBUTE_PREFIXES.some((prefix) => key.startsWith(prefix))
49
- );
50
- }
51
-
52
- // Stamped on every exported span when a `mask` is configured: the mask
53
- // function's source code, so the stored raw event shows what redaction ran
54
- // client-side when debugging missing attributes.
55
- const MASK_FUNCTION_ATTRIBUTE = 'weflayr.mask_function';
56
-
57
- class WeflayrSpanProcessor {
58
- constructor({ exporter, exportMode = 'batch', defaultTags = {}, mask, shouldExportSpan } = {}) {
59
- if (!exporter) {
60
- throw new Error('WeflayrSpanProcessor: exporter is required');
61
- }
62
- this._delegate =
63
- exportMode === 'immediate'
64
- ? new SimpleSpanProcessor(exporter)
65
- : new BatchSpanProcessor(exporter);
66
- this._defaultTags = defaultTags;
67
- this._mask = mask;
68
- this._maskFunctionSource = mask ? String(mask) : null;
69
- this._shouldExportSpan = shouldExportSpan ?? isDefaultExportSpan;
70
- this._vercelAiSdkSpanFilter = new VercelAiSdkSpanFilter();
71
- // LLM spans we've started but not yet seen end. On forceFlush we end any
72
- // leftovers with ERROR status — covers cases like openllmetry's anthropic
73
- // streaming wrapper, which leaks the span when the underlying call
74
- // rejects. Generic across providers; no per-provider patching needed.
75
- this._openLlmSpans = new Set();
76
- }
77
-
78
- onStart(span, parentContext) {
79
- for (const [k, v] of Object.entries(this._defaultTags)) {
80
- span.setAttribute(`${EXTRA_TAG_PREFIX}${k}`, v);
81
- }
82
- const propagated = getMergedMetadataFromContext(parentContext);
83
- for (const [k, v] of Object.entries(propagated)) {
84
- span.setAttribute(k, v);
85
- }
86
- if (isKnownLLMInstrumentor(span)) {
87
- this._openLlmSpans.add(span);
88
- }
89
- this._vercelAiSdkSpanFilter.onStart(span);
90
- debug(
91
- 'span start: name=%s defaultTags=%d propagatedMetadata=%d',
92
- span.name,
93
- Object.keys(this._defaultTags).length,
94
- Object.keys(propagated).length
95
- );
96
- return this._delegate.onStart(span, parentContext);
97
- }
98
-
99
- onEnd(span) {
100
- this._openLlmSpans.delete(span);
101
- try {
102
- const vercelVerdict = this._vercelAiSdkSpanFilter.shouldExport(span);
103
- if (vercelVerdict === true) {
104
- stampVercelGatewayProviderName(span);
105
- }
106
- if (vercelVerdict === false || (vercelVerdict === null && !this._shouldExportSpan(span))) {
107
- debug(
108
- 'span end: filtered out name=%s scope=%s',
109
- span.name,
110
- span.instrumentationScope?.name
111
- );
112
- return;
113
- }
114
- } catch {
115
- return;
116
- }
117
- debug('span end: exporting name=%s scope=%s', span.name, span.instrumentationScope?.name);
118
-
119
- if ((process.env[CONTENT_CAPTURE_ENV] || '').toLowerCase() === 'false') {
120
- for (const key of Object.keys(span.attributes)) {
121
- if (_isContentAttribute(key)) delete span.attributes[key];
122
- }
123
- }
124
-
125
- if (this._mask) {
126
- try {
127
- const masked = this._mask(span.attributes);
128
- if (masked && masked !== span.attributes) {
129
- for (const k of Object.keys(span.attributes)) delete span.attributes[k];
130
- Object.assign(span.attributes, masked);
131
- }
132
- } catch {
133
- for (const k of Object.keys(span.attributes)) delete span.attributes[k];
134
- }
135
- // Stamped after masking so the mask can't strip it.
136
- span.attributes[MASK_FUNCTION_ATTRIBUTE] = this._maskFunctionSource;
137
- }
138
-
139
- return this._delegate.onEnd(span);
140
- }
141
-
142
- async forceFlush() {
143
- this._endOrphanedLlmSpans();
144
- return this._delegate.forceFlush();
145
- }
146
-
147
- _endOrphanedLlmSpans() {
148
- const orphans = [...this._openLlmSpans];
149
- this._openLlmSpans.clear();
150
- for (const span of orphans) {
151
- try {
152
- if (typeof span.isRecording === 'function' && !span.isRecording()) continue;
153
- span.setStatus({
154
- code: SpanStatusCode.ERROR,
155
- message: 'weflayr: span did not complete before flush',
156
- });
157
- span.end();
158
- debug('forceFlush: ended orphaned LLM span name=%s', span.name);
159
- } catch (err) {
160
- debug('forceFlush: failed to end orphan span: %s', err?.message || err);
161
- }
162
- }
163
- }
164
-
165
- shutdown() {
166
- return this._delegate.shutdown();
167
- }
168
- }
169
-
170
- module.exports = { CONTENT_CAPTURE_ENV, WeflayrSpanProcessor };
@@ -1,79 +0,0 @@
1
- 'use strict';
2
-
3
- // The Vercel AI SDK's OTel integrations emit aggregate spans around each model
4
- // call, all repeating the same usage counts:
5
- // - `@ai-sdk/otel` (ai >= 7, scope "gen_ai"): per-call "chat" spans are
6
- // wrapped in "agent_step" + "invoke_agent" spans, and embed/embedMany
7
- // emits an outer "embeddings" operation span around the model-call
8
- // "embeddings" span(s).
9
- // - the legacy integration (ai <= 6, scope "ai"): `ai.<fn>.do<Call>` spans
10
- // are wrapped in an outer `ai.<fn>` span.
11
- // Exactly one span per model call may reach the exporter — exporting an
12
- // aggregate alongside its children would bill every call twice.
13
-
14
- const VERCEL_SEMCONV_SCOPE = 'gen_ai';
15
- const VERCEL_LEGACY_SCOPE = 'ai';
16
-
17
- const LEGACY_MODEL_CALL_SPAN_NAME = /\.do(Generate|Stream|Embed)$/;
18
-
19
- function _parentSpanId(span) {
20
- return span.parentSpanContext?.spanId ?? span.parentSpanId;
21
- }
22
-
23
- class VercelAiSdkSpanFilter {
24
- constructor() {
25
- // spanId -> gen_ai.operation.name for open "gen_ai"-scope spans, so a
26
- // span can check what its parent is (children end before their parent).
27
- this._openSpanOperations = new Map();
28
- }
29
-
30
- onStart(span) {
31
- if (span.instrumentationScope?.name !== VERCEL_SEMCONV_SCOPE) return;
32
- this._openSpanOperations.set(
33
- span.spanContext().spanId,
34
- span.attributes['gen_ai.operation.name']
35
- );
36
- }
37
-
38
- /**
39
- * Export verdict for a Vercel AI SDK span, or null when the span is not
40
- * one (the caller falls back to the default filter).
41
- */
42
- shouldExport(span) {
43
- const scope = span.instrumentationScope?.name;
44
- if (scope === VERCEL_LEGACY_SCOPE) {
45
- return LEGACY_MODEL_CALL_SPAN_NAME.test(span.name);
46
- }
47
- if (scope !== VERCEL_SEMCONV_SCOPE) {
48
- return null;
49
- }
50
- const operation = span.attributes['gen_ai.operation.name'];
51
- this._openSpanOperations.delete(span.spanContext().spanId);
52
- if (operation === 'chat') {
53
- return true;
54
- }
55
- if (operation === 'embeddings') {
56
- // Keep the outer aggregate (one event per embed/embedMany call, with the
57
- // total usage) and drop the nested model-call span(s) repeating it.
58
- return this._openSpanOperations.get(_parentSpanId(span)) !== 'embeddings';
59
- }
60
- // invoke_agent / agent_step (usage aggregates) and execute_tool (no usage).
61
- return false;
62
- }
63
- }
64
-
65
- // `@ai-sdk/otel` reports the Vercel AI Gateway as the bare provider id
66
- // "gateway" — too generic a name to special-case downstream. Stamp the weflayr
67
- // provider override (which the normalizer prefers) with the canonical name.
68
- // A providerNameOverride set through propagateMetadata was stamped at span start and
69
- // wins.
70
- function stampVercelGatewayProviderName(span) {
71
- if (
72
- span.attributes['gen_ai.provider.name'] === 'gateway' &&
73
- span.attributes['weflayr.provider_name'] === undefined
74
- ) {
75
- span.attributes['weflayr.provider_name'] = 'vercel_ai_gateway';
76
- }
77
- }
78
-
79
- module.exports = { VercelAiSdkSpanFilter, stampVercelGatewayProviderName };