@arizeai/phoenix-otel 0.3.0 → 0.3.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.
@@ -1,85 +1,329 @@
1
1
  import { DiagLogLevel } from "@opentelemetry/api";
2
2
  import { Instrumentation } from "@opentelemetry/instrumentation";
3
- import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
3
+ import { NodeTracerProvider, SpanProcessor } from "@opentelemetry/sdk-trace-node";
4
+ /**
5
+ * Type definition for HTTP headers used in OTLP communication
6
+ * @example { "custom-header": "value", "x-api-version": "1.0" }
7
+ */
4
8
  export type Headers = Record<string, string>;
5
9
  /**
6
- * Configuration parameters for registering Phoenix OpenTelemetry tracing
10
+ * Configuration parameters for registering Phoenix OpenTelemetry tracing.
11
+ *
12
+ * This interface defines all the available options for configuring the Phoenix
13
+ * OpenTelemetry integration, including connection details, processing options,
14
+ * and instrumentation settings.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * const config: RegisterParams = {
19
+ * projectName: "my-application",
20
+ * url: "https://app.phoenix.arize.com",
21
+ * apiKey: "your-api-key",
22
+ * batch: true,
23
+ * global: true
24
+ * };
25
+ * ```
7
26
  */
8
27
  export type RegisterParams = {
9
28
  /**
10
- * The project the spans should be associated to
29
+ * The project name that spans will be associated with in Phoenix.
30
+ * This helps organize and filter traces in the Phoenix UI.
31
+ *
11
32
  * @default "default"
33
+ * @example "my-web-app"
34
+ * @example "api-service"
12
35
  */
13
36
  projectName?: string;
14
37
  /**
15
- * The URL to the phoenix server. Can be postfixed with tracing path.
16
- * If not provided, environment variables are checked.
38
+ * The URL to the Phoenix server. Can be postfixed with the tracing path.
39
+ * If not provided, the system will check the PHOENIX_COLLECTOR_URL environment variable.
40
+ *
41
+ * The URL will be automatically normalized to include the `/v1/traces` endpoint if not present.
42
+ *
17
43
  * @example "https://app.phoenix.arize.com"
44
+ * @example "https://app.phoenix.arize.com/v1/traces"
45
+ * @example "http://localhost:6006"
18
46
  */
19
47
  url?: string;
20
48
  /**
21
- * The API key for the phoenix instance.
22
- * If not provided, environment variables are checked.
49
+ * The API key for authenticating with the Phoenix instance.
50
+ * If not provided, the system will check the PHOENIX_API_KEY environment variable.
51
+ *
52
+ * The API key will be automatically added to the Authorization header as a Bearer token.
53
+ *
54
+ * @example "phx_1234567890abcdef"
23
55
  */
24
56
  apiKey?: string;
25
57
  /**
26
- * Headers to be used when communicating with the OTLP collector
58
+ * Additional headers to be included when communicating with the OTLP collector.
59
+ * These headers will be merged with any automatically generated headers (like Authorization).
60
+ *
61
+ * @example { "x-custom-header": "value", "x-api-version": "1.0" }
27
62
  */
28
63
  headers?: Headers;
29
64
  /**
30
65
  * Whether to use batching for span processing.
31
- * It is recommended to use batching in production environments
66
+ *
67
+ * - `true` (default): Uses OpenInferenceBatchSpanProcessor for better performance in production
68
+ * - `false`: Uses OpenInferenceSimpleSpanProcessor for immediate span export (useful for debugging)
69
+ *
70
+ * Batching is recommended for production environments as it reduces network overhead
71
+ * and improves performance by sending multiple spans in a single request.
72
+ *
32
73
  * @default true
33
74
  */
34
75
  batch?: boolean;
35
76
  /**
36
- * A list of instrumentation to register.
37
- * Note: this may only work with commonjs projects. ESM projects will require manually applying instrumentation.
77
+ * A list of OpenTelemetry instrumentations to automatically register.
78
+ *
79
+ * **Note**: This feature may only work with CommonJS projects. ESM projects
80
+ * may require manual instrumentation registration.
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
85
+ * import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
86
+ *
87
+ * const instrumentations = [
88
+ * new HttpInstrumentation(),
89
+ * new ExpressInstrumentation()
90
+ * ];
91
+ * ```
38
92
  */
39
93
  instrumentations?: Instrumentation[];
40
94
  /**
41
- * Whether to set the tracer as a global provider.
95
+ * Custom span processors to add to the tracer provider.
96
+ *
97
+ * **Important**: When provided, this will override the default span processor
98
+ * created from the `url`, `apiKey`, `headers`, and `batch` parameters.
99
+ *
100
+ * @example
101
+ * ```typescript
102
+ * import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
103
+ *
104
+ * const customProcessors = [
105
+ * new BatchSpanProcessor(exporter),
106
+ * new MyCustomSpanProcessor()
107
+ * ];
108
+ * ```
109
+ */
110
+ spanProcessors?: SpanProcessor[];
111
+ /**
112
+ * Whether to register the tracer provider as the global provider.
113
+ *
114
+ * When `true` (default), the provider will be registered globally and can be
115
+ * accessed throughout the application. Set to `false` if you want to manage
116
+ * the provider lifecycle manually or use multiple providers.
117
+ *
42
118
  * @default true
43
119
  */
44
120
  global?: boolean;
45
121
  /**
46
- * The diag log level to set for the built in DiagConsoleLogger instance.
47
- * Omit to disable built in logging.
122
+ * The diagnostic log level for the built-in DiagConsoleLogger.
123
+ *
124
+ * This controls the verbosity of OpenTelemetry's internal logging.
125
+ * Omit this parameter to disable built-in logging entirely.
126
+ *
127
+ * @example DiagLogLevel.INFO
128
+ * @example DiagLogLevel.DEBUG
129
+ * @example DiagLogLevel.ERROR
48
130
  */
49
131
  diagLogLevel?: DiagLogLevel;
50
132
  };
