@mastra/arize 1.3.16 → 1.3.17-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -4
- package/dist/index.js.map +1 -1
- package/dist/openInferenceOTLPExporter.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -22,8 +22,6 @@ const MASTRA_SPAN_TYPE = "mastra.span.type";
|
|
|
22
22
|
* Only non-CHAIN types are mapped here - all other span types default to CHAIN.
|
|
23
23
|
*/
|
|
24
24
|
const SPAN_TYPE_TO_KIND = {
|
|
25
|
-
model_generation: _arizeai_openinference_semantic_conventions.OpenInferenceSpanKind.LLM,
|
|
26
|
-
model_step: _arizeai_openinference_semantic_conventions.OpenInferenceSpanKind.LLM,
|
|
27
25
|
model_chunk: _arizeai_openinference_semantic_conventions.OpenInferenceSpanKind.LLM,
|
|
28
26
|
tool_call: _arizeai_openinference_semantic_conventions.OpenInferenceSpanKind.TOOL,
|
|
29
27
|
mcp_tool_call: _arizeai_openinference_semantic_conventions.OpenInferenceSpanKind.TOOL,
|
|
@@ -130,7 +128,7 @@ var OpenInferenceOTLPTraceExporter = class extends _opentelemetry_exporter_trace
|
|
|
130
128
|
...mastraOther
|
|
131
129
|
};
|
|
132
130
|
const spanType = mastraOther[MASTRA_SPAN_TYPE];
|
|
133
|
-
if (typeof spanType === "string") mutableSpan.attributes[_arizeai_openinference_semantic_conventions.SemanticConventions.OPENINFERENCE_SPAN_KIND] = SPAN_TYPE_TO_KIND[spanType] ?? _arizeai_openinference_semantic_conventions.OpenInferenceSpanKind.CHAIN;
|
|
131
|
+
if (typeof spanType === "string") mutableSpan.attributes[_arizeai_openinference_semantic_conventions.SemanticConventions.OPENINFERENCE_SPAN_KIND] = attributes[_opentelemetry_semantic_conventions_incubating.ATTR_GEN_AI_OPERATION_NAME] === "chat" ? _arizeai_openinference_semantic_conventions.OpenInferenceSpanKind.LLM : SPAN_TYPE_TO_KIND[spanType] ?? _arizeai_openinference_semantic_conventions.OpenInferenceSpanKind.CHAIN;
|
|
134
132
|
}
|
|
135
133
|
return mutableSpan;
|
|
136
134
|
});
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["OpenInferenceSpanKind","ATTR_GEN_AI_USAGE_INPUT_TOKENS","ATTR_GEN_AI_USAGE_OUTPUT_TOKENS","LLM_TOKEN_COUNT_PROMPT","LLM_TOKEN_COUNT_COMPLETION","LLM_TOKEN_COUNT_TOTAL","LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ","LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE","LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING","LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO","LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO","OTLPTraceExporter","SESSION_ID","TAG_TAGS","USER_ID","METADATA","ATTR_GEN_AI_INPUT_MESSAGES","ATTR_GEN_AI_TOOL_CALL_ARGUMENTS","INPUT_MIME_TYPE","INPUT_VALUE","ATTR_GEN_AI_OUTPUT_MESSAGES","ATTR_GEN_AI_TOOL_CALL_RESULT","OUTPUT_MIME_TYPE","OUTPUT_VALUE","SemanticConventions","OtelExporter","SEMRESATTRS_PROJECT_NAME"],"sources":["../src/openInferenceOTLPExporter.ts","../src/tracing.ts"],"sourcesContent":["import { convertGenAISpanAttributesToOpenInferenceSpanAttributes } from '@arizeai/openinference-genai';\nimport type { Mutable } from '@arizeai/openinference-genai/types';\nimport {\n INPUT_MIME_TYPE,\n INPUT_VALUE,\n LLM_TOKEN_COUNT_COMPLETION,\n LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO,\n LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING,\n LLM_TOKEN_COUNT_PROMPT,\n LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO,\n LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ,\n LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE,\n LLM_TOKEN_COUNT_TOTAL,\n METADATA,\n OpenInferenceSpanKind,\n OUTPUT_MIME_TYPE,\n OUTPUT_VALUE,\n SemanticConventions,\n SESSION_ID,\n TAG_TAGS,\n USER_ID,\n} from '@arizeai/openinference-semantic-conventions';\nimport type { ExportResult } from '@opentelemetry/core';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nimport {\n ATTR_GEN_AI_INPUT_MESSAGES,\n ATTR_GEN_AI_OUTPUT_MESSAGES,\n ATTR_GEN_AI_USAGE_INPUT_TOKENS,\n ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,\n ATTR_GEN_AI_TOOL_CALL_ARGUMENTS,\n ATTR_GEN_AI_TOOL_CALL_RESULT,\n} from '@opentelemetry/semantic-conventions/incubating';\n\n// GenAI usage attribute keys (not all are in @opentelemetry/semantic-conventions yet)\n// @see https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/\nconst GEN_AI_USAGE_REASONING_TOKENS = 'gen_ai.usage.reasoning_tokens';\nconst GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS = 'gen_ai.usage.cache_read.input_tokens';\nconst GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS = 'gen_ai.usage.cache_creation.input_tokens';\nconst GEN_AI_USAGE_AUDIO_INPUT_TOKENS = 'gen_ai.usage.audio_input_tokens';\nconst GEN_AI_USAGE_AUDIO_OUTPUT_TOKENS = 'gen_ai.usage.audio_output_tokens';\n\nconst MASTRA_GENERAL_PREFIX = 'mastra.';\nconst MASTRA_METADATA_PREFIX = 'mastra.metadata.';\nconst MASTRA_MODEL_STEP_INPUT = 'mastra.model_step.input';\nconst MASTRA_MODEL_STEP_OUTPUT = 'mastra.model_step.output';\nconst MASTRA_MODEL_CHUNK_OUTPUT = 'mastra.model_chunk.output';\nconst MASTRA_SPAN_TYPE = 'mastra.span.type';\n\n/**\n * Maps Mastra span types to OpenInference span kinds for proper trace categorization.\n *\n * Only non-CHAIN types are mapped here - all other span types default to CHAIN.\n */\nconst SPAN_TYPE_TO_KIND: Record<string, OpenInferenceSpanKind> = {\n // Model spans -> LLM\n model_generation: OpenInferenceSpanKind.LLM,\n model_step: OpenInferenceSpanKind.LLM,\n model_chunk: OpenInferenceSpanKind.LLM,\n // Tool spans -> TOOL\n tool_call: OpenInferenceSpanKind.TOOL,\n mcp_tool_call: OpenInferenceSpanKind.TOOL,\n // Agent spans -> AGENT\n agent_run: OpenInferenceSpanKind.AGENT,\n};\n\n/**\n * Converts GenAI usage metrics to OpenInference LLM token count attributes.\n * Maps from OTEL GenAI semantic conventions to OpenInference semantic conventions.\n *\n * @param attributes - The span attributes containing GenAI usage metrics\n * @returns OpenInference token count attributes\n */\nfunction convertUsageMetricsToOpenInference(attributes: Record<string, any>): Record<string, any> {\n const result: Record<string, any> = {};\n\n const inputTokens = attributes[ATTR_GEN_AI_USAGE_INPUT_TOKENS];\n const outputTokens = attributes[ATTR_GEN_AI_USAGE_OUTPUT_TOKENS];\n\n // Core token counts\n if (inputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT] = inputTokens;\n }\n if (outputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_COMPLETION] = outputTokens;\n }\n\n // Total tokens (compute if we have both input and output)\n if (inputTokens !== undefined && outputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_TOTAL] = inputTokens + outputTokens;\n }\n\n // Cache tokens (prompt details)\n const cacheReadInputTokens = attributes[GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS];\n if (cacheReadInputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ] = cacheReadInputTokens;\n }\n\n const cacheCreationInputTokens = attributes[GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS];\n if (cacheCreationInputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE] = cacheCreationInputTokens;\n }\n\n // Reasoning tokens (completion details)\n const reasoningTokens = attributes[GEN_AI_USAGE_REASONING_TOKENS];\n if (reasoningTokens !== undefined) {\n result[LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING] = reasoningTokens;\n }\n\n // Audio tokens\n const audioInputTokens = attributes[GEN_AI_USAGE_AUDIO_INPUT_TOKENS];\n if (audioInputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO] = audioInputTokens;\n }\n\n const audioOutputTokens = attributes[GEN_AI_USAGE_AUDIO_OUTPUT_TOKENS];\n if (audioOutputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO] = audioOutputTokens;\n }\n\n return result;\n}\n\n/**\n * Splits Mastra span attributes into two groups:\n * - `metadata`: keys starting with \"mastra.metadata.\" (prefix removed)\n * - `other`: all remaining keys starting with \"mastra.\"\n *\n * Any attributes not starting with \"mastra.\" are ignored entirely.\n */\nfunction splitMastraAttributes(attributes: Record<string, any>): {\n mastraMetadata: Record<string, any>;\n mastraOther: Record<string, any>;\n} {\n return Object.entries(attributes).reduce(\n (acc, [key, value]) => {\n if (key.startsWith(MASTRA_GENERAL_PREFIX)) {\n if (key.startsWith(MASTRA_METADATA_PREFIX)) {\n const strippedKey = key.slice(MASTRA_METADATA_PREFIX.length);\n acc.mastraMetadata[strippedKey] = value;\n } else {\n acc.mastraOther[key] = value;\n }\n }\n return acc;\n },\n {\n mastraMetadata: {} as Record<string, any>,\n mastraOther: {} as Record<string, any>,\n },\n );\n}\n\nexport class OpenInferenceOTLPTraceExporter extends OTLPTraceExporter {\n export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void) {\n const processedSpans = spans.map(span => {\n const attributes = { ...(span.attributes ?? {}) };\n const mutableSpan = span as Mutable<ReadableSpan>;\n\n const { mastraMetadata, mastraOther } = splitMastraAttributes(attributes);\n const processedAttributes = convertGenAISpanAttributesToOpenInferenceSpanAttributes(attributes);\n\n // only add processed attributes if conversion was successful\n if (processedAttributes) {\n const threadId = mastraMetadata['threadId'];\n if (threadId) {\n delete mastraMetadata['threadId'];\n processedAttributes[SESSION_ID] = threadId;\n }\n\n // Map mastra.tags to OpenInference native tag.tags convention (tags are only on root spans)\n if (mastraOther['mastra.tags']) {\n processedAttributes[TAG_TAGS] = mastraOther['mastra.tags'];\n delete mastraOther['mastra.tags'];\n }\n\n const userId = mastraMetadata['userId'];\n if (userId) {\n delete mastraMetadata['userId'];\n processedAttributes[USER_ID] = userId;\n }\n\n // Gather custom metadata into OpenInference metadata (flat best-effort)\n if (Object.keys(mastraMetadata).length > 0) {\n try {\n processedAttributes[METADATA] = JSON.stringify(mastraMetadata);\n } catch {\n // best-effort only\n }\n }\n\n const inputMessages =\n attributes[ATTR_GEN_AI_INPUT_MESSAGES] ??\n attributes[ATTR_GEN_AI_TOOL_CALL_ARGUMENTS] ??\n mastraOther[MASTRA_MODEL_STEP_INPUT];\n if (inputMessages) {\n processedAttributes[INPUT_MIME_TYPE] = 'application/json';\n processedAttributes[INPUT_VALUE] = inputMessages;\n }\n const outputMessages =\n attributes[ATTR_GEN_AI_OUTPUT_MESSAGES] ??\n attributes[ATTR_GEN_AI_TOOL_CALL_RESULT] ??\n mastraOther[MASTRA_MODEL_STEP_OUTPUT] ??\n mastraOther[MASTRA_MODEL_CHUNK_OUTPUT];\n if (outputMessages) {\n processedAttributes[OUTPUT_MIME_TYPE] = 'application/json';\n processedAttributes[OUTPUT_VALUE] = outputMessages;\n }\n\n // Map generic Mastra span input/output to OpenInference input/output\n // These are set by Mastra's gen-ai-semantics.ts for non-LLM/tool spans\n // (e.g., mastra.processor_run.input, mastra.workflow_run.input, etc.)\n if (!processedAttributes[INPUT_VALUE]) {\n for (const key of Object.keys(mastraOther)) {\n if (key.endsWith('.input')) {\n processedAttributes[INPUT_MIME_TYPE] = 'application/json';\n processedAttributes[INPUT_VALUE] = mastraOther[key];\n break;\n }\n }\n }\n if (!processedAttributes[OUTPUT_VALUE]) {\n for (const key of Object.keys(mastraOther)) {\n if (key.endsWith('.output')) {\n processedAttributes[OUTPUT_MIME_TYPE] = 'application/json';\n processedAttributes[OUTPUT_VALUE] = mastraOther[key];\n break;\n }\n }\n }\n\n // Convert GenAI usage metrics to OpenInference token count attributes\n const usageMetrics = convertUsageMetricsToOpenInference(attributes);\n Object.assign(processedAttributes, usageMetrics);\n\n mutableSpan.attributes = { ...processedAttributes, ...mastraOther };\n\n // Set span kind based on mastra.span.type for proper trace categorization\n const spanType = mastraOther[MASTRA_SPAN_TYPE];\n if (typeof spanType === 'string') {\n mutableSpan.attributes[SemanticConventions.OPENINFERENCE_SPAN_KIND] =\n SPAN_TYPE_TO_KIND[spanType] ?? OpenInferenceSpanKind.CHAIN;\n }\n }\n\n return mutableSpan;\n });\n\n super.export(processedSpans, resultCallback);\n }\n}\n","import { SEMRESATTRS_PROJECT_NAME } from '@arizeai/openinference-semantic-conventions';\nimport { OtelExporter } from '@mastra/otel-exporter';\nimport type { OtelExporterConfig } from '@mastra/otel-exporter';\n\nimport { OpenInferenceOTLPTraceExporter } from './openInferenceOTLPExporter.js';\n\nconst LOG_PREFIX = '[ArizeExporter]';\n\nexport const ARIZE_AX_ENDPOINT = 'https://otlp.arize.com/v1/traces';\n\nexport type ArizeExporterConfig = Omit<OtelExporterConfig, 'provider'> & {\n /**\n * Required if sending traces to Arize AX\n */\n spaceId?: string;\n /**\n * Required if sending traces to Arize AX, or to any other collector that\n * requires an Authorization header\n */\n apiKey?: string;\n /**\n * Collector endpoint destination for trace exports.\n * Required when sending traces to Phoenix, Phoenix Cloud, or other collectors.\n * Optional when sending traces to Arize AX.\n */\n endpoint?: string;\n /**\n * Optional project name to be added as a resource attribute using\n * OpenInference Semantic Conventions\n */\n projectName?: string;\n /**\n * Optional headers to be added to each OTLP request\n */\n headers?: Record<string, string>;\n};\n\nexport class ArizeExporter extends OtelExporter {\n name = 'arize';\n\n constructor(config: ArizeExporterConfig = {}) {\n // Read configuration from config or environment variables\n // Priority: config > ARIZE_* env vars > PHOENIX_* env vars\n const spaceId = config.spaceId ?? process.env.ARIZE_SPACE_ID;\n const apiKey = config.apiKey ?? process.env.ARIZE_API_KEY ?? process.env.PHOENIX_API_KEY;\n const projectName = config.projectName ?? process.env.ARIZE_PROJECT_NAME ?? process.env.PHOENIX_PROJECT_NAME;\n\n // Determine endpoint: config > PHOENIX_COLLECTOR_ENDPOINT > PHOENIX_ENDPOINT > ARIZE_AX_ENDPOINT (if spaceId is set)\n let endpoint: string | undefined =\n config.endpoint ?? process.env.PHOENIX_COLLECTOR_ENDPOINT ?? process.env.PHOENIX_ENDPOINT;\n\n const headers: Record<string, string> = {\n ...config.headers,\n };\n\n // Validate credentials based on mode\n let disabledReason: string | undefined;\n\n if (spaceId) {\n // Arize AX mode requires an API key\n if (!apiKey) {\n disabledReason =\n `${LOG_PREFIX} API key is required for Arize AX. ` +\n `Set ARIZE_API_KEY environment variable or pass apiKey in config.`;\n } else {\n // arize ax header configuration\n headers['space_id'] = spaceId;\n headers['api_key'] = apiKey;\n endpoint = endpoint || ARIZE_AX_ENDPOINT;\n }\n } else if (apiKey) {\n // standard otel header configuration\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n if (!disabledReason && !endpoint) {\n disabledReason =\n `${LOG_PREFIX} Endpoint is required in configuration. ` +\n `Set PHOENIX_COLLECTOR_ENDPOINT environment variable, or ARIZE_SPACE_ID for Arize AX, or pass endpoint in config.`;\n }\n\n // If disabled, create with minimal config and disable\n if (disabledReason) {\n super({\n ...config,\n provider: {\n custom: {\n endpoint: 'http://disabled',\n headers: {},\n protocol: 'http/protobuf',\n },\n },\n });\n this.setDisabled(disabledReason);\n return;\n }\n\n super({\n exporter: new OpenInferenceOTLPTraceExporter({\n url: endpoint!,\n headers,\n }),\n ...config,\n resourceAttributes: {\n ...(projectName ? { [SEMRESATTRS_PROJECT_NAME]: projectName } : {}),\n ...config.resourceAttributes,\n },\n provider: {\n custom: {\n endpoint: endpoint!,\n headers,\n protocol: 'http/protobuf',\n },\n } satisfies OtelExporterConfig['provider'],\n } satisfies OtelExporterConfig);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["OpenInferenceSpanKind","ATTR_GEN_AI_USAGE_INPUT_TOKENS","ATTR_GEN_AI_USAGE_OUTPUT_TOKENS","LLM_TOKEN_COUNT_PROMPT","LLM_TOKEN_COUNT_COMPLETION","LLM_TOKEN_COUNT_TOTAL","LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ","LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE","LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING","LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO","LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO","OTLPTraceExporter","SESSION_ID","TAG_TAGS","USER_ID","METADATA","ATTR_GEN_AI_INPUT_MESSAGES","ATTR_GEN_AI_TOOL_CALL_ARGUMENTS","INPUT_MIME_TYPE","INPUT_VALUE","ATTR_GEN_AI_OUTPUT_MESSAGES","ATTR_GEN_AI_TOOL_CALL_RESULT","OUTPUT_MIME_TYPE","OUTPUT_VALUE","SemanticConventions","ATTR_GEN_AI_OPERATION_NAME","OtelExporter","SEMRESATTRS_PROJECT_NAME"],"sources":["../src/openInferenceOTLPExporter.ts","../src/tracing.ts"],"sourcesContent":["import { convertGenAISpanAttributesToOpenInferenceSpanAttributes } from '@arizeai/openinference-genai';\nimport type { Mutable } from '@arizeai/openinference-genai/types';\nimport {\n INPUT_MIME_TYPE,\n INPUT_VALUE,\n LLM_TOKEN_COUNT_COMPLETION,\n LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO,\n LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING,\n LLM_TOKEN_COUNT_PROMPT,\n LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO,\n LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ,\n LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE,\n LLM_TOKEN_COUNT_TOTAL,\n METADATA,\n OpenInferenceSpanKind,\n OUTPUT_MIME_TYPE,\n OUTPUT_VALUE,\n SemanticConventions,\n SESSION_ID,\n TAG_TAGS,\n USER_ID,\n} from '@arizeai/openinference-semantic-conventions';\nimport type { ExportResult } from '@opentelemetry/core';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nimport {\n ATTR_GEN_AI_INPUT_MESSAGES,\n ATTR_GEN_AI_OPERATION_NAME,\n ATTR_GEN_AI_OUTPUT_MESSAGES,\n ATTR_GEN_AI_USAGE_INPUT_TOKENS,\n ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,\n ATTR_GEN_AI_TOOL_CALL_ARGUMENTS,\n ATTR_GEN_AI_TOOL_CALL_RESULT,\n} from '@opentelemetry/semantic-conventions/incubating';\n\n// GenAI usage attribute keys (not all are in @opentelemetry/semantic-conventions yet)\n// @see https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/\nconst GEN_AI_USAGE_REASONING_TOKENS = 'gen_ai.usage.reasoning_tokens';\nconst GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS = 'gen_ai.usage.cache_read.input_tokens';\nconst GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS = 'gen_ai.usage.cache_creation.input_tokens';\nconst GEN_AI_USAGE_AUDIO_INPUT_TOKENS = 'gen_ai.usage.audio_input_tokens';\nconst GEN_AI_USAGE_AUDIO_OUTPUT_TOKENS = 'gen_ai.usage.audio_output_tokens';\n\nconst MASTRA_GENERAL_PREFIX = 'mastra.';\nconst MASTRA_METADATA_PREFIX = 'mastra.metadata.';\nconst MASTRA_MODEL_STEP_INPUT = 'mastra.model_step.input';\nconst MASTRA_MODEL_STEP_OUTPUT = 'mastra.model_step.output';\nconst MASTRA_MODEL_CHUNK_OUTPUT = 'mastra.model_chunk.output';\nconst MASTRA_SPAN_TYPE = 'mastra.span.type';\n\n/**\n * Maps Mastra span types to OpenInference span kinds for proper trace categorization.\n *\n * Only non-CHAIN types are mapped here - all other span types default to CHAIN.\n */\nconst SPAN_TYPE_TO_KIND: Record<string, OpenInferenceSpanKind> = {\n // The model call itself (gen_ai.operation.name === 'chat') is mapped to LLM\n // below; the generation loop and its steps around it default to CHAIN.\n model_chunk: OpenInferenceSpanKind.LLM,\n // Tool spans -> TOOL\n tool_call: OpenInferenceSpanKind.TOOL,\n mcp_tool_call: OpenInferenceSpanKind.TOOL,\n // Agent spans -> AGENT\n agent_run: OpenInferenceSpanKind.AGENT,\n};\n\n/**\n * Converts GenAI usage metrics to OpenInference LLM token count attributes.\n * Maps from OTEL GenAI semantic conventions to OpenInference semantic conventions.\n *\n * @param attributes - The span attributes containing GenAI usage metrics\n * @returns OpenInference token count attributes\n */\nfunction convertUsageMetricsToOpenInference(attributes: Record<string, any>): Record<string, any> {\n const result: Record<string, any> = {};\n\n const inputTokens = attributes[ATTR_GEN_AI_USAGE_INPUT_TOKENS];\n const outputTokens = attributes[ATTR_GEN_AI_USAGE_OUTPUT_TOKENS];\n\n // Core token counts\n if (inputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT] = inputTokens;\n }\n if (outputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_COMPLETION] = outputTokens;\n }\n\n // Total tokens (compute if we have both input and output)\n if (inputTokens !== undefined && outputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_TOTAL] = inputTokens + outputTokens;\n }\n\n // Cache tokens (prompt details)\n const cacheReadInputTokens = attributes[GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS];\n if (cacheReadInputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ] = cacheReadInputTokens;\n }\n\n const cacheCreationInputTokens = attributes[GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS];\n if (cacheCreationInputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE] = cacheCreationInputTokens;\n }\n\n // Reasoning tokens (completion details)\n const reasoningTokens = attributes[GEN_AI_USAGE_REASONING_TOKENS];\n if (reasoningTokens !== undefined) {\n result[LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING] = reasoningTokens;\n }\n\n // Audio tokens\n const audioInputTokens = attributes[GEN_AI_USAGE_AUDIO_INPUT_TOKENS];\n if (audioInputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO] = audioInputTokens;\n }\n\n const audioOutputTokens = attributes[GEN_AI_USAGE_AUDIO_OUTPUT_TOKENS];\n if (audioOutputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO] = audioOutputTokens;\n }\n\n return result;\n}\n\n/**\n * Splits Mastra span attributes into two groups:\n * - `metadata`: keys starting with \"mastra.metadata.\" (prefix removed)\n * - `other`: all remaining keys starting with \"mastra.\"\n *\n * Any attributes not starting with \"mastra.\" are ignored entirely.\n */\nfunction splitMastraAttributes(attributes: Record<string, any>): {\n mastraMetadata: Record<string, any>;\n mastraOther: Record<string, any>;\n} {\n return Object.entries(attributes).reduce(\n (acc, [key, value]) => {\n if (key.startsWith(MASTRA_GENERAL_PREFIX)) {\n if (key.startsWith(MASTRA_METADATA_PREFIX)) {\n const strippedKey = key.slice(MASTRA_METADATA_PREFIX.length);\n acc.mastraMetadata[strippedKey] = value;\n } else {\n acc.mastraOther[key] = value;\n }\n }\n return acc;\n },\n {\n mastraMetadata: {} as Record<string, any>,\n mastraOther: {} as Record<string, any>,\n },\n );\n}\n\nexport class OpenInferenceOTLPTraceExporter extends OTLPTraceExporter {\n export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void) {\n const processedSpans = spans.map(span => {\n const attributes = { ...(span.attributes ?? {}) };\n const mutableSpan = span as Mutable<ReadableSpan>;\n\n const { mastraMetadata, mastraOther } = splitMastraAttributes(attributes);\n const processedAttributes = convertGenAISpanAttributesToOpenInferenceSpanAttributes(attributes);\n\n // only add processed attributes if conversion was successful\n if (processedAttributes) {\n const threadId = mastraMetadata['threadId'];\n if (threadId) {\n delete mastraMetadata['threadId'];\n processedAttributes[SESSION_ID] = threadId;\n }\n\n // Map mastra.tags to OpenInference native tag.tags convention (tags are only on root spans)\n if (mastraOther['mastra.tags']) {\n processedAttributes[TAG_TAGS] = mastraOther['mastra.tags'];\n delete mastraOther['mastra.tags'];\n }\n\n const userId = mastraMetadata['userId'];\n if (userId) {\n delete mastraMetadata['userId'];\n processedAttributes[USER_ID] = userId;\n }\n\n // Gather custom metadata into OpenInference metadata (flat best-effort)\n if (Object.keys(mastraMetadata).length > 0) {\n try {\n processedAttributes[METADATA] = JSON.stringify(mastraMetadata);\n } catch {\n // best-effort only\n }\n }\n\n const inputMessages =\n attributes[ATTR_GEN_AI_INPUT_MESSAGES] ??\n attributes[ATTR_GEN_AI_TOOL_CALL_ARGUMENTS] ??\n mastraOther[MASTRA_MODEL_STEP_INPUT];\n if (inputMessages) {\n processedAttributes[INPUT_MIME_TYPE] = 'application/json';\n processedAttributes[INPUT_VALUE] = inputMessages;\n }\n const outputMessages =\n attributes[ATTR_GEN_AI_OUTPUT_MESSAGES] ??\n attributes[ATTR_GEN_AI_TOOL_CALL_RESULT] ??\n mastraOther[MASTRA_MODEL_STEP_OUTPUT] ??\n mastraOther[MASTRA_MODEL_CHUNK_OUTPUT];\n if (outputMessages) {\n processedAttributes[OUTPUT_MIME_TYPE] = 'application/json';\n processedAttributes[OUTPUT_VALUE] = outputMessages;\n }\n\n // Map generic Mastra span input/output to OpenInference input/output\n // These are set by Mastra's gen-ai-semantics.ts for non-LLM/tool spans\n // (e.g., mastra.processor_run.input, mastra.workflow_run.input, etc.)\n if (!processedAttributes[INPUT_VALUE]) {\n for (const key of Object.keys(mastraOther)) {\n if (key.endsWith('.input')) {\n processedAttributes[INPUT_MIME_TYPE] = 'application/json';\n processedAttributes[INPUT_VALUE] = mastraOther[key];\n break;\n }\n }\n }\n if (!processedAttributes[OUTPUT_VALUE]) {\n for (const key of Object.keys(mastraOther)) {\n if (key.endsWith('.output')) {\n processedAttributes[OUTPUT_MIME_TYPE] = 'application/json';\n processedAttributes[OUTPUT_VALUE] = mastraOther[key];\n break;\n }\n }\n }\n\n // Convert GenAI usage metrics to OpenInference token count attributes\n const usageMetrics = convertUsageMetricsToOpenInference(attributes);\n Object.assign(processedAttributes, usageMetrics);\n\n mutableSpan.attributes = { ...processedAttributes, ...mastraOther };\n\n // Set span kind based on mastra.span.type for proper trace categorization\n const spanType = mastraOther[MASTRA_SPAN_TYPE];\n if (typeof spanType === 'string') {\n mutableSpan.attributes[SemanticConventions.OPENINFERENCE_SPAN_KIND] =\n attributes[ATTR_GEN_AI_OPERATION_NAME] === 'chat'\n ? OpenInferenceSpanKind.LLM\n : (SPAN_TYPE_TO_KIND[spanType] ?? OpenInferenceSpanKind.CHAIN);\n }\n }\n\n return mutableSpan;\n });\n\n super.export(processedSpans, resultCallback);\n }\n}\n","import { SEMRESATTRS_PROJECT_NAME } from '@arizeai/openinference-semantic-conventions';\nimport { OtelExporter } from '@mastra/otel-exporter';\nimport type { OtelExporterConfig } from '@mastra/otel-exporter';\n\nimport { OpenInferenceOTLPTraceExporter } from './openInferenceOTLPExporter.js';\n\nconst LOG_PREFIX = '[ArizeExporter]';\n\nexport const ARIZE_AX_ENDPOINT = 'https://otlp.arize.com/v1/traces';\n\nexport type ArizeExporterConfig = Omit<OtelExporterConfig, 'provider'> & {\n /**\n * Required if sending traces to Arize AX\n */\n spaceId?: string;\n /**\n * Required if sending traces to Arize AX, or to any other collector that\n * requires an Authorization header\n */\n apiKey?: string;\n /**\n * Collector endpoint destination for trace exports.\n * Required when sending traces to Phoenix, Phoenix Cloud, or other collectors.\n * Optional when sending traces to Arize AX.\n */\n endpoint?: string;\n /**\n * Optional project name to be added as a resource attribute using\n * OpenInference Semantic Conventions\n */\n projectName?: string;\n /**\n * Optional headers to be added to each OTLP request\n */\n headers?: Record<string, string>;\n};\n\nexport class ArizeExporter extends OtelExporter {\n name = 'arize';\n\n constructor(config: ArizeExporterConfig = {}) {\n // Read configuration from config or environment variables\n // Priority: config > ARIZE_* env vars > PHOENIX_* env vars\n const spaceId = config.spaceId ?? process.env.ARIZE_SPACE_ID;\n const apiKey = config.apiKey ?? process.env.ARIZE_API_KEY ?? process.env.PHOENIX_API_KEY;\n const projectName = config.projectName ?? process.env.ARIZE_PROJECT_NAME ?? process.env.PHOENIX_PROJECT_NAME;\n\n // Determine endpoint: config > PHOENIX_COLLECTOR_ENDPOINT > PHOENIX_ENDPOINT > ARIZE_AX_ENDPOINT (if spaceId is set)\n let endpoint: string | undefined =\n config.endpoint ?? process.env.PHOENIX_COLLECTOR_ENDPOINT ?? process.env.PHOENIX_ENDPOINT;\n\n const headers: Record<string, string> = {\n ...config.headers,\n };\n\n // Validate credentials based on mode\n let disabledReason: string | undefined;\n\n if (spaceId) {\n // Arize AX mode requires an API key\n if (!apiKey) {\n disabledReason =\n `${LOG_PREFIX} API key is required for Arize AX. ` +\n `Set ARIZE_API_KEY environment variable or pass apiKey in config.`;\n } else {\n // arize ax header configuration\n headers['space_id'] = spaceId;\n headers['api_key'] = apiKey;\n endpoint = endpoint || ARIZE_AX_ENDPOINT;\n }\n } else if (apiKey) {\n // standard otel header configuration\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n if (!disabledReason && !endpoint) {\n disabledReason =\n `${LOG_PREFIX} Endpoint is required in configuration. ` +\n `Set PHOENIX_COLLECTOR_ENDPOINT environment variable, or ARIZE_SPACE_ID for Arize AX, or pass endpoint in config.`;\n }\n\n // If disabled, create with minimal config and disable\n if (disabledReason) {\n super({\n ...config,\n provider: {\n custom: {\n endpoint: 'http://disabled',\n headers: {},\n protocol: 'http/protobuf',\n },\n },\n });\n this.setDisabled(disabledReason);\n return;\n }\n\n super({\n exporter: new OpenInferenceOTLPTraceExporter({\n url: endpoint!,\n headers,\n }),\n ...config,\n resourceAttributes: {\n ...(projectName ? { [SEMRESATTRS_PROJECT_NAME]: projectName } : {}),\n ...config.resourceAttributes,\n },\n provider: {\n custom: {\n endpoint: endpoint!,\n headers,\n protocol: 'http/protobuf',\n },\n } satisfies OtelExporterConfig['provider'],\n } satisfies OtelExporterConfig);\n }\n}\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import { INPUT_MIME_TYPE, INPUT_VALUE, LLM_TOKEN_COUNT_COMPLETION, LLM_TOKEN_COU
|
|
|
2
2
|
import { OtelExporter } from "@mastra/otel-exporter";
|
|
3
3
|
import { convertGenAISpanAttributesToOpenInferenceSpanAttributes } from "@arizeai/openinference-genai";
|
|
4
4
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
|
|
5
|
-
import { ATTR_GEN_AI_INPUT_MESSAGES, ATTR_GEN_AI_OUTPUT_MESSAGES, ATTR_GEN_AI_TOOL_CALL_ARGUMENTS, ATTR_GEN_AI_TOOL_CALL_RESULT, ATTR_GEN_AI_USAGE_INPUT_TOKENS, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS } from "@opentelemetry/semantic-conventions/incubating";
|
|
5
|
+
import { ATTR_GEN_AI_INPUT_MESSAGES, ATTR_GEN_AI_OPERATION_NAME, ATTR_GEN_AI_OUTPUT_MESSAGES, ATTR_GEN_AI_TOOL_CALL_ARGUMENTS, ATTR_GEN_AI_TOOL_CALL_RESULT, ATTR_GEN_AI_USAGE_INPUT_TOKENS, ATTR_GEN_AI_USAGE_OUTPUT_TOKENS } from "@opentelemetry/semantic-conventions/incubating";
|
|
6
6
|
//#region src/openInferenceOTLPExporter.ts
|
|
7
7
|
const GEN_AI_USAGE_REASONING_TOKENS = "gen_ai.usage.reasoning_tokens";
|
|
8
8
|
const GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS = "gen_ai.usage.cache_read.input_tokens";
|
|
@@ -21,8 +21,6 @@ const MASTRA_SPAN_TYPE = "mastra.span.type";
|
|
|
21
21
|
* Only non-CHAIN types are mapped here - all other span types default to CHAIN.
|
|
22
22
|
*/
|
|
23
23
|
const SPAN_TYPE_TO_KIND = {
|
|
24
|
-
model_generation: OpenInferenceSpanKind.LLM,
|
|
25
|
-
model_step: OpenInferenceSpanKind.LLM,
|
|
26
24
|
model_chunk: OpenInferenceSpanKind.LLM,
|
|
27
25
|
tool_call: OpenInferenceSpanKind.TOOL,
|
|
28
26
|
mcp_tool_call: OpenInferenceSpanKind.TOOL,
|
|
@@ -129,7 +127,7 @@ var OpenInferenceOTLPTraceExporter = class extends OTLPTraceExporter {
|
|
|
129
127
|
...mastraOther
|
|
130
128
|
};
|
|
131
129
|
const spanType = mastraOther[MASTRA_SPAN_TYPE];
|
|
132
|
-
if (typeof spanType === "string") mutableSpan.attributes[SemanticConventions.OPENINFERENCE_SPAN_KIND] = SPAN_TYPE_TO_KIND[spanType] ?? OpenInferenceSpanKind.CHAIN;
|
|
130
|
+
if (typeof spanType === "string") mutableSpan.attributes[SemanticConventions.OPENINFERENCE_SPAN_KIND] = attributes[ATTR_GEN_AI_OPERATION_NAME] === "chat" ? OpenInferenceSpanKind.LLM : SPAN_TYPE_TO_KIND[spanType] ?? OpenInferenceSpanKind.CHAIN;
|
|
133
131
|
}
|
|
134
132
|
return mutableSpan;
|
|
135
133
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/openInferenceOTLPExporter.ts","../src/tracing.ts"],"sourcesContent":["import { convertGenAISpanAttributesToOpenInferenceSpanAttributes } from '@arizeai/openinference-genai';\nimport type { Mutable } from '@arizeai/openinference-genai/types';\nimport {\n INPUT_MIME_TYPE,\n INPUT_VALUE,\n LLM_TOKEN_COUNT_COMPLETION,\n LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO,\n LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING,\n LLM_TOKEN_COUNT_PROMPT,\n LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO,\n LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ,\n LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE,\n LLM_TOKEN_COUNT_TOTAL,\n METADATA,\n OpenInferenceSpanKind,\n OUTPUT_MIME_TYPE,\n OUTPUT_VALUE,\n SemanticConventions,\n SESSION_ID,\n TAG_TAGS,\n USER_ID,\n} from '@arizeai/openinference-semantic-conventions';\nimport type { ExportResult } from '@opentelemetry/core';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nimport {\n ATTR_GEN_AI_INPUT_MESSAGES,\n ATTR_GEN_AI_OUTPUT_MESSAGES,\n ATTR_GEN_AI_USAGE_INPUT_TOKENS,\n ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,\n ATTR_GEN_AI_TOOL_CALL_ARGUMENTS,\n ATTR_GEN_AI_TOOL_CALL_RESULT,\n} from '@opentelemetry/semantic-conventions/incubating';\n\n// GenAI usage attribute keys (not all are in @opentelemetry/semantic-conventions yet)\n// @see https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/\nconst GEN_AI_USAGE_REASONING_TOKENS = 'gen_ai.usage.reasoning_tokens';\nconst GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS = 'gen_ai.usage.cache_read.input_tokens';\nconst GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS = 'gen_ai.usage.cache_creation.input_tokens';\nconst GEN_AI_USAGE_AUDIO_INPUT_TOKENS = 'gen_ai.usage.audio_input_tokens';\nconst GEN_AI_USAGE_AUDIO_OUTPUT_TOKENS = 'gen_ai.usage.audio_output_tokens';\n\nconst MASTRA_GENERAL_PREFIX = 'mastra.';\nconst MASTRA_METADATA_PREFIX = 'mastra.metadata.';\nconst MASTRA_MODEL_STEP_INPUT = 'mastra.model_step.input';\nconst MASTRA_MODEL_STEP_OUTPUT = 'mastra.model_step.output';\nconst MASTRA_MODEL_CHUNK_OUTPUT = 'mastra.model_chunk.output';\nconst MASTRA_SPAN_TYPE = 'mastra.span.type';\n\n/**\n * Maps Mastra span types to OpenInference span kinds for proper trace categorization.\n *\n * Only non-CHAIN types are mapped here - all other span types default to CHAIN.\n */\nconst SPAN_TYPE_TO_KIND: Record<string, OpenInferenceSpanKind> = {\n // Model spans -> LLM\n model_generation: OpenInferenceSpanKind.LLM,\n model_step: OpenInferenceSpanKind.LLM,\n model_chunk: OpenInferenceSpanKind.LLM,\n // Tool spans -> TOOL\n tool_call: OpenInferenceSpanKind.TOOL,\n mcp_tool_call: OpenInferenceSpanKind.TOOL,\n // Agent spans -> AGENT\n agent_run: OpenInferenceSpanKind.AGENT,\n};\n\n/**\n * Converts GenAI usage metrics to OpenInference LLM token count attributes.\n * Maps from OTEL GenAI semantic conventions to OpenInference semantic conventions.\n *\n * @param attributes - The span attributes containing GenAI usage metrics\n * @returns OpenInference token count attributes\n */\nfunction convertUsageMetricsToOpenInference(attributes: Record<string, any>): Record<string, any> {\n const result: Record<string, any> = {};\n\n const inputTokens = attributes[ATTR_GEN_AI_USAGE_INPUT_TOKENS];\n const outputTokens = attributes[ATTR_GEN_AI_USAGE_OUTPUT_TOKENS];\n\n // Core token counts\n if (inputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT] = inputTokens;\n }\n if (outputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_COMPLETION] = outputTokens;\n }\n\n // Total tokens (compute if we have both input and output)\n if (inputTokens !== undefined && outputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_TOTAL] = inputTokens + outputTokens;\n }\n\n // Cache tokens (prompt details)\n const cacheReadInputTokens = attributes[GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS];\n if (cacheReadInputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ] = cacheReadInputTokens;\n }\n\n const cacheCreationInputTokens = attributes[GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS];\n if (cacheCreationInputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE] = cacheCreationInputTokens;\n }\n\n // Reasoning tokens (completion details)\n const reasoningTokens = attributes[GEN_AI_USAGE_REASONING_TOKENS];\n if (reasoningTokens !== undefined) {\n result[LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING] = reasoningTokens;\n }\n\n // Audio tokens\n const audioInputTokens = attributes[GEN_AI_USAGE_AUDIO_INPUT_TOKENS];\n if (audioInputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO] = audioInputTokens;\n }\n\n const audioOutputTokens = attributes[GEN_AI_USAGE_AUDIO_OUTPUT_TOKENS];\n if (audioOutputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO] = audioOutputTokens;\n }\n\n return result;\n}\n\n/**\n * Splits Mastra span attributes into two groups:\n * - `metadata`: keys starting with \"mastra.metadata.\" (prefix removed)\n * - `other`: all remaining keys starting with \"mastra.\"\n *\n * Any attributes not starting with \"mastra.\" are ignored entirely.\n */\nfunction splitMastraAttributes(attributes: Record<string, any>): {\n mastraMetadata: Record<string, any>;\n mastraOther: Record<string, any>;\n} {\n return Object.entries(attributes).reduce(\n (acc, [key, value]) => {\n if (key.startsWith(MASTRA_GENERAL_PREFIX)) {\n if (key.startsWith(MASTRA_METADATA_PREFIX)) {\n const strippedKey = key.slice(MASTRA_METADATA_PREFIX.length);\n acc.mastraMetadata[strippedKey] = value;\n } else {\n acc.mastraOther[key] = value;\n }\n }\n return acc;\n },\n {\n mastraMetadata: {} as Record<string, any>,\n mastraOther: {} as Record<string, any>,\n },\n );\n}\n\nexport class OpenInferenceOTLPTraceExporter extends OTLPTraceExporter {\n export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void) {\n const processedSpans = spans.map(span => {\n const attributes = { ...(span.attributes ?? {}) };\n const mutableSpan = span as Mutable<ReadableSpan>;\n\n const { mastraMetadata, mastraOther } = splitMastraAttributes(attributes);\n const processedAttributes = convertGenAISpanAttributesToOpenInferenceSpanAttributes(attributes);\n\n // only add processed attributes if conversion was successful\n if (processedAttributes) {\n const threadId = mastraMetadata['threadId'];\n if (threadId) {\n delete mastraMetadata['threadId'];\n processedAttributes[SESSION_ID] = threadId;\n }\n\n // Map mastra.tags to OpenInference native tag.tags convention (tags are only on root spans)\n if (mastraOther['mastra.tags']) {\n processedAttributes[TAG_TAGS] = mastraOther['mastra.tags'];\n delete mastraOther['mastra.tags'];\n }\n\n const userId = mastraMetadata['userId'];\n if (userId) {\n delete mastraMetadata['userId'];\n processedAttributes[USER_ID] = userId;\n }\n\n // Gather custom metadata into OpenInference metadata (flat best-effort)\n if (Object.keys(mastraMetadata).length > 0) {\n try {\n processedAttributes[METADATA] = JSON.stringify(mastraMetadata);\n } catch {\n // best-effort only\n }\n }\n\n const inputMessages =\n attributes[ATTR_GEN_AI_INPUT_MESSAGES] ??\n attributes[ATTR_GEN_AI_TOOL_CALL_ARGUMENTS] ??\n mastraOther[MASTRA_MODEL_STEP_INPUT];\n if (inputMessages) {\n processedAttributes[INPUT_MIME_TYPE] = 'application/json';\n processedAttributes[INPUT_VALUE] = inputMessages;\n }\n const outputMessages =\n attributes[ATTR_GEN_AI_OUTPUT_MESSAGES] ??\n attributes[ATTR_GEN_AI_TOOL_CALL_RESULT] ??\n mastraOther[MASTRA_MODEL_STEP_OUTPUT] ??\n mastraOther[MASTRA_MODEL_CHUNK_OUTPUT];\n if (outputMessages) {\n processedAttributes[OUTPUT_MIME_TYPE] = 'application/json';\n processedAttributes[OUTPUT_VALUE] = outputMessages;\n }\n\n // Map generic Mastra span input/output to OpenInference input/output\n // These are set by Mastra's gen-ai-semantics.ts for non-LLM/tool spans\n // (e.g., mastra.processor_run.input, mastra.workflow_run.input, etc.)\n if (!processedAttributes[INPUT_VALUE]) {\n for (const key of Object.keys(mastraOther)) {\n if (key.endsWith('.input')) {\n processedAttributes[INPUT_MIME_TYPE] = 'application/json';\n processedAttributes[INPUT_VALUE] = mastraOther[key];\n break;\n }\n }\n }\n if (!processedAttributes[OUTPUT_VALUE]) {\n for (const key of Object.keys(mastraOther)) {\n if (key.endsWith('.output')) {\n processedAttributes[OUTPUT_MIME_TYPE] = 'application/json';\n processedAttributes[OUTPUT_VALUE] = mastraOther[key];\n break;\n }\n }\n }\n\n // Convert GenAI usage metrics to OpenInference token count attributes\n const usageMetrics = convertUsageMetricsToOpenInference(attributes);\n Object.assign(processedAttributes, usageMetrics);\n\n mutableSpan.attributes = { ...processedAttributes, ...mastraOther };\n\n // Set span kind based on mastra.span.type for proper trace categorization\n const spanType = mastraOther[MASTRA_SPAN_TYPE];\n if (typeof spanType === 'string') {\n mutableSpan.attributes[SemanticConventions.OPENINFERENCE_SPAN_KIND] =\n SPAN_TYPE_TO_KIND[spanType] ?? OpenInferenceSpanKind.CHAIN;\n }\n }\n\n return mutableSpan;\n });\n\n super.export(processedSpans, resultCallback);\n }\n}\n","import { SEMRESATTRS_PROJECT_NAME } from '@arizeai/openinference-semantic-conventions';\nimport { OtelExporter } from '@mastra/otel-exporter';\nimport type { OtelExporterConfig } from '@mastra/otel-exporter';\n\nimport { OpenInferenceOTLPTraceExporter } from './openInferenceOTLPExporter.js';\n\nconst LOG_PREFIX = '[ArizeExporter]';\n\nexport const ARIZE_AX_ENDPOINT = 'https://otlp.arize.com/v1/traces';\n\nexport type ArizeExporterConfig = Omit<OtelExporterConfig, 'provider'> & {\n /**\n * Required if sending traces to Arize AX\n */\n spaceId?: string;\n /**\n * Required if sending traces to Arize AX, or to any other collector that\n * requires an Authorization header\n */\n apiKey?: string;\n /**\n * Collector endpoint destination for trace exports.\n * Required when sending traces to Phoenix, Phoenix Cloud, or other collectors.\n * Optional when sending traces to Arize AX.\n */\n endpoint?: string;\n /**\n * Optional project name to be added as a resource attribute using\n * OpenInference Semantic Conventions\n */\n projectName?: string;\n /**\n * Optional headers to be added to each OTLP request\n */\n headers?: Record<string, string>;\n};\n\nexport class ArizeExporter extends OtelExporter {\n name = 'arize';\n\n constructor(config: ArizeExporterConfig = {}) {\n // Read configuration from config or environment variables\n // Priority: config > ARIZE_* env vars > PHOENIX_* env vars\n const spaceId = config.spaceId ?? process.env.ARIZE_SPACE_ID;\n const apiKey = config.apiKey ?? process.env.ARIZE_API_KEY ?? process.env.PHOENIX_API_KEY;\n const projectName = config.projectName ?? process.env.ARIZE_PROJECT_NAME ?? process.env.PHOENIX_PROJECT_NAME;\n\n // Determine endpoint: config > PHOENIX_COLLECTOR_ENDPOINT > PHOENIX_ENDPOINT > ARIZE_AX_ENDPOINT (if spaceId is set)\n let endpoint: string | undefined =\n config.endpoint ?? process.env.PHOENIX_COLLECTOR_ENDPOINT ?? process.env.PHOENIX_ENDPOINT;\n\n const headers: Record<string, string> = {\n ...config.headers,\n };\n\n // Validate credentials based on mode\n let disabledReason: string | undefined;\n\n if (spaceId) {\n // Arize AX mode requires an API key\n if (!apiKey) {\n disabledReason =\n `${LOG_PREFIX} API key is required for Arize AX. ` +\n `Set ARIZE_API_KEY environment variable or pass apiKey in config.`;\n } else {\n // arize ax header configuration\n headers['space_id'] = spaceId;\n headers['api_key'] = apiKey;\n endpoint = endpoint || ARIZE_AX_ENDPOINT;\n }\n } else if (apiKey) {\n // standard otel header configuration\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n if (!disabledReason && !endpoint) {\n disabledReason =\n `${LOG_PREFIX} Endpoint is required in configuration. ` +\n `Set PHOENIX_COLLECTOR_ENDPOINT environment variable, or ARIZE_SPACE_ID for Arize AX, or pass endpoint in config.`;\n }\n\n // If disabled, create with minimal config and disable\n if (disabledReason) {\n super({\n ...config,\n provider: {\n custom: {\n endpoint: 'http://disabled',\n headers: {},\n protocol: 'http/protobuf',\n },\n },\n });\n this.setDisabled(disabledReason);\n return;\n }\n\n super({\n exporter: new OpenInferenceOTLPTraceExporter({\n url: endpoint!,\n headers,\n }),\n ...config,\n resourceAttributes: {\n ...(projectName ? { [SEMRESATTRS_PROJECT_NAME]: projectName } : {}),\n ...config.resourceAttributes,\n },\n provider: {\n custom: {\n endpoint: endpoint!,\n headers,\n protocol: 'http/protobuf',\n },\n } satisfies OtelExporterConfig['provider'],\n } satisfies OtelExporterConfig);\n }\n}\n"],"mappings":";;;;;;AAoCA,MAAM,gCAAgC;AACtC,MAAM,uCAAuC;AAC7C,MAAM,2CAA2C;AACjD,MAAM,kCAAkC;AACxC,MAAM,mCAAmC;AAEzC,MAAM,wBAAwB;AAC9B,MAAM,yBAAyB;AAC/B,MAAM,0BAA0B;AAChC,MAAM,2BAA2B;AACjC,MAAM,4BAA4B;AAClC,MAAM,mBAAmB;;;;;;AAOzB,MAAM,oBAA2D;CAE/D,kBAAkB,sBAAsB;CACxC,YAAY,sBAAsB;CAClC,aAAa,sBAAsB;CAEnC,WAAW,sBAAsB;CACjC,eAAe,sBAAsB;CAErC,WAAW,sBAAsB;AACnC;;;;;;;;AASA,SAAS,mCAAmC,YAAsD;CAChG,MAAM,SAA8B,CAAC;CAErC,MAAM,cAAc,WAAW;CAC/B,MAAM,eAAe,WAAW;CAGhC,IAAI,gBAAgB,KAAA,GAClB,OAAO,0BAA0B;CAEnC,IAAI,iBAAiB,KAAA,GACnB,OAAO,8BAA8B;CAIvC,IAAI,gBAAgB,KAAA,KAAa,iBAAiB,KAAA,GAChD,OAAO,yBAAyB,cAAc;CAIhD,MAAM,uBAAuB,WAAW;CACxC,IAAI,yBAAyB,KAAA,GAC3B,OAAO,6CAA6C;CAGtD,MAAM,2BAA2B,WAAW;CAC5C,IAAI,6BAA6B,KAAA,GAC/B,OAAO,8CAA8C;CAIvD,MAAM,kBAAkB,WAAW;CACnC,IAAI,oBAAoB,KAAA,GACtB,OAAO,gDAAgD;CAIzD,MAAM,mBAAmB,WAAW;CACpC,IAAI,qBAAqB,KAAA,GACvB,OAAO,wCAAwC;CAGjD,MAAM,oBAAoB,WAAW;CACrC,IAAI,sBAAsB,KAAA,GACxB,OAAO,4CAA4C;CAGrD,OAAO;AACT;;;;;;;;AASA,SAAS,sBAAsB,YAG7B;CACA,OAAO,OAAO,QAAQ,UAAU,CAAC,CAAC,QAC/B,KAAK,CAAC,KAAK,WAAW;EACrB,IAAI,IAAI,WAAW,qBAAqB,GACtC,IAAI,IAAI,WAAW,sBAAsB,GAAG;GAC1C,MAAM,cAAc,IAAI,MAAM,EAA6B;GAC3D,IAAI,eAAe,eAAe;EACpC,OACE,IAAI,YAAY,OAAO;EAG3B,OAAO;CACT,GACA;EACE,gBAAgB,CAAC;EACjB,aAAa,CAAC;CAChB,CACF;AACF;AAEA,IAAa,iCAAb,cAAoD,kBAAkB;CACpE,OAAO,OAAuB,gBAAgD;EAC5E,MAAM,iBAAiB,MAAM,KAAI,SAAQ;GACvC,MAAM,aAAa,EAAE,GAAI,KAAK,cAAc,CAAC,EAAG;GAChD,MAAM,cAAc;GAEpB,MAAM,EAAE,gBAAgB,gBAAgB,sBAAsB,UAAU;GACxE,MAAM,sBAAsB,wDAAwD,UAAU;GAG9F,IAAI,qBAAqB;IACvB,MAAM,WAAW,eAAe;IAChC,IAAI,UAAU;KACZ,OAAO,eAAe;KACtB,oBAAoB,cAAc;IACpC;IAGA,IAAI,YAAY,gBAAgB;KAC9B,oBAAoB,YAAY,YAAY;KAC5C,OAAO,YAAY;IACrB;IAEA,MAAM,SAAS,eAAe;IAC9B,IAAI,QAAQ;KACV,OAAO,eAAe;KACtB,oBAAoB,WAAW;IACjC;IAGA,IAAI,OAAO,KAAK,cAAc,CAAC,CAAC,SAAS,GACvC,IAAI;KACF,oBAAoB,YAAY,KAAK,UAAU,cAAc;IAC/D,QAAQ,CAER;IAGF,MAAM,gBACJ,WAAW,+BACX,WAAW,oCACX,YAAY;IACd,IAAI,eAAe;KACjB,oBAAoB,mBAAmB;KACvC,oBAAoB,eAAe;IACrC;IACA,MAAM,iBACJ,WAAW,gCACX,WAAW,iCACX,YAAY,6BACZ,YAAY;IACd,IAAI,gBAAgB;KAClB,oBAAoB,oBAAoB;KACxC,oBAAoB,gBAAgB;IACtC;IAKA,IAAI,CAAC,oBAAoB,cAClB;UAAA,MAAM,OAAO,OAAO,KAAK,WAAW,GACvC,IAAI,IAAI,SAAS,QAAQ,GAAG;MAC1B,oBAAoB,mBAAmB;MACvC,oBAAoB,eAAe,YAAY;MAC/C;KACF;;IAGJ,IAAI,CAAC,oBAAoB,eAClB;UAAA,MAAM,OAAO,OAAO,KAAK,WAAW,GACvC,IAAI,IAAI,SAAS,SAAS,GAAG;MAC3B,oBAAoB,oBAAoB;MACxC,oBAAoB,gBAAgB,YAAY;MAChD;KACF;;IAKJ,MAAM,eAAe,mCAAmC,UAAU;IAClE,OAAO,OAAO,qBAAqB,YAAY;IAE/C,YAAY,aAAa;KAAE,GAAG;KAAqB,GAAG;IAAY;IAGlE,MAAM,WAAW,YAAY;IAC7B,IAAI,OAAO,aAAa,UACtB,YAAY,WAAW,oBAAoB,2BACzC,kBAAkB,aAAa,sBAAsB;GAE3D;GAEA,OAAO;EACT,CAAC;EAED,MAAM,OAAO,gBAAgB,cAAc;CAC7C;AACF;;;ACpPA,MAAM,aAAa;AAEnB,MAAa,oBAAoB;AA6BjC,IAAa,gBAAb,cAAmC,aAAa;CAC9C,OAAO;CAEP,YAAY,SAA8B,CAAC,GAAG;EAG5C,MAAM,UAAU,OAAO,WAAW,QAAQ,IAAI;EAC9C,MAAM,SAAS,OAAO,UAAU,QAAQ,IAAI,iBAAiB,QAAQ,IAAI;EACzE,MAAM,cAAc,OAAO,eAAe,QAAQ,IAAI,sBAAsB,QAAQ,IAAI;EAGxF,IAAI,WACF,OAAO,YAAY,QAAQ,IAAI,8BAA8B,QAAQ,IAAI;EAE3E,MAAM,UAAkC,EACtC,GAAG,OAAO,QACZ;EAGA,IAAI;EAEJ,IAAI,SAEF,IAAI,CAAC,QACH,iBACE,GAAG,WAAW;OAEX;GAEL,QAAQ,cAAc;GACtB,QAAQ,aAAa;GACrB,WAAW,YAAA;EACb;OACK,IAAI,QAET,QAAQ,mBAAmB,UAAU;EAGvC,IAAI,CAAC,kBAAkB,CAAC,UACtB,iBACE,GAAG,WAAW;EAKlB,IAAI,gBAAgB;GAClB,MAAM;IACJ,GAAG;IACH,UAAU,EACR,QAAQ;KACN,UAAU;KACV,SAAS,CAAC;KACV,UAAU;IACZ,EACF;GACF,CAAC;GACD,KAAK,YAAY,cAAc;GAC/B;EACF;EAEA,MAAM;GACJ,UAAU,IAAI,+BAA+B;IAC3C,KAAK;IACL;GACF,CAAC;GACD,GAAG;GACH,oBAAoB;IAClB,GAAI,cAAc,GAAG,2BAA2B,YAAY,IAAI,CAAC;IACjE,GAAG,OAAO;GACZ;GACA,UAAU,EACR,QAAQ;IACI;IACV;IACA,UAAU;GACZ,EACF;EACF,CAA8B;CAChC;AACF"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/openInferenceOTLPExporter.ts","../src/tracing.ts"],"sourcesContent":["import { convertGenAISpanAttributesToOpenInferenceSpanAttributes } from '@arizeai/openinference-genai';\nimport type { Mutable } from '@arizeai/openinference-genai/types';\nimport {\n INPUT_MIME_TYPE,\n INPUT_VALUE,\n LLM_TOKEN_COUNT_COMPLETION,\n LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO,\n LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING,\n LLM_TOKEN_COUNT_PROMPT,\n LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO,\n LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ,\n LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE,\n LLM_TOKEN_COUNT_TOTAL,\n METADATA,\n OpenInferenceSpanKind,\n OUTPUT_MIME_TYPE,\n OUTPUT_VALUE,\n SemanticConventions,\n SESSION_ID,\n TAG_TAGS,\n USER_ID,\n} from '@arizeai/openinference-semantic-conventions';\nimport type { ExportResult } from '@opentelemetry/core';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto';\nimport type { ReadableSpan } from '@opentelemetry/sdk-trace-base';\nimport {\n ATTR_GEN_AI_INPUT_MESSAGES,\n ATTR_GEN_AI_OPERATION_NAME,\n ATTR_GEN_AI_OUTPUT_MESSAGES,\n ATTR_GEN_AI_USAGE_INPUT_TOKENS,\n ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,\n ATTR_GEN_AI_TOOL_CALL_ARGUMENTS,\n ATTR_GEN_AI_TOOL_CALL_RESULT,\n} from '@opentelemetry/semantic-conventions/incubating';\n\n// GenAI usage attribute keys (not all are in @opentelemetry/semantic-conventions yet)\n// @see https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/\nconst GEN_AI_USAGE_REASONING_TOKENS = 'gen_ai.usage.reasoning_tokens';\nconst GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS = 'gen_ai.usage.cache_read.input_tokens';\nconst GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS = 'gen_ai.usage.cache_creation.input_tokens';\nconst GEN_AI_USAGE_AUDIO_INPUT_TOKENS = 'gen_ai.usage.audio_input_tokens';\nconst GEN_AI_USAGE_AUDIO_OUTPUT_TOKENS = 'gen_ai.usage.audio_output_tokens';\n\nconst MASTRA_GENERAL_PREFIX = 'mastra.';\nconst MASTRA_METADATA_PREFIX = 'mastra.metadata.';\nconst MASTRA_MODEL_STEP_INPUT = 'mastra.model_step.input';\nconst MASTRA_MODEL_STEP_OUTPUT = 'mastra.model_step.output';\nconst MASTRA_MODEL_CHUNK_OUTPUT = 'mastra.model_chunk.output';\nconst MASTRA_SPAN_TYPE = 'mastra.span.type';\n\n/**\n * Maps Mastra span types to OpenInference span kinds for proper trace categorization.\n *\n * Only non-CHAIN types are mapped here - all other span types default to CHAIN.\n */\nconst SPAN_TYPE_TO_KIND: Record<string, OpenInferenceSpanKind> = {\n // The model call itself (gen_ai.operation.name === 'chat') is mapped to LLM\n // below; the generation loop and its steps around it default to CHAIN.\n model_chunk: OpenInferenceSpanKind.LLM,\n // Tool spans -> TOOL\n tool_call: OpenInferenceSpanKind.TOOL,\n mcp_tool_call: OpenInferenceSpanKind.TOOL,\n // Agent spans -> AGENT\n agent_run: OpenInferenceSpanKind.AGENT,\n};\n\n/**\n * Converts GenAI usage metrics to OpenInference LLM token count attributes.\n * Maps from OTEL GenAI semantic conventions to OpenInference semantic conventions.\n *\n * @param attributes - The span attributes containing GenAI usage metrics\n * @returns OpenInference token count attributes\n */\nfunction convertUsageMetricsToOpenInference(attributes: Record<string, any>): Record<string, any> {\n const result: Record<string, any> = {};\n\n const inputTokens = attributes[ATTR_GEN_AI_USAGE_INPUT_TOKENS];\n const outputTokens = attributes[ATTR_GEN_AI_USAGE_OUTPUT_TOKENS];\n\n // Core token counts\n if (inputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT] = inputTokens;\n }\n if (outputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_COMPLETION] = outputTokens;\n }\n\n // Total tokens (compute if we have both input and output)\n if (inputTokens !== undefined && outputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_TOTAL] = inputTokens + outputTokens;\n }\n\n // Cache tokens (prompt details)\n const cacheReadInputTokens = attributes[GEN_AI_USAGE_CACHE_READ_INPUT_TOKENS];\n if (cacheReadInputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ] = cacheReadInputTokens;\n }\n\n const cacheCreationInputTokens = attributes[GEN_AI_USAGE_CACHE_CREATION_INPUT_TOKENS];\n if (cacheCreationInputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE] = cacheCreationInputTokens;\n }\n\n // Reasoning tokens (completion details)\n const reasoningTokens = attributes[GEN_AI_USAGE_REASONING_TOKENS];\n if (reasoningTokens !== undefined) {\n result[LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING] = reasoningTokens;\n }\n\n // Audio tokens\n const audioInputTokens = attributes[GEN_AI_USAGE_AUDIO_INPUT_TOKENS];\n if (audioInputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO] = audioInputTokens;\n }\n\n const audioOutputTokens = attributes[GEN_AI_USAGE_AUDIO_OUTPUT_TOKENS];\n if (audioOutputTokens !== undefined) {\n result[LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO] = audioOutputTokens;\n }\n\n return result;\n}\n\n/**\n * Splits Mastra span attributes into two groups:\n * - `metadata`: keys starting with \"mastra.metadata.\" (prefix removed)\n * - `other`: all remaining keys starting with \"mastra.\"\n *\n * Any attributes not starting with \"mastra.\" are ignored entirely.\n */\nfunction splitMastraAttributes(attributes: Record<string, any>): {\n mastraMetadata: Record<string, any>;\n mastraOther: Record<string, any>;\n} {\n return Object.entries(attributes).reduce(\n (acc, [key, value]) => {\n if (key.startsWith(MASTRA_GENERAL_PREFIX)) {\n if (key.startsWith(MASTRA_METADATA_PREFIX)) {\n const strippedKey = key.slice(MASTRA_METADATA_PREFIX.length);\n acc.mastraMetadata[strippedKey] = value;\n } else {\n acc.mastraOther[key] = value;\n }\n }\n return acc;\n },\n {\n mastraMetadata: {} as Record<string, any>,\n mastraOther: {} as Record<string, any>,\n },\n );\n}\n\nexport class OpenInferenceOTLPTraceExporter extends OTLPTraceExporter {\n export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void) {\n const processedSpans = spans.map(span => {\n const attributes = { ...(span.attributes ?? {}) };\n const mutableSpan = span as Mutable<ReadableSpan>;\n\n const { mastraMetadata, mastraOther } = splitMastraAttributes(attributes);\n const processedAttributes = convertGenAISpanAttributesToOpenInferenceSpanAttributes(attributes);\n\n // only add processed attributes if conversion was successful\n if (processedAttributes) {\n const threadId = mastraMetadata['threadId'];\n if (threadId) {\n delete mastraMetadata['threadId'];\n processedAttributes[SESSION_ID] = threadId;\n }\n\n // Map mastra.tags to OpenInference native tag.tags convention (tags are only on root spans)\n if (mastraOther['mastra.tags']) {\n processedAttributes[TAG_TAGS] = mastraOther['mastra.tags'];\n delete mastraOther['mastra.tags'];\n }\n\n const userId = mastraMetadata['userId'];\n if (userId) {\n delete mastraMetadata['userId'];\n processedAttributes[USER_ID] = userId;\n }\n\n // Gather custom metadata into OpenInference metadata (flat best-effort)\n if (Object.keys(mastraMetadata).length > 0) {\n try {\n processedAttributes[METADATA] = JSON.stringify(mastraMetadata);\n } catch {\n // best-effort only\n }\n }\n\n const inputMessages =\n attributes[ATTR_GEN_AI_INPUT_MESSAGES] ??\n attributes[ATTR_GEN_AI_TOOL_CALL_ARGUMENTS] ??\n mastraOther[MASTRA_MODEL_STEP_INPUT];\n if (inputMessages) {\n processedAttributes[INPUT_MIME_TYPE] = 'application/json';\n processedAttributes[INPUT_VALUE] = inputMessages;\n }\n const outputMessages =\n attributes[ATTR_GEN_AI_OUTPUT_MESSAGES] ??\n attributes[ATTR_GEN_AI_TOOL_CALL_RESULT] ??\n mastraOther[MASTRA_MODEL_STEP_OUTPUT] ??\n mastraOther[MASTRA_MODEL_CHUNK_OUTPUT];\n if (outputMessages) {\n processedAttributes[OUTPUT_MIME_TYPE] = 'application/json';\n processedAttributes[OUTPUT_VALUE] = outputMessages;\n }\n\n // Map generic Mastra span input/output to OpenInference input/output\n // These are set by Mastra's gen-ai-semantics.ts for non-LLM/tool spans\n // (e.g., mastra.processor_run.input, mastra.workflow_run.input, etc.)\n if (!processedAttributes[INPUT_VALUE]) {\n for (const key of Object.keys(mastraOther)) {\n if (key.endsWith('.input')) {\n processedAttributes[INPUT_MIME_TYPE] = 'application/json';\n processedAttributes[INPUT_VALUE] = mastraOther[key];\n break;\n }\n }\n }\n if (!processedAttributes[OUTPUT_VALUE]) {\n for (const key of Object.keys(mastraOther)) {\n if (key.endsWith('.output')) {\n processedAttributes[OUTPUT_MIME_TYPE] = 'application/json';\n processedAttributes[OUTPUT_VALUE] = mastraOther[key];\n break;\n }\n }\n }\n\n // Convert GenAI usage metrics to OpenInference token count attributes\n const usageMetrics = convertUsageMetricsToOpenInference(attributes);\n Object.assign(processedAttributes, usageMetrics);\n\n mutableSpan.attributes = { ...processedAttributes, ...mastraOther };\n\n // Set span kind based on mastra.span.type for proper trace categorization\n const spanType = mastraOther[MASTRA_SPAN_TYPE];\n if (typeof spanType === 'string') {\n mutableSpan.attributes[SemanticConventions.OPENINFERENCE_SPAN_KIND] =\n attributes[ATTR_GEN_AI_OPERATION_NAME] === 'chat'\n ? OpenInferenceSpanKind.LLM\n : (SPAN_TYPE_TO_KIND[spanType] ?? OpenInferenceSpanKind.CHAIN);\n }\n }\n\n return mutableSpan;\n });\n\n super.export(processedSpans, resultCallback);\n }\n}\n","import { SEMRESATTRS_PROJECT_NAME } from '@arizeai/openinference-semantic-conventions';\nimport { OtelExporter } from '@mastra/otel-exporter';\nimport type { OtelExporterConfig } from '@mastra/otel-exporter';\n\nimport { OpenInferenceOTLPTraceExporter } from './openInferenceOTLPExporter.js';\n\nconst LOG_PREFIX = '[ArizeExporter]';\n\nexport const ARIZE_AX_ENDPOINT = 'https://otlp.arize.com/v1/traces';\n\nexport type ArizeExporterConfig = Omit<OtelExporterConfig, 'provider'> & {\n /**\n * Required if sending traces to Arize AX\n */\n spaceId?: string;\n /**\n * Required if sending traces to Arize AX, or to any other collector that\n * requires an Authorization header\n */\n apiKey?: string;\n /**\n * Collector endpoint destination for trace exports.\n * Required when sending traces to Phoenix, Phoenix Cloud, or other collectors.\n * Optional when sending traces to Arize AX.\n */\n endpoint?: string;\n /**\n * Optional project name to be added as a resource attribute using\n * OpenInference Semantic Conventions\n */\n projectName?: string;\n /**\n * Optional headers to be added to each OTLP request\n */\n headers?: Record<string, string>;\n};\n\nexport class ArizeExporter extends OtelExporter {\n name = 'arize';\n\n constructor(config: ArizeExporterConfig = {}) {\n // Read configuration from config or environment variables\n // Priority: config > ARIZE_* env vars > PHOENIX_* env vars\n const spaceId = config.spaceId ?? process.env.ARIZE_SPACE_ID;\n const apiKey = config.apiKey ?? process.env.ARIZE_API_KEY ?? process.env.PHOENIX_API_KEY;\n const projectName = config.projectName ?? process.env.ARIZE_PROJECT_NAME ?? process.env.PHOENIX_PROJECT_NAME;\n\n // Determine endpoint: config > PHOENIX_COLLECTOR_ENDPOINT > PHOENIX_ENDPOINT > ARIZE_AX_ENDPOINT (if spaceId is set)\n let endpoint: string | undefined =\n config.endpoint ?? process.env.PHOENIX_COLLECTOR_ENDPOINT ?? process.env.PHOENIX_ENDPOINT;\n\n const headers: Record<string, string> = {\n ...config.headers,\n };\n\n // Validate credentials based on mode\n let disabledReason: string | undefined;\n\n if (spaceId) {\n // Arize AX mode requires an API key\n if (!apiKey) {\n disabledReason =\n `${LOG_PREFIX} API key is required for Arize AX. ` +\n `Set ARIZE_API_KEY environment variable or pass apiKey in config.`;\n } else {\n // arize ax header configuration\n headers['space_id'] = spaceId;\n headers['api_key'] = apiKey;\n endpoint = endpoint || ARIZE_AX_ENDPOINT;\n }\n } else if (apiKey) {\n // standard otel header configuration\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n if (!disabledReason && !endpoint) {\n disabledReason =\n `${LOG_PREFIX} Endpoint is required in configuration. ` +\n `Set PHOENIX_COLLECTOR_ENDPOINT environment variable, or ARIZE_SPACE_ID for Arize AX, or pass endpoint in config.`;\n }\n\n // If disabled, create with minimal config and disable\n if (disabledReason) {\n super({\n ...config,\n provider: {\n custom: {\n endpoint: 'http://disabled',\n headers: {},\n protocol: 'http/protobuf',\n },\n },\n });\n this.setDisabled(disabledReason);\n return;\n }\n\n super({\n exporter: new OpenInferenceOTLPTraceExporter({\n url: endpoint!,\n headers,\n }),\n ...config,\n resourceAttributes: {\n ...(projectName ? { [SEMRESATTRS_PROJECT_NAME]: projectName } : {}),\n ...config.resourceAttributes,\n },\n provider: {\n custom: {\n endpoint: endpoint!,\n headers,\n protocol: 'http/protobuf',\n },\n } satisfies OtelExporterConfig['provider'],\n } satisfies OtelExporterConfig);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openInferenceOTLPExporter.d.ts","sourceRoot":"","sources":["../src/openInferenceOTLPExporter.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAiIlE,qBAAa,8BAA+B,SAAQ,iBAAiB;IACnE,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"openInferenceOTLPExporter.d.ts","sourceRoot":"","sources":["../src/openInferenceOTLPExporter.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAiIlE,qBAAa,8BAA+B,SAAQ,iBAAiB;IACnE,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,QAiG3E;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/arize",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.17-alpha.0",
|
|
4
4
|
"description": "Arize observability provider for Mastra - includes tracing and future observability features",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"@opentelemetry/resources": "^2.10.0",
|
|
31
31
|
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
|
32
32
|
"@opentelemetry/semantic-conventions": "^1.43.0",
|
|
33
|
-
"@mastra/otel-exporter": "1.
|
|
33
|
+
"@mastra/otel-exporter": "1.4.0-alpha.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "22.20.1",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"tsdown": "0.22.9",
|
|
41
41
|
"typescript": "^7.0.2",
|
|
42
42
|
"vitest": "4.1.10",
|
|
43
|
-
"@internal/lint": "0.0.133",
|
|
44
43
|
"@internal/types-builder": "0.0.108",
|
|
45
|
-
"@
|
|
44
|
+
"@internal/lint": "0.0.133",
|
|
45
|
+
"@mastra/core": "1.68.0-alpha.0"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
48
|
"@mastra/core": ">=1.16.0-0 <2.0.0-0"
|