51
133
  /**
52
- * Registers Phoenix OpenTelemetry tracing with the specified configuration
134
+ * Registers Phoenix OpenTelemetry tracing with the specified configuration.
135
+ *
136
+ * This function sets up a complete OpenTelemetry tracing pipeline configured
137
+ * to send traces to a Phoenix instance. It creates a NodeTracerProvider with
138
+ * appropriate span processors, resource attributes, and optional instrumentations.
139
+ *
140
+ * The function handles:
141
+ * - Creating and configuring a NodeTracerProvider
142
+ * - Setting up OTLP trace export to Phoenix
143
+ * - Configuring span processors (batch or simple)
144
+ * - Registering instrumentations (if provided)
145
+ * - Setting up resource attributes for project identification
146
+ * - Optional global provider registration
53
147
  *
54
148
  * @param params - Configuration parameters for Phoenix tracing
55
- * @param params.url - The URL to the phoenix server. Can be postfixed with tracing path
56
- * @param params.apiKey - The API key for the phoenix instance
57
- * @param params.projectName - The project the spans should be associated to
58
- * @param params.instrumentations - A list of instrumentation to register
59
- * @param params.batch - Whether to use batching for span processing
60
- * @param params.global - Whether to set the tracer as a global provider
61
- * @param params.diagLogLevel - the diagnostics log level
62
- * @returns {NodeTracerProvider} The configured NodeTracerProvider instance
149
+ * @returns The configured NodeTracerProvider instance that can be used to create traces
63
150
  *
64
151
  * @example
152
+ * Basic usage with minimal configuration:
65
153
  * ```typescript
66
154
  * import { register } from '@arizeai/phoenix-otel';
67
155
  *
156
+ * // Uses environment variables for URL and API key
157
+ * const provider = register({
158
+ * projectName: 'my-application'
159
+ * });
160
+ * ```
161
+ *
162
+ * @example
163
+ * Full configuration with custom settings:
164
+ * ```typescript
165
+ * import { register } from '@arizeai/phoenix-otel';
166
+ * import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
167
+ * import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
168
+ *
169
+ * const provider = register({
170
+ * projectName: 'my-web-app',
171
+ * url: 'https://app.phoenix.arize.com',
172
+ * apiKey: 'phx_1234567890abcdef',
173
+ * batch: true,
174
+ * global: true,
175
+ * instrumentations: [
176
+ * new HttpInstrumentation(),
177
+ * new ExpressInstrumentation()
178
+ * ],
179
+ * diagLogLevel: DiagLogLevel.INFO
180
+ * });
181
+ * ```
182
+ *
183
+ * @example
184
+ * Custom span processors:
185
+ * ```typescript
186
+ * import { register } from '@arizeai/phoenix-otel';
187
+ * import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
188
+ * import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
189
+ *
190
+ * const exporter = new OTLPTraceExporter({
191
+ * url: 'https://app.phoenix.arize.com/v1/traces',
192
+ * headers: { 'Authorization': 'Bearer your-api-key' }
193
+ * });
194
+ *
68
195
  * const provider = register({
69
196
  * projectName: 'my-app',
197
+ * spanProcessors: [new BatchSpanProcessor(exporter)],
198
+ * global: false // Manual provider management
199
+ * });
200
+ * ```
201
+ *
202
+ * @example
203
+ * Debugging configuration:
204
+ * ```typescript
205
+ * const provider = register({
206
+ * projectName: 'debug-app',
207
+ * url: 'http://localhost:6006',
208
+ * batch: false, // Immediate span export for debugging
209
+ * diagLogLevel: DiagLogLevel.DEBUG
210
+ * });
211
+ * ```
212
+ */
213
+ export declare function register(params: RegisterParams): NodeTracerProvider;
214
+ /**
215
+ * Creates a default span processor configured for Phoenix OpenTelemetry tracing.
216
+ *
217
+ * This function creates an appropriate span processor (batch or simple) based on
218
+ * the provided configuration parameters. It handles URL normalization, header
219
+ * configuration, and API key authentication automatically.
220
+ *
221
+ * The function will:
222
+ * - Normalize the collector URL to include the `/v1/traces` endpoint if needed
223
+ * - Configure authentication headers using the provided API key
224
+ * - Merge any additional custom headers
225
+ * - Create either a batch or simple span processor based on the `batch` parameter
226
+ *
227
+ * @param params - Configuration parameters for the span processor
228
+ * @param params.url - The URL to the Phoenix server (will be normalized to include `/v1/traces`)
229
+ * @param params.apiKey - The API key for authenticating with the Phoenix instance
230
+ * @param params.headers - Additional headers to include in OTLP requests
231
+ * @param params.batch - Whether to use batching for span processing (recommended for production)
232
+ * @returns A configured SpanProcessor instance ready for use with a NodeTracerProvider
233
+ *
234
+ * @example
235
+ * Basic usage with environment variables:
236
+ * ```typescript
237
+ * const processor = getDefaultSpanProcessor({
238
+ * batch: true
239
+ * });
240
+ * ```
241
+ *
242
+ * @example
243
+ * Full configuration with custom settings:
244
+ * ```typescript
245
+ * const processor = getDefaultSpanProcessor({
246
+ * url: 'https://app.phoenix.arize.com',
247
+ * apiKey: 'phx_1234567890abcdef',
248
+ * headers: { 'x-custom-header': 'value' },
249
+ * batch: true
250
+ * });
251
+ * ```
252
+ *
253
+ * @example
254
+ * Debugging configuration with immediate export:
255
+ * ```typescript
256
+ * const processor = getDefaultSpanProcessor({
257
+ * url: 'http://localhost:6006',
258
+ * batch: false // Immediate span export for debugging
259
+ * });
260
+ * ```
261
+ *
262
+ * @example
263
+ * Using with custom headers:
264
+ * ```typescript
265
+ * const processor = getDefaultSpanProcessor({
70
266
  * url: 'https://app.phoenix.arize.com',
71
267
  * apiKey: 'your-api-key',
268
+ * headers: {
269
+ * 'x-api-version': '1.0',
270
+ * 'x-client-name': 'my-app'
271
+ * },
72
272
  * batch: true
73
273
  * });
74
274
  * ```
75
275
  */
76
- export declare function register({ url: paramsUrl, apiKey: paramsApiKey, headers: paramsHeaders, projectName, instrumentations, batch, global, diagLogLevel, }: RegisterParams): NodeTracerProvider;
276
+ export declare function getDefaultSpanProcessor({ url: paramsUrl, apiKey: paramsApiKey, headers: paramsHeaders, batch, }: Pick<RegisterParams, "url" | "apiKey" | "batch" | "headers">): SpanProcessor;
77
277
  /**
78
- * A utility method to normalize the URL to be HTTP compatible.
79
- * Assumes we are using HTTP over gRPC and ensures the URL ends with the correct traces endpoint.
278
+ * Normalizes a Phoenix server URL to ensure it includes the correct OTLP traces endpoint.
279
+ *
280
+ * This utility function ensures that any Phoenix server URL is properly formatted
281
+ * to include the `/v1/traces` endpoint required for OTLP trace export. It handles
282
+ * various URL formats and automatically appends the endpoint if missing.
80
283
  *
81
- * @param url - The URL to the phoenix server. May contain a slug
82
- * @returns {string} The normalized URL with the '/v1/traces' endpoint
284
+ * The function:
285
+ * - Checks if the URL already contains `/v1/traces`
286
+ * - If missing, appends `/v1/traces` to the base URL
287
+ * - Returns a properly formatted URL string
288
+ * - Assumes HTTP over gRPC protocol for OTLP communication
289
+ *
290
+ * @param url - The base URL to the Phoenix server (may or may not include the traces endpoint)
291
+ * @returns A normalized URL string that includes the `/v1/traces` endpoint
292
+ *
293
+ * @example
294
+ * URL without traces endpoint:
295
+ * ```typescript
296
+ * const normalized = ensureCollectorEndpoint('https://app.phoenix.arize.com');
297
+ * // Returns: 'https://app.phoenix.arize.com/v1/traces'
298
+ * ```
299
+ *
300
+ * @example
301
+ * URL that already includes traces endpoint:
302
+ * ```typescript
303
+ * const normalized = ensureCollectorEndpoint('https://app.phoenix.arize.com/v1/traces');
304
+ * // Returns: 'https://app.phoenix.arize.com/v1/traces'
305
+ * ```
306
+ *
307
+ * @example
308
+ * Local development URL:
309
+ * ```typescript
310
+ * const normalized = ensureCollectorEndpoint('http://localhost:6006');
311
+ * // Returns: 'http://localhost:6006/v1/traces'
312
+ * ```
313
+ *
314
+ * @example
315
+ * URL with custom port and path:
316
+ * ```typescript
317
+ * const normalized = ensureCollectorEndpoint('https://phoenix.example.com:8080');
318
+ * // Returns: 'https://phoenix.example.com:8080/v1/traces'
319
+ * ```
320
+ *
321
+ * @example
322
+ * URL with existing path (edge case):
323
+ * ```typescript
324
+ * const normalized = ensureCollectorEndpoint('https://app.phoenix.arize.com/api');
325
+ * // Returns: 'https://app.phoenix.arize.com/api/v1/traces'
326
+ * ```
83
327
  */
84
328
  export declare function ensureCollectorEndpoint(url: string): string;
85
329
  //# sourceMappingURL=register.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/register.ts"],"names":[],"mappings":"AAQA,OAAO,EAA2B,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EACL,eAAe,EAEhB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,kBAAkB,EAEnB,MAAM,+BAA+B,CAAC;AAEvC,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,QAAQ,CAAC,EACvB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,aAAkB,EAC3B,WAAuB,EACvB,gBAAgB,EAChB,KAAY,EACZ,MAAa,EACb,YAAY,GACb,EAAE,cAAc,GAAG,kBAAkB,CA0CrC;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK3D"}
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/register.ts"],"names":[],"mappings":"AAQA,OAAO,EAA2B,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EACL,eAAe,EAEhB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,kBAAkB,EAClB,aAAa,EACd,MAAM,+BAA+B,CAAC;AAEvC;;;GAGG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;;;;;OASG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;;;;;;OAOG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;;;OAUG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;;;;;;;;;;;;;;OAgBG;IACH,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IAErC;;;;;;;;;;;;;;;OAeG;IACH,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IAEjC;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,kBAAkB,CA6BnE;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,aAAkB,EAC3B,KAAY,GACb,EAAE,IAAI,CACL,cAAc,EACd,KAAK,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,CACvC,GAAG,aAAa,CAuBhB;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAa3D"}
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.register = register;
4
+ exports.getDefaultSpanProcessor = getDefaultSpanProcessor;
4
5
  exports.ensureCollectorEndpoint = ensureCollectorEndpoint;
5
6
  const openinference_semantic_conventions_1 = require("@arizeai/openinference-semantic-conventions");
6
7
  const openinference_vercel_1 = require("@arizeai/openinference-vercel");
@@ -11,34 +12,170 @@ const instrumentation_1 = require("@opentelemetry/instrumentation");
11
12
  const resources_1 = require("@opentelemetry/resources");
12
13
  const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
13
14
  /**
14
- * Registers Phoenix OpenTelemetry tracing with the specified configuration
15
+ * Registers Phoenix OpenTelemetry tracing with the specified configuration.
16
+ *
17
+ * This function sets up a complete OpenTelemetry tracing pipeline configured
18
+ * to send traces to a Phoenix instance. It creates a NodeTracerProvider with
19
+ * appropriate span processors, resource attributes, and optional instrumentations.
20
+ *
21
+ * The function handles:
22
+ * - Creating and configuring a NodeTracerProvider
23
+ * - Setting up OTLP trace export to Phoenix
24
+ * - Configuring span processors (batch or simple)
25
+ * - Registering instrumentations (if provided)
26
+ * - Setting up resource attributes for project identification
27
+ * - Optional global provider registration
15
28
  *
16
29
  * @param params - Configuration parameters for Phoenix tracing
17
- * @param params.url - The URL to the phoenix server. Can be postfixed with tracing path
18
- * @param params.apiKey - The API key for the phoenix instance
19
- * @param params.projectName - The project the spans should be associated to
20
- * @param params.instrumentations - A list of instrumentation to register
21
- * @param params.batch - Whether to use batching for span processing
22
- * @param params.global - Whether to set the tracer as a global provider
23
- * @param params.diagLogLevel - the diagnostics log level
24
- * @returns {NodeTracerProvider} The configured NodeTracerProvider instance
30
+ * @returns The configured NodeTracerProvider instance that can be used to create traces
25
31
  *
26
32
  * @example
33
+ * Basic usage with minimal configuration:
27
34
  * ```typescript
28
35
  * import { register } from '@arizeai/phoenix-otel';
29
36
  *
37
+ * // Uses environment variables for URL and API key
30
38
  * const provider = register({
31
- * projectName: 'my-app',
39
+ * projectName: 'my-application'
40
+ * });
41
+ * ```
42
+ *
43
+ * @example
44
+ * Full configuration with custom settings:
45
+ * ```typescript
46
+ * import { register } from '@arizeai/phoenix-otel';
47
+ * import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
48
+ * import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
49
+ *
50
+ * const provider = register({
51
+ * projectName: 'my-web-app',
32
52
  * url: 'https://app.phoenix.arize.com',
33
- * apiKey: 'your-api-key',
34
- * batch: true
53
+ * apiKey: 'phx_1234567890abcdef',
54
+ * batch: true,
55
+ * global: true,
56
+ * instrumentations: [
57
+ * new HttpInstrumentation(),
58
+ * new ExpressInstrumentation()
59
+ * ],
60
+ * diagLogLevel: DiagLogLevel.INFO
61
+ * });
62
+ * ```
63
+ *
64
+ * @example
65
+ * Custom span processors:
66
+ * ```typescript
67
+ * import { register } from '@arizeai/phoenix-otel';
68
+ * import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
69
+ * import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';
70
+ *
71
+ * const exporter = new OTLPTraceExporter({
72
+ * url: 'https://app.phoenix.arize.com/v1/traces',
73
+ * headers: { 'Authorization': 'Bearer your-api-key' }
74
+ * });
75
+ *
76
+ * const provider = register({
77
+ * projectName: 'my-app',
78
+ * spanProcessors: [new BatchSpanProcessor(exporter)],
79
+ * global: false // Manual provider management
80
+ * });
81
+ * ```
82
+ *
83
+ * @example
84
+ * Debugging configuration:
85
+ * ```typescript
86
+ * const provider = register({
87
+ * projectName: 'debug-app',
88
+ * url: 'http://localhost:6006',
89
+ * batch: false, // Immediate span export for debugging
90
+ * diagLogLevel: DiagLogLevel.DEBUG
35
91
  * });
36
92
  * ```
37
93
  */
38
- function register({ url: paramsUrl, apiKey: paramsApiKey, headers: paramsHeaders = {}, projectName = "default", instrumentations, batch = true, global = true, diagLogLevel, }) {
94
+ function register(params) {
95
+ const { projectName = "default", instrumentations, global = true, diagLogLevel, spanProcessors, } = params;
39
96
  if (diagLogLevel) {
40
97
  api_1.diag.setLogger(new api_1.DiagConsoleLogger(), diagLogLevel);
41
98
  }
99
+ const provider = new sdk_trace_node_1.NodeTracerProvider({
100
+ resource: (0, resources_1.resourceFromAttributes)({
101
+ [openinference_semantic_conventions_1.SEMRESATTRS_PROJECT_NAME]: projectName,
102
+ }),
103
+ spanProcessors: spanProcessors || [getDefaultSpanProcessor(params)],
104
+ });
105
+ if (instrumentations) {
106
+ (0, instrumentation_1.registerInstrumentations)({
107
+ instrumentations,
108
+ tracerProvider: provider,
109
+ });
110
+ }
111
+ if (global) {
112
+ provider.register();
113
+ }
114
+ return provider;
115
+ }
116
+ /**
117
+ * Creates a default span processor configured for Phoenix OpenTelemetry tracing.
118
+ *
119
+ * This function creates an appropriate span processor (batch or simple) based on
120
+ * the provided configuration parameters. It handles URL normalization, header
121
+ * configuration, and API key authentication automatically.
122
+ *
123
+ * The function will:
124
+ * - Normalize the collector URL to include the `/v1/traces` endpoint if needed
125
+ * - Configure authentication headers using the provided API key
126
+ * - Merge any additional custom headers
127
+ * - Create either a batch or simple span processor based on the `batch` parameter
128
+ *
129
+ * @param params - Configuration parameters for the span processor
130
+ * @param params.url - The URL to the Phoenix server (will be normalized to include `/v1/traces`)
131
+ * @param params.apiKey - The API key for authenticating with the Phoenix instance
132
+ * @param params.headers - Additional headers to include in OTLP requests
133
+ * @param params.batch - Whether to use batching for span processing (recommended for production)
134
+ * @returns A configured SpanProcessor instance ready for use with a NodeTracerProvider
135
+ *
136
+ * @example
137
+ * Basic usage with environment variables:
138
+ * ```typescript
139
+ * const processor = getDefaultSpanProcessor({
140
+ * batch: true
141
+ * });
142
+ * ```
143
+ *
144
+ * @example
145
+ * Full configuration with custom settings:
146
+ * ```typescript
147
+ * const processor = getDefaultSpanProcessor({
148
+ * url: 'https://app.phoenix.arize.com',
149
+ * apiKey: 'phx_1234567890abcdef',
150
+ * headers: { 'x-custom-header': 'value' },
151
+ * batch: true
152
+ * });
153
+ * ```
154
+ *
155
+ * @example
156
+ * Debugging configuration with immediate export:
157
+ * ```typescript
158
+ * const processor = getDefaultSpanProcessor({
159
+ * url: 'http://localhost:6006',
160
+ * batch: false // Immediate span export for debugging
161
+ * });
162
+ * ```
163
+ *
164
+ * @example
165
+ * Using with custom headers:
166
+ * ```typescript
167
+ * const processor = getDefaultSpanProcessor({
168
+ * url: 'https://app.phoenix.arize.com',
169
+ * apiKey: 'your-api-key',
170
+ * headers: {
171
+ * 'x-api-version': '1.0',
172
+ * 'x-client-name': 'my-app'
173
+ * },
174
+ * batch: true
175
+ * });
176
+ * ```
177
+ */
178
+ function getDefaultSpanProcessor({ url: paramsUrl, apiKey: paramsApiKey, headers: paramsHeaders = {}, batch = true, }) {
42
179
  const url = ensureCollectorEndpoint(paramsUrl || (0, config_1.getEnvCollectorURL)() || "http://localhost:6006");
43
180
  const apiKey = paramsApiKey || (0, config_1.getEnvApiKey)();
44
181
  const headers = Array.isArray(paramsHeaders)
@@ -59,33 +196,70 @@ function register({ url: paramsUrl, apiKey: paramsApiKey, headers: paramsHeaders
59
196
  else {
60
197
  spanProcessor = new openinference_vercel_1.OpenInferenceSimpleSpanProcessor({ exporter });
61
198
  }
62
- const provider = new sdk_trace_node_1.NodeTracerProvider({
63
- resource: (0, resources_1.resourceFromAttributes)({
64
- [openinference_semantic_conventions_1.SEMRESATTRS_PROJECT_NAME]: projectName,
65
- }),
66
- spanProcessors: [spanProcessor],
67
- });
68
- if (instrumentations) {
69
- (0, instrumentation_1.registerInstrumentations)({
70
- instrumentations,
71
- tracerProvider: provider,
72
- });
73
- }
74
- if (global) {
75
- provider.register();
76
- }
77
- return provider;
199
+ return spanProcessor;
78
200
  }
79
201
  /**
80
- * A utility method to normalize the URL to be HTTP compatible.
81
- * Assumes we are using HTTP over gRPC and ensures the URL ends with the correct traces endpoint.
202
+ * Normalizes a Phoenix server URL to ensure it includes the correct OTLP traces endpoint.
203
+ *
204
+ * This utility function ensures that any Phoenix server URL is properly formatted
205
+ * to include the `/v1/traces` endpoint required for OTLP trace export. It handles
206
+ * various URL formats and automatically appends the endpoint if missing.
207
+ *
208
+ * The function:
209
+ * - Checks if the URL already contains `/v1/traces`
210
+ * - If missing, appends `/v1/traces` to the base URL
211
+ * - Returns a properly formatted URL string
212
+ * - Assumes HTTP over gRPC protocol for OTLP communication
213
+ *
214
+ * @param url - The base URL to the Phoenix server (may or may not include the traces endpoint)
215
+ * @returns A normalized URL string that includes the `/v1/traces` endpoint
216
+ *
217
+ * @example
218
+ * URL without traces endpoint:
219
+ * ```typescript
220
+ * const normalized = ensureCollectorEndpoint('https://app.phoenix.arize.com');
221
+ * // Returns: 'https://app.phoenix.arize.com/v1/traces'
222
+ * ```
223
+ *
224
+ * @example
225
+ * URL that already includes traces endpoint:
226
+ * ```typescript
227
+ * const normalized = ensureCollectorEndpoint('https://app.phoenix.arize.com/v1/traces');
228
+ * // Returns: 'https://app.phoenix.arize.com/v1/traces'
229
+ * ```
230
+ *
231
+ * @example
232
+ * Local development URL:
233
+ * ```typescript
234
+ * const normalized = ensureCollectorEndpoint('http://localhost:6006');
235
+ * // Returns: 'http://localhost:6006/v1/traces'
236
+ * ```
82
237
  *
83
- * @param url - The URL to the phoenix server. May contain a slug
84
- * @returns {string} The normalized URL with the '/v1/traces' endpoint
238
+ * @example
239
+ * URL with custom port and path:
240
+ * ```typescript
241
+ * const normalized = ensureCollectorEndpoint('https://phoenix.example.com:8080');
242
+ * // Returns: 'https://phoenix.example.com:8080/v1/traces'
243
+ * ```
244
+ *
245
+ * @example
246
+ * URL with existing path (edge case):
247
+ * ```typescript
248
+ * const normalized = ensureCollectorEndpoint('https://app.phoenix.arize.com/api');
249
+ * // Returns: 'https://app.phoenix.arize.com/api/v1/traces'
250
+ * ```
85
251
  */
86
252
  function ensureCollectorEndpoint(url) {
87
253
  if (!url.includes("/v1/traces")) {
88
- return new URL("/v1/traces", url).toString();
254
+ // Ensure the base URL has a trailing slash for proper path concatenation
255
+ // Without this, the URL constructor treats the last segment as a file and replaces it
256
+ const baseUrl = new URL(url);
257
+ if (!baseUrl.pathname.endsWith("/")) {
258
+ baseUrl.pathname += "/";
259
+ }
260
+ // Append v1/traces to the pathname (without leading slash to append, not replace)
261
+ baseUrl.pathname += "v1/traces";
262
+ return baseUrl.toString();
89
263
  }
90
264
  return new URL(url).toString();
91
265
  }
@@ -1 +1 @@
1
- {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/register.ts"],"names":[],"mappings":";;AA8FA,4BAmDC;AASD,0DAKC;AA/JD,oGAAuF;AACvF,wEAGuC;AAEvC,qCAA4D;AAE5D,4CAA2E;AAC3E,wFAA6E;AAC7E,oEAGwC;AACxC,wDAAkE;AAClE,kEAGuC;AAmDvC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,SAAgB,QAAQ,CAAC,EACvB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,aAAa,GAAG,EAAE,EAC3B,WAAW,GAAG,SAAS,EACvB,gBAAgB,EAChB,KAAK,GAAG,IAAI,EACZ,MAAM,GAAG,IAAI,EACb,YAAY,GACG;IACf,IAAI,YAAY,EAAE,CAAC;QACjB,UAAI,CAAC,SAAS,CAAC,IAAI,uBAAiB,EAAE,EAAE,YAAY,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,GAAG,GAAG,uBAAuB,CACjC,SAAS,IAAI,IAAA,2BAAkB,GAAE,IAAI,uBAAuB,CAC7D,CAAC;IACF,MAAM,MAAM,GAAG,YAAY,IAAI,IAAA,qBAAY,GAAE,CAAC;IAC9C,MAAM,OAAO,GAAY,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC;QACnD,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC;QACnC,CAAC,CAAC,aAAa,CAAC;IAClB,MAAM,gBAAgB,GAAG,OAAO,MAAM,IAAI,QAAQ,CAAC;IACnD,IAAI,gBAAgB,EAAE,CAAC;QACrB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,EAAE,CAAC;IAChD,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,6CAAiB,CAAC;QACrC,GAAG;QACH,OAAO;KACR,CAAC,CAAC;IACH,IAAI,aAA4B,CAAC;IACjC,IAAI,KAAK,EAAE,CAAC;QACV,aAAa,GAAG,IAAI,sDAA+B,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,aAAa,GAAG,IAAI,uDAAgC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,mCAAkB,CAAC;QACtC,QAAQ,EAAE,IAAA,kCAAsB,EAAC;YAC/B,CAAC,6DAAwB,CAAC,EAAE,WAAW;SACxC,CAAC;QACF,cAAc,EAAE,CAAC,aAAa,CAAC;KAChC,CAAC,CAAC;IAEH,IAAI,gBAAgB,EAAE,CAAC;QACrB,IAAA,0CAAwB,EAAC;YACvB,gBAAgB;YAChB,cAAc,EAAE,QAAQ;SACzB,CAAC,CAAC;IACL,CAAC;IACD,IAAI,MAAM,EAAE,CAAC;QACX,QAAQ,CAAC,QAAQ,EAAE,CAAC;IACtB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,uBAAuB,CAAC,GAAW;IACjD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/register.ts"],"names":[],"mappings":"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"}