@latitude-data/telemetry 3.0.0-alpha.1 → 3.0.0-alpha.3

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 CHANGED
@@ -92,7 +92,7 @@ var import_context_async_hooks = require("@opentelemetry/context-async-hooks");
92
92
  var import_core = require("@opentelemetry/core");
93
93
  var import_resources = require("@opentelemetry/resources");
94
94
  var import_sdk_trace_node2 = require("@opentelemetry/sdk-trace-node");
95
- var import_semantic_conventions = require("@opentelemetry/semantic-conventions");
95
+ var import_semantic_conventions2 = require("@opentelemetry/semantic-conventions");
96
96
 
97
97
  // src/sdk/instrumentations.ts
98
98
  var import_instrumentation = require("@opentelemetry/instrumentation");
@@ -160,6 +160,7 @@ async function registerLatitudeInstrumentations(options) {
160
160
  // src/sdk/processor.ts
161
161
  var import_exporter_trace_otlp_http = require("@opentelemetry/exporter-trace-otlp-http");
162
162
  var import_sdk_trace_node = require("@opentelemetry/sdk-trace-node");
163
+ var import_semantic_conventions = require("@opentelemetry/semantic-conventions");
163
164
 
164
165
  // src/constants/attributes.ts
165
166
  var ATTRIBUTES = {
@@ -286,7 +287,7 @@ function attributeKeys(span) {
286
287
  return Object.keys(attrs);
287
288
  }
288
289
  function instrumentationScopeName(span) {
289
- return span.instrumentationLibrary?.name ?? "";
290
+ return span.instrumentationScope?.name ?? "";
290
291
  }
291
292
  function isGenAiOrLlmAttributeSpan(span) {
292
293
  for (const key of attributeKeys(span)) {
@@ -378,6 +379,7 @@ var RedactThenExportSpanProcessor = class {
378
379
  // src/sdk/processor.ts
379
380
  var LatitudeSpanProcessor = class {
380
381
  tail;
382
+ serviceName;
381
383
  constructor(apiKey, projectSlug, options) {
382
384
  if (!apiKey || apiKey.trim() === "") {
383
385
  throw new Error("[Latitude] apiKey is required and cannot be empty");
@@ -403,8 +405,13 @@ var LatitudeSpanProcessor = class {
403
405
  });
404
406
  const redactThenExport = new RedactThenExportSpanProcessor(redact, batchOrSimple);
405
407
  this.tail = new ExportFilterSpanProcessor(shouldExport, redactThenExport);
408
+ const rawServiceName = options?.serviceName?.trim();
409
+ this.serviceName = rawServiceName === "" ? void 0 : rawServiceName;
406
410
  }
407
411
  onStart(span, parentContext) {
412
+ if (this.serviceName !== void 0) {
413
+ span.setAttribute(import_semantic_conventions.ATTR_SERVICE_NAME, this.serviceName);
414
+ }
408
415
  const latitudeData = getLatitudeContext(parentContext);
409
416
  if (latitudeData) {
410
417
  if (latitudeData.name) {
@@ -457,9 +464,10 @@ function initLatitude(options) {
457
464
  });
458
465
  import_api2.context.setGlobalContextManager(contextManager);
459
466
  import_api2.propagation.setGlobalPropagator(propagator);
467
+ const resourceServiceName = typeof processorOptions.serviceName === "string" && processorOptions.serviceName.trim() !== "" ? processorOptions.serviceName.trim() : SERVICE_NAME;
460
468
  const provider = new import_sdk_trace_node2.NodeTracerProvider({
461
- resource: new import_resources.Resource({
462
- [import_semantic_conventions.ATTR_SERVICE_NAME]: SERVICE_NAME
469
+ resource: (0, import_resources.resourceFromAttributes)({
470
+ [import_semantic_conventions2.ATTR_SERVICE_NAME]: resourceServiceName
463
471
  }),
464
472
  spanProcessors: [new LatitudeSpanProcessor(apiKey, projectSlug, processorOptions)]
465
473
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/sdk/context.ts","../src/sdk/init.ts","../src/sdk/instrumentations.ts","../src/sdk/processor.ts","../src/constants/attributes.ts","../src/constants/scope.ts","../src/env/env.ts","../src/sdk/redact.ts","../src/sdk/span-filter.ts"],"sourcesContent":["export * from \"./sdk/index.ts\"\n","import { type Context, context, createContextKey, trace } from \"@opentelemetry/api\"\nimport type { ContextOptions } from \"./types.ts\"\n\nexport const LATITUDE_CONTEXT_KEY = createContextKey(\"latitude-internal-context\")\nconst CAPTURE_TRACER_NAME = \"so.latitude.instrumentation.capture\"\n\ntype LatitudeContextData = {\n name: string | undefined\n tags: string[] | undefined\n metadata: Record<string, unknown> | undefined\n sessionId: string | undefined\n userId: string | undefined\n}\n\nexport function getLatitudeContext(ctx: Context): LatitudeContextData | undefined {\n return ctx.getValue(LATITUDE_CONTEXT_KEY) as LatitudeContextData | undefined\n}\n\nfunction mergeArrays<T>(a: T[] | undefined, b: T[] | undefined): T[] | undefined {\n if (!a && !b) return undefined\n if (!a) return b\n if (!b) return a\n return [...new Set([...a, ...b])]\n}\n\nexport function capture<T>(name: string, fn: () => T | Promise<T>, options: ContextOptions = {}): T | Promise<T> {\n const currentContext = context.active()\n const existingData = getLatitudeContext(currentContext)\n\n const mergedData: LatitudeContextData = {\n name: options.name ?? name,\n tags: mergeArrays(existingData?.tags, options.tags),\n metadata: { ...existingData?.metadata, ...options.metadata },\n sessionId: options.sessionId ?? existingData?.sessionId,\n userId: options.userId ?? existingData?.userId,\n }\n\n const newContext = currentContext.setValue(LATITUDE_CONTEXT_KEY, mergedData)\n const existingSpan = trace.getSpan(currentContext)\n\n if (existingSpan) {\n return context.with(newContext, fn)\n }\n\n const tracer = trace.getTracer(CAPTURE_TRACER_NAME)\n\n return tracer.startActiveSpan(name, { attributes: { \"latitude.capture.root\": true } }, newContext, (span) => {\n let result: T | Promise<T>\n try {\n result = fn()\n } catch (error) {\n span.recordException(error as Error)\n span.end()\n throw error\n }\n\n if (result instanceof Promise) {\n return result\n .catch((error) => {\n span.recordException(error as Error)\n throw error\n })\n .finally(() => {\n span.end()\n }) as T | Promise<T>\n }\n\n span.end()\n return result\n })\n}\n","import { context, propagation } from \"@opentelemetry/api\"\nimport { AsyncLocalStorageContextManager } from \"@opentelemetry/context-async-hooks\"\nimport { CompositePropagator, W3CBaggagePropagator, W3CTraceContextPropagator } from \"@opentelemetry/core\"\nimport { Resource } from \"@opentelemetry/resources\"\nimport { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\"\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\"\nimport { registerLatitudeInstrumentations } from \"./instrumentations.ts\"\nimport { LatitudeSpanProcessor } from \"./processor.ts\"\nimport type { InitLatitudeOptions } from \"./types.ts\"\n\nconst SERVICE_NAME = process.env.npm_package_name || \"unknown\"\n\n/** Module-level flag to prevent duplicate signal handler registration on repeated initLatitude calls */\nlet shutdownHandlersRegistered = false\n\nexport function initLatitude(options: InitLatitudeOptions): {\n provider: NodeTracerProvider\n flush: () => Promise<void>\n shutdown: () => Promise<void>\n ready: Promise<void>\n} {\n const { apiKey, projectSlug, instrumentations = [], ...processorOptions } = options\n\n if (!apiKey || apiKey.trim() === \"\") {\n throw new Error(\"[Latitude] apiKey is required and cannot be empty\")\n }\n if (!projectSlug || projectSlug.trim() === \"\") {\n throw new Error(\"[Latitude] projectSlug is required and cannot be empty\")\n }\n\n const contextManager = new AsyncLocalStorageContextManager()\n contextManager.enable()\n\n const propagator = new CompositePropagator({\n propagators: [new W3CTraceContextPropagator(), new W3CBaggagePropagator()],\n })\n\n context.setGlobalContextManager(contextManager)\n propagation.setGlobalPropagator(propagator)\n\n const provider = new NodeTracerProvider({\n resource: new Resource({\n [ATTR_SERVICE_NAME]: SERVICE_NAME,\n }),\n spanProcessors: [new LatitudeSpanProcessor(apiKey, projectSlug, processorOptions)],\n })\n\n provider.register()\n\n const ready = registerLatitudeInstrumentations({\n instrumentations,\n tracerProvider: provider,\n }).catch((err) => {\n console.warn(\"[Latitude] Failed to register instrumentations:\", err)\n })\n\n const shutdown = async (): Promise<void> => {\n await provider.shutdown()\n }\n\n const flush = async (): Promise<void> => {\n await provider.forceFlush()\n }\n\n const handleShutdown = async () => {\n try {\n await shutdown()\n } catch (err) {\n console.error(\"Error during Latitude Telemetry shutdown:\", err)\n }\n }\n\n if (!shutdownHandlersRegistered) {\n process.once(\"SIGTERM\", handleShutdown)\n process.once(\"SIGINT\", handleShutdown)\n shutdownHandlersRegistered = true\n }\n\n return {\n provider,\n flush,\n shutdown,\n ready,\n }\n}\n","import type { TracerProvider } from \"@opentelemetry/api\"\nimport { type Instrumentation, registerInstrumentations } from \"@opentelemetry/instrumentation\"\nimport { AnthropicInstrumentation } from \"@traceloop/instrumentation-anthropic\"\nimport { BedrockInstrumentation } from \"@traceloop/instrumentation-bedrock\"\nimport { CohereInstrumentation } from \"@traceloop/instrumentation-cohere\"\nimport { LangChainInstrumentation } from \"@traceloop/instrumentation-langchain\"\nimport { LlamaIndexInstrumentation } from \"@traceloop/instrumentation-llamaindex\"\nimport { OpenAIInstrumentation } from \"@traceloop/instrumentation-openai\"\nimport { TogetherInstrumentation } from \"@traceloop/instrumentation-together\"\nimport { AIPlatformInstrumentation, VertexAIInstrumentation } from \"@traceloop/instrumentation-vertexai\"\n\n/**\n * Supported LLM instrumentation types.\n * Use these string identifiers to enable auto-instrumentation.\n */\nexport type InstrumentationType =\n | \"openai\"\n | \"anthropic\"\n | \"bedrock\"\n | \"cohere\"\n | \"langchain\"\n | \"llamaindex\"\n | \"togetherai\"\n | \"vertexai\"\n | \"aiplatform\"\n\n/**\n * Minimal interface for LLM instrumentation instances.\n * Extends OpenTelemetry's Instrumentation interface.\n */\ninterface LlmInstrumentation extends Instrumentation {\n manuallyInstrument?(module: unknown): void\n}\n\n/**\n * Options for creating LLM instrumentations.\n */\ninterface CreateInstrumentationsOptions {\n /** List of instrumentation types to enable. */\n instrumentations: InstrumentationType[]\n /**\n * Optional module references for auto-instrumentation.\n * If not provided, the instrumentation will attempt to require the module.\n * Used for Traceloop-based instrumentations.\n */\n modules?: Partial<Record<InstrumentationType, unknown>>\n /**\n * Per-instrumentation token enrichment settings.\n * @default { openai: true }\n */\n enrichTokens?: Partial<Record<InstrumentationType, boolean>>\n}\n\ninterface InstrumentationConfig {\n ctor: new (config?: Record<string, unknown>) => LlmInstrumentation\n moduleName: string\n defaultEnrichTokens?: boolean\n}\n\nconst INSTRUMENTATION_MAP: Record<InstrumentationType, InstrumentationConfig> = {\n openai: { ctor: OpenAIInstrumentation, moduleName: \"openai\", defaultEnrichTokens: true },\n anthropic: { ctor: AnthropicInstrumentation, moduleName: \"@anthropic-ai/sdk\" },\n bedrock: { ctor: BedrockInstrumentation, moduleName: \"@aws-sdk/client-bedrock-runtime\" },\n cohere: { ctor: CohereInstrumentation, moduleName: \"cohere-ai\" },\n langchain: { ctor: LangChainInstrumentation, moduleName: \"langchain\" },\n llamaindex: { ctor: LlamaIndexInstrumentation, moduleName: \"llamaindex\" },\n togetherai: { ctor: TogetherInstrumentation, moduleName: \"together-ai\", defaultEnrichTokens: false },\n vertexai: { ctor: VertexAIInstrumentation, moduleName: \"@google-cloud/vertexai\" },\n aiplatform: { ctor: AIPlatformInstrumentation, moduleName: \"@google-cloud/aiplatform\" },\n}\n\n/**\n * Internal function to create LLM instrumentation instances.\n * Not exported publicly - use registerLatitudeInstrumentations instead.\n */\nasync function createLatitudeInstrumentations(options: CreateInstrumentationsOptions): Promise<LlmInstrumentation[]> {\n const result: LlmInstrumentation[] = []\n\n for (const type of options.instrumentations) {\n const config = INSTRUMENTATION_MAP[type]\n if (!config) {\n console.warn(`[Latitude] Unknown instrumentation type: ${type}`)\n continue\n }\n\n const enrichTokens = options.enrichTokens?.[type] ?? config.defaultEnrichTokens\n const inst = new config.ctor(enrichTokens !== undefined ? { enrichTokens } : undefined)\n\n // Get module from explicit options or try to auto-require\n const moduleRef = options.modules?.[type] ?? (await tryRequire(config.moduleName))\n if (!moduleRef) {\n console.warn(\n `[Latitude] Module not found for ${type}: ${config.moduleName}. Install it or pass it explicitly in 'modules'.`,\n )\n continue\n }\n inst.manuallyInstrument?.(moduleRef)\n\n result.push(inst)\n }\n\n return result\n}\n\nasync function tryRequire(moduleName: string): Promise<unknown | undefined> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require(moduleName)\n } catch {\n // Fallback to dynamic import for ESM environments\n try {\n const mod = await import(moduleName)\n return mod.default ?? mod\n } catch {\n return undefined\n }\n }\n}\n\n/**\n * Registers LLM instrumentations with the global OpenTelemetry instrumentation registry.\n *\n * This is a convenience wrapper around `createLatitudeInstrumentations` and\n * `@opentelemetry/instrumentation`'s `registerInstrumentations`.\n *\n * @example\n * ```typescript\n * import { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\"\n * import { registerLatitudeInstrumentations, LatitudeSpanProcessor } from \"@latitude-data/telemetry\"\n *\n * const provider = new NodeTracerProvider({\n * spanProcessors: [new LatitudeSpanProcessor(apiKey, projectSlug)],\n * })\n *\n * await registerLatitudeInstrumentations({\n * instrumentations: [\"openai\", \"anthropic\"],\n * tracerProvider: provider,\n * })\n *\n * provider.register()\n * ```\n */\nexport async function registerLatitudeInstrumentations(\n options: CreateInstrumentationsOptions & { tracerProvider: TracerProvider },\n): Promise<void> {\n const instrumentations = await createLatitudeInstrumentations(options)\n registerInstrumentations({\n instrumentations,\n tracerProvider: options.tracerProvider,\n })\n}\n","import type { Context } from \"@opentelemetry/api\"\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\"\nimport {\n BatchSpanProcessor,\n type ReadableSpan,\n SimpleSpanProcessor,\n type Span,\n type SpanProcessor,\n} from \"@opentelemetry/sdk-trace-node\"\nimport { ATTRIBUTES } from \"../constants/index.ts\"\nimport { env } from \"../env/index.ts\"\nimport { getLatitudeContext } from \"./context.ts\"\nimport { DEFAULT_REDACT_SPAN_PROCESSOR, RedactSpanProcessor } from \"./redact.ts\"\nimport {\n buildShouldExportSpanFromFields,\n ExportFilterSpanProcessor,\n RedactThenExportSpanProcessor,\n} from \"./span-filter.ts\"\nimport type { LatitudeSpanProcessorOptions } from \"./types.ts\"\n\nexport class LatitudeSpanProcessor implements SpanProcessor {\n private readonly tail: SpanProcessor\n\n constructor(apiKey: string, projectSlug: string, options?: LatitudeSpanProcessorOptions) {\n if (!apiKey || apiKey.trim() === \"\") {\n throw new Error(\"[Latitude] apiKey is required and cannot be empty\")\n }\n if (!projectSlug || projectSlug.trim() === \"\") {\n throw new Error(\"[Latitude] projectSlug is required and cannot be empty\")\n }\n\n const exporter =\n options?.exporter ??\n new OTLPTraceExporter({\n url: `${env.EXPORTER_URL}/v1/traces`,\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n \"X-Latitude-Project\": projectSlug,\n },\n timeoutMillis: 30_000,\n })\n\n const redact = options?.disableRedact\n ? null\n : options?.redact\n ? new RedactSpanProcessor(options.redact)\n : DEFAULT_REDACT_SPAN_PROCESSOR()\n\n const batchOrSimple = options?.disableBatch ? new SimpleSpanProcessor(exporter) : new BatchSpanProcessor(exporter)\n\n const shouldExport = buildShouldExportSpanFromFields({\n disableSmartFilter: options?.disableSmartFilter,\n shouldExportSpan: options?.shouldExportSpan,\n blockedInstrumentationScopes: options?.blockedInstrumentationScopes,\n })\n\n const redactThenExport = new RedactThenExportSpanProcessor(redact, batchOrSimple)\n this.tail = new ExportFilterSpanProcessor(shouldExport, redactThenExport)\n }\n\n onStart(span: Span, parentContext: Context): void {\n const latitudeData = getLatitudeContext(parentContext)\n\n if (latitudeData) {\n if (latitudeData.name) {\n span.setAttribute(ATTRIBUTES.name, latitudeData.name)\n // Only update span name for the capture root span (has latitude.capture.root attr)\n // Child spans keep their original names (database.query, business.validate, etc.)\n if (span.attributes[\"latitude.capture.root\"]) {\n span.updateName(latitudeData.name)\n }\n }\n if (latitudeData.tags && latitudeData.tags.length > 0) {\n span.setAttribute(ATTRIBUTES.tags, JSON.stringify(latitudeData.tags))\n }\n if (latitudeData.metadata && Object.keys(latitudeData.metadata).length > 0) {\n span.setAttribute(ATTRIBUTES.metadata, JSON.stringify(latitudeData.metadata))\n }\n if (latitudeData.sessionId) {\n span.setAttribute(ATTRIBUTES.sessionId, latitudeData.sessionId)\n }\n if (latitudeData.userId) {\n span.setAttribute(ATTRIBUTES.userId, latitudeData.userId)\n }\n }\n\n this.tail.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n this.tail.onEnd(span)\n }\n\n async forceFlush(): Promise<void> {\n await this.tail.forceFlush()\n }\n\n async shutdown(): Promise<void> {\n await this.tail.shutdown()\n }\n}\n","export const ATTRIBUTES = {\n name: \"latitude.capture.name\",\n tags: \"latitude.tags\",\n metadata: \"latitude.metadata\",\n sessionId: \"session.id\",\n userId: \"user.id\",\n} as const\n","export const SCOPE_LATITUDE = \"so.latitude.instrumentation\"\n\nexport enum InstrumentationScope {\n Manual = \"manual\",\n OpenAI = \"openai\",\n Anthropic = \"anthropic\",\n AzureOpenAI = \"azure\",\n VercelAI = \"vercelai\",\n VertexAI = \"vertexai\",\n AIPlatform = \"aiplatform\",\n MistralAI = \"mistralai\",\n Bedrock = \"bedrock\",\n Sagemaker = \"sagemaker\",\n TogetherAI = \"togetherai\",\n Replicate = \"replicate\",\n Groq = \"groq\",\n Cohere = \"cohere\",\n LiteLLM = \"litellm\",\n Langchain = \"langchain\",\n LlamaIndex = \"llamaindex\",\n DSPy = \"dspy\",\n Haystack = \"haystack\",\n Ollama = \"ollama\",\n Transformers = \"transformers\",\n AlephAlpha = \"alephalpha\",\n}\n","const DEFAULT_EXPORTER_URL =\n {\n production: \"https://ingest.latitude.so\",\n development: \"http://localhost:3002\",\n test: \"http://localhost:3002\",\n }[process.env.NODE_ENV ?? \"development\"] ?? \"http://localhost:3002\"\n\nfunction getExporterUrl() {\n if (process.env.LATITUDE_TELEMETRY_URL) {\n return process.env.LATITUDE_TELEMETRY_URL\n }\n\n return DEFAULT_EXPORTER_URL\n}\n\nexport const env = { EXPORTER_URL: getExporterUrl() } as const\n","import type * as otel from \"@opentelemetry/api\"\nimport type { ReadableSpan, Span, SpanProcessor } from \"@opentelemetry/sdk-trace-node\"\n\nexport interface RedactSpanProcessorOptions {\n attributes: (string | RegExp)[]\n mask?: (attribute: string, value: unknown) => string\n}\n\nexport class RedactSpanProcessor implements SpanProcessor {\n private options: RedactSpanProcessorOptions\n\n constructor(options: RedactSpanProcessorOptions) {\n this.options = options\n\n if (!options.mask) {\n this.options.mask = (_attribute: string, _value: unknown) => \"******\"\n }\n }\n\n onStart(_span: Span, _context: otel.Context): void {\n // Noop\n }\n\n onEnd(span: ReadableSpan): void {\n Object.assign(span.attributes, this.redactAttributes(span.attributes))\n for (const event of span.events) {\n if (!event.attributes) continue\n Object.assign(event.attributes, this.redactAttributes(event.attributes))\n }\n for (const link of span.links) {\n if (!link.attributes) continue\n Object.assign(link.attributes, this.redactAttributes(link.attributes))\n }\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n private shouldRedact(attribute: string) {\n return this.options.attributes.some((pattern) => {\n if (typeof pattern === \"string\") {\n return attribute === pattern\n } else if (pattern instanceof RegExp) {\n return pattern.test(attribute)\n }\n return false\n })\n }\n\n private redactAttributes(attributes: otel.Attributes) {\n const redacted: otel.Attributes = {}\n\n for (const [key, value] of Object.entries(attributes)) {\n if (this.shouldRedact(key)) {\n redacted[key] = this.options.mask?.(key, value)\n }\n }\n\n return redacted\n }\n}\n\nexport const DEFAULT_REDACT_SPAN_PROCESSOR = () =>\n new RedactSpanProcessor({\n attributes: [\n // HTTP security headers\n /^http\\.request\\.header\\.authorization$/i,\n /^http\\.request\\.header\\.cookie$/i,\n /^http\\.request\\.header\\.x[-_]api[-_]key$/i,\n // Database statements may contain sensitive data\n /^db\\.statement$/i,\n ],\n })\n","import type { Context } from \"@opentelemetry/api\"\nimport type { ReadableSpan, Span, SpanProcessor } from \"@opentelemetry/sdk-trace-node\"\nimport { SCOPE_LATITUDE } from \"../constants/scope.ts\"\n\n/** OpenTelemetry GenAI semantic convention attribute prefix. */\nconst GEN_AI_PREFIX = \"gen_ai.\"\n\n/** Legacy / OpenInference-style LLM attribute prefix. */\nconst LLM_PREFIX = \"llm.\"\n\nconst OPENINFERENCE_KIND = \"openinference.span.kind\"\n\n/** OTel Python instrumentation scope prefixes for LLM-related instrumentors we support. */\nconst OTEL_LLM_INSTRUMENTATION_SCOPE_PREFIXES = [\n \"opentelemetry.instrumentation.alephalpha\",\n \"opentelemetry.instrumentation.anthropic\",\n \"opentelemetry.instrumentation.bedrock\",\n \"opentelemetry.instrumentation.cohere\",\n \"opentelemetry.instrumentation.crewai\",\n \"opentelemetry.instrumentation.google_generativeai\",\n \"opentelemetry.instrumentation.groq\",\n \"opentelemetry.instrumentation.haystack\",\n \"opentelemetry.instrumentation.langchain\",\n \"opentelemetry.instrumentation.llamaindex\",\n \"opentelemetry.instrumentation.mistralai\",\n \"opentelemetry.instrumentation.ollama\",\n \"opentelemetry.instrumentation.openai\",\n \"opentelemetry.instrumentation.replicate\",\n \"opentelemetry.instrumentation.sagemaker\",\n \"opentelemetry.instrumentation.together\",\n \"opentelemetry.instrumentation.transformers\",\n \"opentelemetry.instrumentation.vertexai\",\n \"opentelemetry.instrumentation.watsonx\",\n \"openinference.instrumentation\",\n] as const\n\n/** Substrings in scope names that indicate LLM / GenAI instrumentation (e.g. Traceloop JS). */\nconst LLM_SCOPE_SUBSTRINGS = [\"openinference\", \"traceloop\", \"langsmith\", \"litellm\"] as const\n\nexport type SmartFilterOptions = {\n /**\n * When true, all spans are exported (legacy behavior).\n * Default false — only LLM-relevant spans are exported.\n */\n disableSmartFilter?: boolean\n /**\n * When smart filter is on, also export spans for which this returns true\n * (in addition to {@link isDefaultExportSpan}).\n */\n shouldExportSpan?: (span: ReadableSpan) => boolean\n /** Instrumentation scope names to drop (exact match) even if they pass the default predicate. */\n blockedInstrumentationScopes?: string[]\n}\n\n/** Input for {@link buildShouldExportSpanFromFields}; allows `undefined` field values for ergonomics. */\nexport type SmartFilterFieldsInput = {\n disableSmartFilter?: boolean | undefined\n shouldExportSpan?: ((span: ReadableSpan) => boolean) | undefined\n blockedInstrumentationScopes?: string[] | undefined\n}\n\n/**\n * Builds the export predicate from loose option fields (`exactOptionalPropertyTypes`-safe call sites).\n */\nexport function buildShouldExportSpanFromFields(fields: SmartFilterFieldsInput): (span: ReadableSpan) => boolean {\n return buildShouldExportSpan({\n ...(fields.disableSmartFilter !== undefined ? { disableSmartFilter: fields.disableSmartFilter } : {}),\n ...(fields.shouldExportSpan !== undefined ? { shouldExportSpan: fields.shouldExportSpan } : {}),\n ...(fields.blockedInstrumentationScopes !== undefined\n ? { blockedInstrumentationScopes: fields.blockedInstrumentationScopes }\n : {}),\n })\n}\n\nfunction attributeKeys(span: ReadableSpan): string[] {\n const attrs = span.attributes\n if (!attrs || typeof attrs !== \"object\") return []\n return Object.keys(attrs as Record<string, unknown>)\n}\n\nfunction instrumentationScopeName(span: ReadableSpan): string {\n return span.instrumentationLibrary?.name ?? \"\"\n}\n\n/** True if the span uses OpenTelemetry GenAI semantic conventions or common LLM attribute namespaces. */\nexport function isGenAiOrLlmAttributeSpan(span: ReadableSpan): boolean {\n for (const key of attributeKeys(span)) {\n if (key.startsWith(GEN_AI_PREFIX) || key.startsWith(LLM_PREFIX)) return true\n if (key === OPENINFERENCE_KIND || key.startsWith(\"openinference.\")) return true\n // Vercel AI SDK uses ai.* prefix\n if (key.startsWith(\"ai.\")) return true\n // Latitude context attributes\n if (key.startsWith(\"latitude.\")) return true\n }\n return false\n}\n\n/** True if the span was created with Latitude's tracer scopes. */\nexport function isLatitudeInstrumentationSpan(span: ReadableSpan): boolean {\n const name = instrumentationScopeName(span)\n return name === SCOPE_LATITUDE || name.startsWith(`${SCOPE_LATITUDE}.`)\n}\n\nfunction isKnownLlmInstrumentationScope(span: ReadableSpan): boolean {\n const name = instrumentationScopeName(span)\n if (!name) return false\n for (const prefix of OTEL_LLM_INSTRUMENTATION_SCOPE_PREFIXES) {\n if (name === prefix || name.startsWith(`${prefix}.`)) return true\n }\n const lower = name.toLowerCase()\n for (const part of LLM_SCOPE_SUBSTRINGS) {\n if (lower.includes(part)) return true\n }\n return false\n}\n\n/**\n * Default export predicate (smart filter): Latitude scopes, GenAI / LLM attributes,\n * or known LLM instrumentation scopes.\n */\nexport function isDefaultExportSpan(span: ReadableSpan): boolean {\n if (isLatitudeInstrumentationSpan(span)) return true\n if (isGenAiOrLlmAttributeSpan(span)) return true\n if (isKnownLlmInstrumentationScope(span)) return true\n return false\n}\n\nexport function buildShouldExportSpan(options: SmartFilterOptions): (span: ReadableSpan) => boolean {\n if (options.disableSmartFilter) return () => true\n const blocked = new Set(options.blockedInstrumentationScopes ?? [])\n const extra = options.shouldExportSpan\n return (span: ReadableSpan) => {\n const scope = instrumentationScopeName(span)\n if (blocked.has(scope)) return false\n if (isDefaultExportSpan(span)) return true\n if (extra?.(span)) return true\n return false\n }\n}\n\n/**\n * Drops spans that fail the export predicate before passing them to the inner processor.\n * Inner processor should perform redaction and export.\n */\nexport class ExportFilterSpanProcessor implements SpanProcessor {\n private readonly shouldExport: (span: ReadableSpan) => boolean\n private readonly inner: SpanProcessor\n\n constructor(shouldExport: (span: ReadableSpan) => boolean, inner: SpanProcessor) {\n this.shouldExport = shouldExport\n this.inner = inner\n }\n\n onStart(span: Span, parentContext: Context): void {\n this.inner.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n if (!this.shouldExport(span)) return\n this.inner.onEnd(span)\n }\n\n forceFlush(): Promise<void> {\n return this.inner.forceFlush()\n }\n\n shutdown(): Promise<void> {\n return this.inner.shutdown()\n }\n}\n\n/** Runs optional redaction then the export processor (batch/simple). */\nexport class RedactThenExportSpanProcessor implements SpanProcessor {\n private readonly redact: SpanProcessor | null\n private readonly exportProcessor: SpanProcessor\n\n constructor(redact: SpanProcessor | null, exportProcessor: SpanProcessor) {\n this.redact = redact\n this.exportProcessor = exportProcessor\n }\n\n onStart(span: Span, parentContext: Context): void {\n this.redact?.onStart(span, parentContext)\n this.exportProcessor.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n this.redact?.onEnd(span)\n this.exportProcessor.onEnd(span)\n }\n\n forceFlush(): Promise<void> {\n return this.exportProcessor.forceFlush()\n }\n\n shutdown(): Promise<void> {\n return this.exportProcessor.shutdown()\n }\n}\n"],"mappings":"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","names":["import_api","import_sdk_trace_node"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/sdk/context.ts","../src/sdk/init.ts","../src/sdk/instrumentations.ts","../src/sdk/processor.ts","../src/constants/attributes.ts","../src/constants/scope.ts","../src/env/env.ts","../src/sdk/redact.ts","../src/sdk/span-filter.ts"],"sourcesContent":["export * from \"./sdk/index.ts\"\n","import { type Context, context, createContextKey, trace } from \"@opentelemetry/api\"\nimport type { ContextOptions } from \"./types.ts\"\n\nexport const LATITUDE_CONTEXT_KEY = createContextKey(\"latitude-internal-context\")\nconst CAPTURE_TRACER_NAME = \"so.latitude.instrumentation.capture\"\n\ntype LatitudeContextData = {\n name: string | undefined\n tags: string[] | undefined\n metadata: Record<string, unknown> | undefined\n sessionId: string | undefined\n userId: string | undefined\n}\n\nexport function getLatitudeContext(ctx: Context): LatitudeContextData | undefined {\n return ctx.getValue(LATITUDE_CONTEXT_KEY) as LatitudeContextData | undefined\n}\n\nfunction mergeArrays<T>(a: T[] | undefined, b: T[] | undefined): T[] | undefined {\n if (!a && !b) return undefined\n if (!a) return b\n if (!b) return a\n return [...new Set([...a, ...b])]\n}\n\nexport function capture<T>(name: string, fn: () => T | Promise<T>, options: ContextOptions = {}): T | Promise<T> {\n const currentContext = context.active()\n const existingData = getLatitudeContext(currentContext)\n\n const mergedData: LatitudeContextData = {\n name: options.name ?? name,\n tags: mergeArrays(existingData?.tags, options.tags),\n metadata: { ...existingData?.metadata, ...options.metadata },\n sessionId: options.sessionId ?? existingData?.sessionId,\n userId: options.userId ?? existingData?.userId,\n }\n\n const newContext = currentContext.setValue(LATITUDE_CONTEXT_KEY, mergedData)\n const existingSpan = trace.getSpan(currentContext)\n\n if (existingSpan) {\n return context.with(newContext, fn)\n }\n\n const tracer = trace.getTracer(CAPTURE_TRACER_NAME)\n\n return tracer.startActiveSpan(name, { attributes: { \"latitude.capture.root\": true } }, newContext, (span) => {\n let result: T | Promise<T>\n try {\n result = fn()\n } catch (error) {\n span.recordException(error as Error)\n span.end()\n throw error\n }\n\n if (result instanceof Promise) {\n return result\n .catch((error) => {\n span.recordException(error as Error)\n throw error\n })\n .finally(() => {\n span.end()\n }) as T | Promise<T>\n }\n\n span.end()\n return result\n })\n}\n","import { context, propagation } from \"@opentelemetry/api\"\nimport { AsyncLocalStorageContextManager } from \"@opentelemetry/context-async-hooks\"\nimport { CompositePropagator, W3CBaggagePropagator, W3CTraceContextPropagator } from \"@opentelemetry/core\"\nimport { resourceFromAttributes } from \"@opentelemetry/resources\"\nimport { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\"\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\"\nimport { registerLatitudeInstrumentations } from \"./instrumentations.ts\"\nimport { LatitudeSpanProcessor } from \"./processor.ts\"\nimport type { InitLatitudeOptions } from \"./types.ts\"\n\nconst SERVICE_NAME = process.env.npm_package_name || \"unknown\"\n\n/** Module-level flag to prevent duplicate signal handler registration on repeated initLatitude calls */\nlet shutdownHandlersRegistered = false\n\nexport function initLatitude(options: InitLatitudeOptions): {\n provider: NodeTracerProvider\n flush: () => Promise<void>\n shutdown: () => Promise<void>\n ready: Promise<void>\n} {\n const { apiKey, projectSlug, instrumentations = [], ...processorOptions } = options\n\n if (!apiKey || apiKey.trim() === \"\") {\n throw new Error(\"[Latitude] apiKey is required and cannot be empty\")\n }\n if (!projectSlug || projectSlug.trim() === \"\") {\n throw new Error(\"[Latitude] projectSlug is required and cannot be empty\")\n }\n\n const contextManager = new AsyncLocalStorageContextManager()\n contextManager.enable()\n\n const propagator = new CompositePropagator({\n propagators: [new W3CTraceContextPropagator(), new W3CBaggagePropagator()],\n })\n\n context.setGlobalContextManager(contextManager)\n propagation.setGlobalPropagator(propagator)\n\n const resourceServiceName =\n typeof processorOptions.serviceName === \"string\" && processorOptions.serviceName.trim() !== \"\"\n ? processorOptions.serviceName.trim()\n : SERVICE_NAME\n\n const provider = new NodeTracerProvider({\n resource: resourceFromAttributes({\n [ATTR_SERVICE_NAME]: resourceServiceName,\n }),\n spanProcessors: [new LatitudeSpanProcessor(apiKey, projectSlug, processorOptions)],\n })\n\n provider.register()\n\n const ready = registerLatitudeInstrumentations({\n instrumentations,\n tracerProvider: provider,\n }).catch((err) => {\n console.warn(\"[Latitude] Failed to register instrumentations:\", err)\n })\n\n const shutdown = async (): Promise<void> => {\n await provider.shutdown()\n }\n\n const flush = async (): Promise<void> => {\n await provider.forceFlush()\n }\n\n const handleShutdown = async () => {\n try {\n await shutdown()\n } catch (err) {\n console.error(\"Error during Latitude Telemetry shutdown:\", err)\n }\n }\n\n if (!shutdownHandlersRegistered) {\n process.once(\"SIGTERM\", handleShutdown)\n process.once(\"SIGINT\", handleShutdown)\n shutdownHandlersRegistered = true\n }\n\n return {\n provider,\n flush,\n shutdown,\n ready,\n }\n}\n","import type { TracerProvider } from \"@opentelemetry/api\"\nimport { type Instrumentation, registerInstrumentations } from \"@opentelemetry/instrumentation\"\nimport { AnthropicInstrumentation } from \"@traceloop/instrumentation-anthropic\"\nimport { BedrockInstrumentation } from \"@traceloop/instrumentation-bedrock\"\nimport { CohereInstrumentation } from \"@traceloop/instrumentation-cohere\"\nimport { LangChainInstrumentation } from \"@traceloop/instrumentation-langchain\"\nimport { LlamaIndexInstrumentation } from \"@traceloop/instrumentation-llamaindex\"\nimport { OpenAIInstrumentation } from \"@traceloop/instrumentation-openai\"\nimport { TogetherInstrumentation } from \"@traceloop/instrumentation-together\"\nimport { AIPlatformInstrumentation, VertexAIInstrumentation } from \"@traceloop/instrumentation-vertexai\"\n\n/**\n * Supported LLM instrumentation types.\n * Use these string identifiers to enable auto-instrumentation.\n */\nexport type InstrumentationType =\n | \"openai\"\n | \"anthropic\"\n | \"bedrock\"\n | \"cohere\"\n | \"langchain\"\n | \"llamaindex\"\n | \"togetherai\"\n | \"vertexai\"\n | \"aiplatform\"\n\n/**\n * Minimal interface for LLM instrumentation instances.\n * Extends OpenTelemetry's Instrumentation interface.\n */\ninterface LlmInstrumentation extends Instrumentation {\n manuallyInstrument?(module: unknown): void\n}\n\n/**\n * Options for creating LLM instrumentations.\n */\ninterface CreateInstrumentationsOptions {\n /** List of instrumentation types to enable. */\n instrumentations: InstrumentationType[]\n /**\n * Optional module references for auto-instrumentation.\n * If not provided, the instrumentation will attempt to require the module.\n * Used for Traceloop-based instrumentations.\n */\n modules?: Partial<Record<InstrumentationType, unknown>>\n /**\n * Per-instrumentation token enrichment settings.\n * @default { openai: true }\n */\n enrichTokens?: Partial<Record<InstrumentationType, boolean>>\n}\n\ninterface InstrumentationConfig {\n ctor: new (config?: Record<string, unknown>) => LlmInstrumentation\n moduleName: string\n defaultEnrichTokens?: boolean\n}\n\nconst INSTRUMENTATION_MAP: Record<InstrumentationType, InstrumentationConfig> = {\n openai: { ctor: OpenAIInstrumentation, moduleName: \"openai\", defaultEnrichTokens: true },\n anthropic: { ctor: AnthropicInstrumentation, moduleName: \"@anthropic-ai/sdk\" },\n bedrock: { ctor: BedrockInstrumentation, moduleName: \"@aws-sdk/client-bedrock-runtime\" },\n cohere: { ctor: CohereInstrumentation, moduleName: \"cohere-ai\" },\n langchain: { ctor: LangChainInstrumentation, moduleName: \"langchain\" },\n llamaindex: { ctor: LlamaIndexInstrumentation, moduleName: \"llamaindex\" },\n togetherai: { ctor: TogetherInstrumentation, moduleName: \"together-ai\", defaultEnrichTokens: false },\n vertexai: { ctor: VertexAIInstrumentation, moduleName: \"@google-cloud/vertexai\" },\n aiplatform: { ctor: AIPlatformInstrumentation, moduleName: \"@google-cloud/aiplatform\" },\n}\n\n/**\n * Internal function to create LLM instrumentation instances.\n * Not exported publicly - use registerLatitudeInstrumentations instead.\n */\nasync function createLatitudeInstrumentations(options: CreateInstrumentationsOptions): Promise<LlmInstrumentation[]> {\n const result: LlmInstrumentation[] = []\n\n for (const type of options.instrumentations) {\n const config = INSTRUMENTATION_MAP[type]\n if (!config) {\n console.warn(`[Latitude] Unknown instrumentation type: ${type}`)\n continue\n }\n\n const enrichTokens = options.enrichTokens?.[type] ?? config.defaultEnrichTokens\n const inst = new config.ctor(enrichTokens !== undefined ? { enrichTokens } : undefined)\n\n // Get module from explicit options or try to auto-require\n const moduleRef = options.modules?.[type] ?? (await tryRequire(config.moduleName))\n if (!moduleRef) {\n console.warn(\n `[Latitude] Module not found for ${type}: ${config.moduleName}. Install it or pass it explicitly in 'modules'.`,\n )\n continue\n }\n inst.manuallyInstrument?.(moduleRef)\n\n result.push(inst)\n }\n\n return result\n}\n\nasync function tryRequire(moduleName: string): Promise<unknown | undefined> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require(moduleName)\n } catch {\n // Fallback to dynamic import for ESM environments\n try {\n const mod = await import(moduleName)\n return mod.default ?? mod\n } catch {\n return undefined\n }\n }\n}\n\n/**\n * Registers LLM instrumentations with the global OpenTelemetry instrumentation registry.\n *\n * This is a convenience wrapper around `createLatitudeInstrumentations` and\n * `@opentelemetry/instrumentation`'s `registerInstrumentations`.\n *\n * @example\n * ```typescript\n * import { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\"\n * import { registerLatitudeInstrumentations, LatitudeSpanProcessor } from \"@latitude-data/telemetry\"\n *\n * const provider = new NodeTracerProvider({\n * spanProcessors: [new LatitudeSpanProcessor(apiKey, projectSlug)],\n * })\n *\n * await registerLatitudeInstrumentations({\n * instrumentations: [\"openai\", \"anthropic\"],\n * tracerProvider: provider,\n * })\n *\n * provider.register()\n * ```\n */\nexport async function registerLatitudeInstrumentations(\n options: CreateInstrumentationsOptions & { tracerProvider: TracerProvider },\n): Promise<void> {\n const instrumentations = await createLatitudeInstrumentations(options)\n registerInstrumentations({\n instrumentations,\n tracerProvider: options.tracerProvider,\n })\n}\n","import type { Context } from \"@opentelemetry/api\"\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\"\nimport {\n BatchSpanProcessor,\n type ReadableSpan,\n SimpleSpanProcessor,\n type Span,\n type SpanProcessor,\n} from \"@opentelemetry/sdk-trace-node\"\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\"\nimport { ATTRIBUTES } from \"../constants/index.ts\"\nimport { env } from \"../env/index.ts\"\nimport { getLatitudeContext } from \"./context.ts\"\nimport { DEFAULT_REDACT_SPAN_PROCESSOR, RedactSpanProcessor } from \"./redact.ts\"\nimport {\n buildShouldExportSpanFromFields,\n ExportFilterSpanProcessor,\n RedactThenExportSpanProcessor,\n} from \"./span-filter.ts\"\nimport type { LatitudeSpanProcessorOptions } from \"./types.ts\"\n\nexport class LatitudeSpanProcessor implements SpanProcessor {\n private readonly tail: SpanProcessor\n private readonly serviceName: string | undefined\n\n constructor(apiKey: string, projectSlug: string, options?: LatitudeSpanProcessorOptions) {\n if (!apiKey || apiKey.trim() === \"\") {\n throw new Error(\"[Latitude] apiKey is required and cannot be empty\")\n }\n if (!projectSlug || projectSlug.trim() === \"\") {\n throw new Error(\"[Latitude] projectSlug is required and cannot be empty\")\n }\n\n const exporter =\n options?.exporter ??\n new OTLPTraceExporter({\n url: `${env.EXPORTER_URL}/v1/traces`,\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n \"X-Latitude-Project\": projectSlug,\n },\n timeoutMillis: 30_000,\n })\n\n const redact = options?.disableRedact\n ? null\n : options?.redact\n ? new RedactSpanProcessor(options.redact)\n : DEFAULT_REDACT_SPAN_PROCESSOR()\n\n const batchOrSimple = options?.disableBatch ? new SimpleSpanProcessor(exporter) : new BatchSpanProcessor(exporter)\n\n const shouldExport = buildShouldExportSpanFromFields({\n disableSmartFilter: options?.disableSmartFilter,\n shouldExportSpan: options?.shouldExportSpan,\n blockedInstrumentationScopes: options?.blockedInstrumentationScopes,\n })\n\n const redactThenExport = new RedactThenExportSpanProcessor(redact, batchOrSimple)\n this.tail = new ExportFilterSpanProcessor(shouldExport, redactThenExport)\n\n const rawServiceName = options?.serviceName?.trim()\n this.serviceName = rawServiceName === \"\" ? undefined : rawServiceName\n }\n\n onStart(span: Span, parentContext: Context): void {\n if (this.serviceName !== undefined) {\n span.setAttribute(ATTR_SERVICE_NAME, this.serviceName)\n }\n\n const latitudeData = getLatitudeContext(parentContext)\n\n if (latitudeData) {\n if (latitudeData.name) {\n span.setAttribute(ATTRIBUTES.name, latitudeData.name)\n // Only update span name for the capture root span (has latitude.capture.root attr)\n // Child spans keep their original names (database.query, business.validate, etc.)\n if (span.attributes[\"latitude.capture.root\"]) {\n span.updateName(latitudeData.name)\n }\n }\n if (latitudeData.tags && latitudeData.tags.length > 0) {\n span.setAttribute(ATTRIBUTES.tags, JSON.stringify(latitudeData.tags))\n }\n if (latitudeData.metadata && Object.keys(latitudeData.metadata).length > 0) {\n span.setAttribute(ATTRIBUTES.metadata, JSON.stringify(latitudeData.metadata))\n }\n if (latitudeData.sessionId) {\n span.setAttribute(ATTRIBUTES.sessionId, latitudeData.sessionId)\n }\n if (latitudeData.userId) {\n span.setAttribute(ATTRIBUTES.userId, latitudeData.userId)\n }\n }\n\n this.tail.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n this.tail.onEnd(span)\n }\n\n async forceFlush(): Promise<void> {\n await this.tail.forceFlush()\n }\n\n async shutdown(): Promise<void> {\n await this.tail.shutdown()\n }\n}\n","export const ATTRIBUTES = {\n name: \"latitude.capture.name\",\n tags: \"latitude.tags\",\n metadata: \"latitude.metadata\",\n sessionId: \"session.id\",\n userId: \"user.id\",\n} as const\n","export const SCOPE_LATITUDE = \"so.latitude.instrumentation\"\n\nexport enum InstrumentationScope {\n Manual = \"manual\",\n OpenAI = \"openai\",\n Anthropic = \"anthropic\",\n AzureOpenAI = \"azure\",\n VercelAI = \"vercelai\",\n VertexAI = \"vertexai\",\n AIPlatform = \"aiplatform\",\n MistralAI = \"mistralai\",\n Bedrock = \"bedrock\",\n Sagemaker = \"sagemaker\",\n TogetherAI = \"togetherai\",\n Replicate = \"replicate\",\n Groq = \"groq\",\n Cohere = \"cohere\",\n LiteLLM = \"litellm\",\n Langchain = \"langchain\",\n LlamaIndex = \"llamaindex\",\n DSPy = \"dspy\",\n Haystack = \"haystack\",\n Ollama = \"ollama\",\n Transformers = \"transformers\",\n AlephAlpha = \"alephalpha\",\n}\n","const DEFAULT_EXPORTER_URL =\n {\n production: \"https://ingest.latitude.so\",\n development: \"http://localhost:3002\",\n test: \"http://localhost:3002\",\n }[process.env.NODE_ENV ?? \"development\"] ?? \"http://localhost:3002\"\n\nfunction getExporterUrl() {\n if (process.env.LATITUDE_TELEMETRY_URL) {\n return process.env.LATITUDE_TELEMETRY_URL\n }\n\n return DEFAULT_EXPORTER_URL\n}\n\nexport const env = { EXPORTER_URL: getExporterUrl() } as const\n","import type * as otel from \"@opentelemetry/api\"\nimport type { ReadableSpan, Span, SpanProcessor } from \"@opentelemetry/sdk-trace-node\"\n\nexport interface RedactSpanProcessorOptions {\n attributes: (string | RegExp)[]\n mask?: (attribute: string, value: unknown) => string\n}\n\nexport class RedactSpanProcessor implements SpanProcessor {\n private options: RedactSpanProcessorOptions\n\n constructor(options: RedactSpanProcessorOptions) {\n this.options = options\n\n if (!options.mask) {\n this.options.mask = (_attribute: string, _value: unknown) => \"******\"\n }\n }\n\n onStart(_span: Span, _context: otel.Context): void {\n // Noop\n }\n\n onEnd(span: ReadableSpan): void {\n Object.assign(span.attributes, this.redactAttributes(span.attributes))\n for (const event of span.events) {\n if (!event.attributes) continue\n Object.assign(event.attributes, this.redactAttributes(event.attributes))\n }\n for (const link of span.links) {\n if (!link.attributes) continue\n Object.assign(link.attributes, this.redactAttributes(link.attributes))\n }\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n private shouldRedact(attribute: string) {\n return this.options.attributes.some((pattern) => {\n if (typeof pattern === \"string\") {\n return attribute === pattern\n } else if (pattern instanceof RegExp) {\n return pattern.test(attribute)\n }\n return false\n })\n }\n\n private redactAttributes(attributes: otel.Attributes) {\n const redacted: otel.Attributes = {}\n\n for (const [key, value] of Object.entries(attributes)) {\n if (this.shouldRedact(key)) {\n redacted[key] = this.options.mask?.(key, value)\n }\n }\n\n return redacted\n }\n}\n\nexport const DEFAULT_REDACT_SPAN_PROCESSOR = () =>\n new RedactSpanProcessor({\n attributes: [\n // HTTP security headers\n /^http\\.request\\.header\\.authorization$/i,\n /^http\\.request\\.header\\.cookie$/i,\n /^http\\.request\\.header\\.x[-_]api[-_]key$/i,\n // Database statements may contain sensitive data\n /^db\\.statement$/i,\n ],\n })\n","import type { Context } from \"@opentelemetry/api\"\nimport type { ReadableSpan, Span, SpanProcessor } from \"@opentelemetry/sdk-trace-node\"\nimport { SCOPE_LATITUDE } from \"../constants/scope.ts\"\n\n/** OpenTelemetry GenAI semantic convention attribute prefix. */\nconst GEN_AI_PREFIX = \"gen_ai.\"\n\n/** Legacy / OpenInference-style LLM attribute prefix. */\nconst LLM_PREFIX = \"llm.\"\n\nconst OPENINFERENCE_KIND = \"openinference.span.kind\"\n\n/** OTel Python instrumentation scope prefixes for LLM-related instrumentors we support. */\nconst OTEL_LLM_INSTRUMENTATION_SCOPE_PREFIXES = [\n \"opentelemetry.instrumentation.alephalpha\",\n \"opentelemetry.instrumentation.anthropic\",\n \"opentelemetry.instrumentation.bedrock\",\n \"opentelemetry.instrumentation.cohere\",\n \"opentelemetry.instrumentation.crewai\",\n \"opentelemetry.instrumentation.google_generativeai\",\n \"opentelemetry.instrumentation.groq\",\n \"opentelemetry.instrumentation.haystack\",\n \"opentelemetry.instrumentation.langchain\",\n \"opentelemetry.instrumentation.llamaindex\",\n \"opentelemetry.instrumentation.mistralai\",\n \"opentelemetry.instrumentation.ollama\",\n \"opentelemetry.instrumentation.openai\",\n \"opentelemetry.instrumentation.replicate\",\n \"opentelemetry.instrumentation.sagemaker\",\n \"opentelemetry.instrumentation.together\",\n \"opentelemetry.instrumentation.transformers\",\n \"opentelemetry.instrumentation.vertexai\",\n \"opentelemetry.instrumentation.watsonx\",\n \"openinference.instrumentation\",\n] as const\n\n/** Substrings in scope names that indicate LLM / GenAI instrumentation (e.g. Traceloop JS). */\nconst LLM_SCOPE_SUBSTRINGS = [\"openinference\", \"traceloop\", \"langsmith\", \"litellm\"] as const\n\nexport type SmartFilterOptions = {\n /**\n * When true, all spans are exported (legacy behavior).\n * Default false — only LLM-relevant spans are exported.\n */\n disableSmartFilter?: boolean\n /**\n * When smart filter is on, also export spans for which this returns true\n * (in addition to {@link isDefaultExportSpan}).\n */\n shouldExportSpan?: (span: ReadableSpan) => boolean\n /** Instrumentation scope names to drop (exact match) even if they pass the default predicate. */\n blockedInstrumentationScopes?: string[]\n}\n\n/** Input for {@link buildShouldExportSpanFromFields}; allows `undefined` field values for ergonomics. */\nexport type SmartFilterFieldsInput = {\n disableSmartFilter?: boolean | undefined\n shouldExportSpan?: ((span: ReadableSpan) => boolean) | undefined\n blockedInstrumentationScopes?: string[] | undefined\n}\n\n/**\n * Builds the export predicate from loose option fields (`exactOptionalPropertyTypes`-safe call sites).\n */\nexport function buildShouldExportSpanFromFields(fields: SmartFilterFieldsInput): (span: ReadableSpan) => boolean {\n return buildShouldExportSpan({\n ...(fields.disableSmartFilter !== undefined ? { disableSmartFilter: fields.disableSmartFilter } : {}),\n ...(fields.shouldExportSpan !== undefined ? { shouldExportSpan: fields.shouldExportSpan } : {}),\n ...(fields.blockedInstrumentationScopes !== undefined\n ? { blockedInstrumentationScopes: fields.blockedInstrumentationScopes }\n : {}),\n })\n}\n\nfunction attributeKeys(span: ReadableSpan): string[] {\n const attrs = span.attributes\n if (!attrs || typeof attrs !== \"object\") return []\n return Object.keys(attrs as Record<string, unknown>)\n}\n\nfunction instrumentationScopeName(span: ReadableSpan): string {\n return span.instrumentationScope?.name ?? \"\"\n}\n\n/** True if the span uses OpenTelemetry GenAI semantic conventions or common LLM attribute namespaces. */\nexport function isGenAiOrLlmAttributeSpan(span: ReadableSpan): boolean {\n for (const key of attributeKeys(span)) {\n if (key.startsWith(GEN_AI_PREFIX) || key.startsWith(LLM_PREFIX)) return true\n if (key === OPENINFERENCE_KIND || key.startsWith(\"openinference.\")) return true\n // Vercel AI SDK uses ai.* prefix\n if (key.startsWith(\"ai.\")) return true\n // Latitude context attributes\n if (key.startsWith(\"latitude.\")) return true\n }\n return false\n}\n\n/** True if the span was created with Latitude's tracer scopes. */\nexport function isLatitudeInstrumentationSpan(span: ReadableSpan): boolean {\n const name = instrumentationScopeName(span)\n return name === SCOPE_LATITUDE || name.startsWith(`${SCOPE_LATITUDE}.`)\n}\n\nfunction isKnownLlmInstrumentationScope(span: ReadableSpan): boolean {\n const name = instrumentationScopeName(span)\n if (!name) return false\n for (const prefix of OTEL_LLM_INSTRUMENTATION_SCOPE_PREFIXES) {\n if (name === prefix || name.startsWith(`${prefix}.`)) return true\n }\n const lower = name.toLowerCase()\n for (const part of LLM_SCOPE_SUBSTRINGS) {\n if (lower.includes(part)) return true\n }\n return false\n}\n\n/**\n * Default export predicate (smart filter): Latitude scopes, GenAI / LLM attributes,\n * or known LLM instrumentation scopes.\n */\nexport function isDefaultExportSpan(span: ReadableSpan): boolean {\n if (isLatitudeInstrumentationSpan(span)) return true\n if (isGenAiOrLlmAttributeSpan(span)) return true\n if (isKnownLlmInstrumentationScope(span)) return true\n return false\n}\n\nexport function buildShouldExportSpan(options: SmartFilterOptions): (span: ReadableSpan) => boolean {\n if (options.disableSmartFilter) return () => true\n const blocked = new Set(options.blockedInstrumentationScopes ?? [])\n const extra = options.shouldExportSpan\n return (span: ReadableSpan) => {\n const scope = instrumentationScopeName(span)\n if (blocked.has(scope)) return false\n if (isDefaultExportSpan(span)) return true\n if (extra?.(span)) return true\n return false\n }\n}\n\n/**\n * Drops spans that fail the export predicate before passing them to the inner processor.\n * Inner processor should perform redaction and export.\n */\nexport class ExportFilterSpanProcessor implements SpanProcessor {\n private readonly shouldExport: (span: ReadableSpan) => boolean\n private readonly inner: SpanProcessor\n\n constructor(shouldExport: (span: ReadableSpan) => boolean, inner: SpanProcessor) {\n this.shouldExport = shouldExport\n this.inner = inner\n }\n\n onStart(span: Span, parentContext: Context): void {\n this.inner.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n if (!this.shouldExport(span)) return\n this.inner.onEnd(span)\n }\n\n forceFlush(): Promise<void> {\n return this.inner.forceFlush()\n }\n\n shutdown(): Promise<void> {\n return this.inner.shutdown()\n }\n}\n\n/** Runs optional redaction then the export processor (batch/simple). */\nexport class RedactThenExportSpanProcessor implements SpanProcessor {\n private readonly redact: SpanProcessor | null\n private readonly exportProcessor: SpanProcessor\n\n constructor(redact: SpanProcessor | null, exportProcessor: SpanProcessor) {\n this.redact = redact\n this.exportProcessor = exportProcessor\n }\n\n onStart(span: Span, parentContext: Context): void {\n this.redact?.onStart(span, parentContext)\n this.exportProcessor.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n this.redact?.onEnd(span)\n this.exportProcessor.onEnd(span)\n }\n\n forceFlush(): Promise<void> {\n return this.exportProcessor.forceFlush()\n }\n\n shutdown(): Promise<void> {\n return this.exportProcessor.shutdown()\n }\n}\n"],"mappings":"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","names":["import_api","import_sdk_trace_node","import_semantic_conventions"]}
package/dist/index.d.cts CHANGED
@@ -140,12 +140,16 @@ type InitLatitudeOptions = SmartFilterOptions & {
140
140
  redact?: RedactSpanProcessorOptions;
141
141
  disableBatch?: boolean;
142
142
  exporter?: SpanExporter;
143
+ /** Sets `service.name` on exported spans (and on the provider resource when using `initLatitude`). */
144
+ serviceName?: string;
143
145
  };
144
146
  type LatitudeSpanProcessorOptions = SmartFilterOptions & {
145
147
  disableRedact?: boolean;
146
148
  redact?: RedactSpanProcessorOptions;
147
149
  disableBatch?: boolean;
148
150
  exporter?: SpanExporter;
151
+ /** Sets `service.name` on each span so Latitude ingest can attribute telemetry to your service. */
152
+ serviceName?: string;
149
153
  };
150
154
 
151
155
  declare function capture<T>(name: string, fn: () => T | Promise<T>, options?: ContextOptions): T | Promise<T>;
@@ -159,6 +163,7 @@ declare function initLatitude(options: InitLatitudeOptions): {
159
163
 
160
164
  declare class LatitudeSpanProcessor implements SpanProcessor {
161
165
  private readonly tail;
166
+ private readonly serviceName;
162
167
  constructor(apiKey: string, projectSlug: string, options?: LatitudeSpanProcessorOptions);
163
168
  onStart(span: Span, parentContext: Context): void;
164
169
  onEnd(span: ReadableSpan): void;
package/dist/index.d.ts CHANGED
@@ -140,12 +140,16 @@ type InitLatitudeOptions = SmartFilterOptions & {
140
140
  redact?: RedactSpanProcessorOptions;
141
141
  disableBatch?: boolean;
142
142
  exporter?: SpanExporter;
143
+ /** Sets `service.name` on exported spans (and on the provider resource when using `initLatitude`). */
144
+ serviceName?: string;
143
145
  };
144
146
  type LatitudeSpanProcessorOptions = SmartFilterOptions & {
145
147
  disableRedact?: boolean;
146
148
  redact?: RedactSpanProcessorOptions;
147
149
  disableBatch?: boolean;
148
150
  exporter?: SpanExporter;
151
+ /** Sets `service.name` on each span so Latitude ingest can attribute telemetry to your service. */
152
+ serviceName?: string;
149
153
  };
150
154
 
151
155
  declare function capture<T>(name: string, fn: () => T | Promise<T>, options?: ContextOptions): T | Promise<T>;
@@ -159,6 +163,7 @@ declare function initLatitude(options: InitLatitudeOptions): {
159
163
 
160
164
  declare class LatitudeSpanProcessor implements SpanProcessor {
161
165
  private readonly tail;
166
+ private readonly serviceName;
162
167
  constructor(apiKey: string, projectSlug: string, options?: LatitudeSpanProcessorOptions);
163
168
  onStart(span: Span, parentContext: Context): void;
164
169
  onEnd(span: ReadableSpan): void;
package/dist/index.js CHANGED
@@ -60,9 +60,9 @@ function capture(name, fn, options = {}) {
60
60
  import { context as context2, propagation } from "@opentelemetry/api";
61
61
  import { AsyncLocalStorageContextManager } from "@opentelemetry/context-async-hooks";
62
62
  import { CompositePropagator, W3CBaggagePropagator, W3CTraceContextPropagator } from "@opentelemetry/core";
63
- import { Resource } from "@opentelemetry/resources";
63
+ import { resourceFromAttributes } from "@opentelemetry/resources";
64
64
  import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
65
- import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
65
+ import { ATTR_SERVICE_NAME as ATTR_SERVICE_NAME2 } from "@opentelemetry/semantic-conventions";
66
66
 
67
67
  // src/sdk/instrumentations.ts
68
68
  import { registerInstrumentations } from "@opentelemetry/instrumentation";
@@ -133,6 +133,7 @@ import {
133
133
  BatchSpanProcessor,
134
134
  SimpleSpanProcessor
135
135
  } from "@opentelemetry/sdk-trace-node";
136
+ import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
136
137
 
137
138
  // src/constants/attributes.ts
138
139
  var ATTRIBUTES = {
@@ -259,7 +260,7 @@ function attributeKeys(span) {
259
260
  return Object.keys(attrs);
260
261
  }
261
262
  function instrumentationScopeName(span) {
262
- return span.instrumentationLibrary?.name ?? "";
263
+ return span.instrumentationScope?.name ?? "";
263
264
  }
264
265
  function isGenAiOrLlmAttributeSpan(span) {
265
266
  for (const key of attributeKeys(span)) {
@@ -351,6 +352,7 @@ var RedactThenExportSpanProcessor = class {
351
352
  // src/sdk/processor.ts
352
353
  var LatitudeSpanProcessor = class {
353
354
  tail;
355
+ serviceName;
354
356
  constructor(apiKey, projectSlug, options) {
355
357
  if (!apiKey || apiKey.trim() === "") {
356
358
  throw new Error("[Latitude] apiKey is required and cannot be empty");
@@ -376,8 +378,13 @@ var LatitudeSpanProcessor = class {
376
378
  });
377
379
  const redactThenExport = new RedactThenExportSpanProcessor(redact, batchOrSimple);
378
380
  this.tail = new ExportFilterSpanProcessor(shouldExport, redactThenExport);
381
+ const rawServiceName = options?.serviceName?.trim();
382
+ this.serviceName = rawServiceName === "" ? void 0 : rawServiceName;
379
383
  }
380
384
  onStart(span, parentContext) {
385
+ if (this.serviceName !== void 0) {
386
+ span.setAttribute(ATTR_SERVICE_NAME, this.serviceName);
387
+ }
381
388
  const latitudeData = getLatitudeContext(parentContext);
382
389
  if (latitudeData) {
383
390
  if (latitudeData.name) {
@@ -430,9 +437,10 @@ function initLatitude(options) {
430
437
  });
431
438
  context2.setGlobalContextManager(contextManager);
432
439
  propagation.setGlobalPropagator(propagator);
440
+ const resourceServiceName = typeof processorOptions.serviceName === "string" && processorOptions.serviceName.trim() !== "" ? processorOptions.serviceName.trim() : SERVICE_NAME;
433
441
  const provider = new NodeTracerProvider({
434
- resource: new Resource({
435
- [ATTR_SERVICE_NAME]: SERVICE_NAME
442
+ resource: resourceFromAttributes({
443
+ [ATTR_SERVICE_NAME2]: resourceServiceName
436
444
  }),
437
445
  spanProcessors: [new LatitudeSpanProcessor(apiKey, projectSlug, processorOptions)]
438
446
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sdk/context.ts","../src/sdk/init.ts","../src/sdk/instrumentations.ts","../src/sdk/processor.ts","../src/constants/attributes.ts","../src/constants/scope.ts","../src/env/env.ts","../src/sdk/redact.ts","../src/sdk/span-filter.ts"],"sourcesContent":["import { type Context, context, createContextKey, trace } from \"@opentelemetry/api\"\nimport type { ContextOptions } from \"./types.ts\"\n\nexport const LATITUDE_CONTEXT_KEY = createContextKey(\"latitude-internal-context\")\nconst CAPTURE_TRACER_NAME = \"so.latitude.instrumentation.capture\"\n\ntype LatitudeContextData = {\n name: string | undefined\n tags: string[] | undefined\n metadata: Record<string, unknown> | undefined\n sessionId: string | undefined\n userId: string | undefined\n}\n\nexport function getLatitudeContext(ctx: Context): LatitudeContextData | undefined {\n return ctx.getValue(LATITUDE_CONTEXT_KEY) as LatitudeContextData | undefined\n}\n\nfunction mergeArrays<T>(a: T[] | undefined, b: T[] | undefined): T[] | undefined {\n if (!a && !b) return undefined\n if (!a) return b\n if (!b) return a\n return [...new Set([...a, ...b])]\n}\n\nexport function capture<T>(name: string, fn: () => T | Promise<T>, options: ContextOptions = {}): T | Promise<T> {\n const currentContext = context.active()\n const existingData = getLatitudeContext(currentContext)\n\n const mergedData: LatitudeContextData = {\n name: options.name ?? name,\n tags: mergeArrays(existingData?.tags, options.tags),\n metadata: { ...existingData?.metadata, ...options.metadata },\n sessionId: options.sessionId ?? existingData?.sessionId,\n userId: options.userId ?? existingData?.userId,\n }\n\n const newContext = currentContext.setValue(LATITUDE_CONTEXT_KEY, mergedData)\n const existingSpan = trace.getSpan(currentContext)\n\n if (existingSpan) {\n return context.with(newContext, fn)\n }\n\n const tracer = trace.getTracer(CAPTURE_TRACER_NAME)\n\n return tracer.startActiveSpan(name, { attributes: { \"latitude.capture.root\": true } }, newContext, (span) => {\n let result: T | Promise<T>\n try {\n result = fn()\n } catch (error) {\n span.recordException(error as Error)\n span.end()\n throw error\n }\n\n if (result instanceof Promise) {\n return result\n .catch((error) => {\n span.recordException(error as Error)\n throw error\n })\n .finally(() => {\n span.end()\n }) as T | Promise<T>\n }\n\n span.end()\n return result\n })\n}\n","import { context, propagation } from \"@opentelemetry/api\"\nimport { AsyncLocalStorageContextManager } from \"@opentelemetry/context-async-hooks\"\nimport { CompositePropagator, W3CBaggagePropagator, W3CTraceContextPropagator } from \"@opentelemetry/core\"\nimport { Resource } from \"@opentelemetry/resources\"\nimport { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\"\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\"\nimport { registerLatitudeInstrumentations } from \"./instrumentations.ts\"\nimport { LatitudeSpanProcessor } from \"./processor.ts\"\nimport type { InitLatitudeOptions } from \"./types.ts\"\n\nconst SERVICE_NAME = process.env.npm_package_name || \"unknown\"\n\n/** Module-level flag to prevent duplicate signal handler registration on repeated initLatitude calls */\nlet shutdownHandlersRegistered = false\n\nexport function initLatitude(options: InitLatitudeOptions): {\n provider: NodeTracerProvider\n flush: () => Promise<void>\n shutdown: () => Promise<void>\n ready: Promise<void>\n} {\n const { apiKey, projectSlug, instrumentations = [], ...processorOptions } = options\n\n if (!apiKey || apiKey.trim() === \"\") {\n throw new Error(\"[Latitude] apiKey is required and cannot be empty\")\n }\n if (!projectSlug || projectSlug.trim() === \"\") {\n throw new Error(\"[Latitude] projectSlug is required and cannot be empty\")\n }\n\n const contextManager = new AsyncLocalStorageContextManager()\n contextManager.enable()\n\n const propagator = new CompositePropagator({\n propagators: [new W3CTraceContextPropagator(), new W3CBaggagePropagator()],\n })\n\n context.setGlobalContextManager(contextManager)\n propagation.setGlobalPropagator(propagator)\n\n const provider = new NodeTracerProvider({\n resource: new Resource({\n [ATTR_SERVICE_NAME]: SERVICE_NAME,\n }),\n spanProcessors: [new LatitudeSpanProcessor(apiKey, projectSlug, processorOptions)],\n })\n\n provider.register()\n\n const ready = registerLatitudeInstrumentations({\n instrumentations,\n tracerProvider: provider,\n }).catch((err) => {\n console.warn(\"[Latitude] Failed to register instrumentations:\", err)\n })\n\n const shutdown = async (): Promise<void> => {\n await provider.shutdown()\n }\n\n const flush = async (): Promise<void> => {\n await provider.forceFlush()\n }\n\n const handleShutdown = async () => {\n try {\n await shutdown()\n } catch (err) {\n console.error(\"Error during Latitude Telemetry shutdown:\", err)\n }\n }\n\n if (!shutdownHandlersRegistered) {\n process.once(\"SIGTERM\", handleShutdown)\n process.once(\"SIGINT\", handleShutdown)\n shutdownHandlersRegistered = true\n }\n\n return {\n provider,\n flush,\n shutdown,\n ready,\n }\n}\n","import type { TracerProvider } from \"@opentelemetry/api\"\nimport { type Instrumentation, registerInstrumentations } from \"@opentelemetry/instrumentation\"\nimport { AnthropicInstrumentation } from \"@traceloop/instrumentation-anthropic\"\nimport { BedrockInstrumentation } from \"@traceloop/instrumentation-bedrock\"\nimport { CohereInstrumentation } from \"@traceloop/instrumentation-cohere\"\nimport { LangChainInstrumentation } from \"@traceloop/instrumentation-langchain\"\nimport { LlamaIndexInstrumentation } from \"@traceloop/instrumentation-llamaindex\"\nimport { OpenAIInstrumentation } from \"@traceloop/instrumentation-openai\"\nimport { TogetherInstrumentation } from \"@traceloop/instrumentation-together\"\nimport { AIPlatformInstrumentation, VertexAIInstrumentation } from \"@traceloop/instrumentation-vertexai\"\n\n/**\n * Supported LLM instrumentation types.\n * Use these string identifiers to enable auto-instrumentation.\n */\nexport type InstrumentationType =\n | \"openai\"\n | \"anthropic\"\n | \"bedrock\"\n | \"cohere\"\n | \"langchain\"\n | \"llamaindex\"\n | \"togetherai\"\n | \"vertexai\"\n | \"aiplatform\"\n\n/**\n * Minimal interface for LLM instrumentation instances.\n * Extends OpenTelemetry's Instrumentation interface.\n */\ninterface LlmInstrumentation extends Instrumentation {\n manuallyInstrument?(module: unknown): void\n}\n\n/**\n * Options for creating LLM instrumentations.\n */\ninterface CreateInstrumentationsOptions {\n /** List of instrumentation types to enable. */\n instrumentations: InstrumentationType[]\n /**\n * Optional module references for auto-instrumentation.\n * If not provided, the instrumentation will attempt to require the module.\n * Used for Traceloop-based instrumentations.\n */\n modules?: Partial<Record<InstrumentationType, unknown>>\n /**\n * Per-instrumentation token enrichment settings.\n * @default { openai: true }\n */\n enrichTokens?: Partial<Record<InstrumentationType, boolean>>\n}\n\ninterface InstrumentationConfig {\n ctor: new (config?: Record<string, unknown>) => LlmInstrumentation\n moduleName: string\n defaultEnrichTokens?: boolean\n}\n\nconst INSTRUMENTATION_MAP: Record<InstrumentationType, InstrumentationConfig> = {\n openai: { ctor: OpenAIInstrumentation, moduleName: \"openai\", defaultEnrichTokens: true },\n anthropic: { ctor: AnthropicInstrumentation, moduleName: \"@anthropic-ai/sdk\" },\n bedrock: { ctor: BedrockInstrumentation, moduleName: \"@aws-sdk/client-bedrock-runtime\" },\n cohere: { ctor: CohereInstrumentation, moduleName: \"cohere-ai\" },\n langchain: { ctor: LangChainInstrumentation, moduleName: \"langchain\" },\n llamaindex: { ctor: LlamaIndexInstrumentation, moduleName: \"llamaindex\" },\n togetherai: { ctor: TogetherInstrumentation, moduleName: \"together-ai\", defaultEnrichTokens: false },\n vertexai: { ctor: VertexAIInstrumentation, moduleName: \"@google-cloud/vertexai\" },\n aiplatform: { ctor: AIPlatformInstrumentation, moduleName: \"@google-cloud/aiplatform\" },\n}\n\n/**\n * Internal function to create LLM instrumentation instances.\n * Not exported publicly - use registerLatitudeInstrumentations instead.\n */\nasync function createLatitudeInstrumentations(options: CreateInstrumentationsOptions): Promise<LlmInstrumentation[]> {\n const result: LlmInstrumentation[] = []\n\n for (const type of options.instrumentations) {\n const config = INSTRUMENTATION_MAP[type]\n if (!config) {\n console.warn(`[Latitude] Unknown instrumentation type: ${type}`)\n continue\n }\n\n const enrichTokens = options.enrichTokens?.[type] ?? config.defaultEnrichTokens\n const inst = new config.ctor(enrichTokens !== undefined ? { enrichTokens } : undefined)\n\n // Get module from explicit options or try to auto-require\n const moduleRef = options.modules?.[type] ?? (await tryRequire(config.moduleName))\n if (!moduleRef) {\n console.warn(\n `[Latitude] Module not found for ${type}: ${config.moduleName}. Install it or pass it explicitly in 'modules'.`,\n )\n continue\n }\n inst.manuallyInstrument?.(moduleRef)\n\n result.push(inst)\n }\n\n return result\n}\n\nasync function tryRequire(moduleName: string): Promise<unknown | undefined> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require(moduleName)\n } catch {\n // Fallback to dynamic import for ESM environments\n try {\n const mod = await import(moduleName)\n return mod.default ?? mod\n } catch {\n return undefined\n }\n }\n}\n\n/**\n * Registers LLM instrumentations with the global OpenTelemetry instrumentation registry.\n *\n * This is a convenience wrapper around `createLatitudeInstrumentations` and\n * `@opentelemetry/instrumentation`'s `registerInstrumentations`.\n *\n * @example\n * ```typescript\n * import { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\"\n * import { registerLatitudeInstrumentations, LatitudeSpanProcessor } from \"@latitude-data/telemetry\"\n *\n * const provider = new NodeTracerProvider({\n * spanProcessors: [new LatitudeSpanProcessor(apiKey, projectSlug)],\n * })\n *\n * await registerLatitudeInstrumentations({\n * instrumentations: [\"openai\", \"anthropic\"],\n * tracerProvider: provider,\n * })\n *\n * provider.register()\n * ```\n */\nexport async function registerLatitudeInstrumentations(\n options: CreateInstrumentationsOptions & { tracerProvider: TracerProvider },\n): Promise<void> {\n const instrumentations = await createLatitudeInstrumentations(options)\n registerInstrumentations({\n instrumentations,\n tracerProvider: options.tracerProvider,\n })\n}\n","import type { Context } from \"@opentelemetry/api\"\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\"\nimport {\n BatchSpanProcessor,\n type ReadableSpan,\n SimpleSpanProcessor,\n type Span,\n type SpanProcessor,\n} from \"@opentelemetry/sdk-trace-node\"\nimport { ATTRIBUTES } from \"../constants/index.ts\"\nimport { env } from \"../env/index.ts\"\nimport { getLatitudeContext } from \"./context.ts\"\nimport { DEFAULT_REDACT_SPAN_PROCESSOR, RedactSpanProcessor } from \"./redact.ts\"\nimport {\n buildShouldExportSpanFromFields,\n ExportFilterSpanProcessor,\n RedactThenExportSpanProcessor,\n} from \"./span-filter.ts\"\nimport type { LatitudeSpanProcessorOptions } from \"./types.ts\"\n\nexport class LatitudeSpanProcessor implements SpanProcessor {\n private readonly tail: SpanProcessor\n\n constructor(apiKey: string, projectSlug: string, options?: LatitudeSpanProcessorOptions) {\n if (!apiKey || apiKey.trim() === \"\") {\n throw new Error(\"[Latitude] apiKey is required and cannot be empty\")\n }\n if (!projectSlug || projectSlug.trim() === \"\") {\n throw new Error(\"[Latitude] projectSlug is required and cannot be empty\")\n }\n\n const exporter =\n options?.exporter ??\n new OTLPTraceExporter({\n url: `${env.EXPORTER_URL}/v1/traces`,\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n \"X-Latitude-Project\": projectSlug,\n },\n timeoutMillis: 30_000,\n })\n\n const redact = options?.disableRedact\n ? null\n : options?.redact\n ? new RedactSpanProcessor(options.redact)\n : DEFAULT_REDACT_SPAN_PROCESSOR()\n\n const batchOrSimple = options?.disableBatch ? new SimpleSpanProcessor(exporter) : new BatchSpanProcessor(exporter)\n\n const shouldExport = buildShouldExportSpanFromFields({\n disableSmartFilter: options?.disableSmartFilter,\n shouldExportSpan: options?.shouldExportSpan,\n blockedInstrumentationScopes: options?.blockedInstrumentationScopes,\n })\n\n const redactThenExport = new RedactThenExportSpanProcessor(redact, batchOrSimple)\n this.tail = new ExportFilterSpanProcessor(shouldExport, redactThenExport)\n }\n\n onStart(span: Span, parentContext: Context): void {\n const latitudeData = getLatitudeContext(parentContext)\n\n if (latitudeData) {\n if (latitudeData.name) {\n span.setAttribute(ATTRIBUTES.name, latitudeData.name)\n // Only update span name for the capture root span (has latitude.capture.root attr)\n // Child spans keep their original names (database.query, business.validate, etc.)\n if (span.attributes[\"latitude.capture.root\"]) {\n span.updateName(latitudeData.name)\n }\n }\n if (latitudeData.tags && latitudeData.tags.length > 0) {\n span.setAttribute(ATTRIBUTES.tags, JSON.stringify(latitudeData.tags))\n }\n if (latitudeData.metadata && Object.keys(latitudeData.metadata).length > 0) {\n span.setAttribute(ATTRIBUTES.metadata, JSON.stringify(latitudeData.metadata))\n }\n if (latitudeData.sessionId) {\n span.setAttribute(ATTRIBUTES.sessionId, latitudeData.sessionId)\n }\n if (latitudeData.userId) {\n span.setAttribute(ATTRIBUTES.userId, latitudeData.userId)\n }\n }\n\n this.tail.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n this.tail.onEnd(span)\n }\n\n async forceFlush(): Promise<void> {\n await this.tail.forceFlush()\n }\n\n async shutdown(): Promise<void> {\n await this.tail.shutdown()\n }\n}\n","export const ATTRIBUTES = {\n name: \"latitude.capture.name\",\n tags: \"latitude.tags\",\n metadata: \"latitude.metadata\",\n sessionId: \"session.id\",\n userId: \"user.id\",\n} as const\n","export const SCOPE_LATITUDE = \"so.latitude.instrumentation\"\n\nexport enum InstrumentationScope {\n Manual = \"manual\",\n OpenAI = \"openai\",\n Anthropic = \"anthropic\",\n AzureOpenAI = \"azure\",\n VercelAI = \"vercelai\",\n VertexAI = \"vertexai\",\n AIPlatform = \"aiplatform\",\n MistralAI = \"mistralai\",\n Bedrock = \"bedrock\",\n Sagemaker = \"sagemaker\",\n TogetherAI = \"togetherai\",\n Replicate = \"replicate\",\n Groq = \"groq\",\n Cohere = \"cohere\",\n LiteLLM = \"litellm\",\n Langchain = \"langchain\",\n LlamaIndex = \"llamaindex\",\n DSPy = \"dspy\",\n Haystack = \"haystack\",\n Ollama = \"ollama\",\n Transformers = \"transformers\",\n AlephAlpha = \"alephalpha\",\n}\n","const DEFAULT_EXPORTER_URL =\n {\n production: \"https://ingest.latitude.so\",\n development: \"http://localhost:3002\",\n test: \"http://localhost:3002\",\n }[process.env.NODE_ENV ?? \"development\"] ?? \"http://localhost:3002\"\n\nfunction getExporterUrl() {\n if (process.env.LATITUDE_TELEMETRY_URL) {\n return process.env.LATITUDE_TELEMETRY_URL\n }\n\n return DEFAULT_EXPORTER_URL\n}\n\nexport const env = { EXPORTER_URL: getExporterUrl() } as const\n","import type * as otel from \"@opentelemetry/api\"\nimport type { ReadableSpan, Span, SpanProcessor } from \"@opentelemetry/sdk-trace-node\"\n\nexport interface RedactSpanProcessorOptions {\n attributes: (string | RegExp)[]\n mask?: (attribute: string, value: unknown) => string\n}\n\nexport class RedactSpanProcessor implements SpanProcessor {\n private options: RedactSpanProcessorOptions\n\n constructor(options: RedactSpanProcessorOptions) {\n this.options = options\n\n if (!options.mask) {\n this.options.mask = (_attribute: string, _value: unknown) => \"******\"\n }\n }\n\n onStart(_span: Span, _context: otel.Context): void {\n // Noop\n }\n\n onEnd(span: ReadableSpan): void {\n Object.assign(span.attributes, this.redactAttributes(span.attributes))\n for (const event of span.events) {\n if (!event.attributes) continue\n Object.assign(event.attributes, this.redactAttributes(event.attributes))\n }\n for (const link of span.links) {\n if (!link.attributes) continue\n Object.assign(link.attributes, this.redactAttributes(link.attributes))\n }\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n private shouldRedact(attribute: string) {\n return this.options.attributes.some((pattern) => {\n if (typeof pattern === \"string\") {\n return attribute === pattern\n } else if (pattern instanceof RegExp) {\n return pattern.test(attribute)\n }\n return false\n })\n }\n\n private redactAttributes(attributes: otel.Attributes) {\n const redacted: otel.Attributes = {}\n\n for (const [key, value] of Object.entries(attributes)) {\n if (this.shouldRedact(key)) {\n redacted[key] = this.options.mask?.(key, value)\n }\n }\n\n return redacted\n }\n}\n\nexport const DEFAULT_REDACT_SPAN_PROCESSOR = () =>\n new RedactSpanProcessor({\n attributes: [\n // HTTP security headers\n /^http\\.request\\.header\\.authorization$/i,\n /^http\\.request\\.header\\.cookie$/i,\n /^http\\.request\\.header\\.x[-_]api[-_]key$/i,\n // Database statements may contain sensitive data\n /^db\\.statement$/i,\n ],\n })\n","import type { Context } from \"@opentelemetry/api\"\nimport type { ReadableSpan, Span, SpanProcessor } from \"@opentelemetry/sdk-trace-node\"\nimport { SCOPE_LATITUDE } from \"../constants/scope.ts\"\n\n/** OpenTelemetry GenAI semantic convention attribute prefix. */\nconst GEN_AI_PREFIX = \"gen_ai.\"\n\n/** Legacy / OpenInference-style LLM attribute prefix. */\nconst LLM_PREFIX = \"llm.\"\n\nconst OPENINFERENCE_KIND = \"openinference.span.kind\"\n\n/** OTel Python instrumentation scope prefixes for LLM-related instrumentors we support. */\nconst OTEL_LLM_INSTRUMENTATION_SCOPE_PREFIXES = [\n \"opentelemetry.instrumentation.alephalpha\",\n \"opentelemetry.instrumentation.anthropic\",\n \"opentelemetry.instrumentation.bedrock\",\n \"opentelemetry.instrumentation.cohere\",\n \"opentelemetry.instrumentation.crewai\",\n \"opentelemetry.instrumentation.google_generativeai\",\n \"opentelemetry.instrumentation.groq\",\n \"opentelemetry.instrumentation.haystack\",\n \"opentelemetry.instrumentation.langchain\",\n \"opentelemetry.instrumentation.llamaindex\",\n \"opentelemetry.instrumentation.mistralai\",\n \"opentelemetry.instrumentation.ollama\",\n \"opentelemetry.instrumentation.openai\",\n \"opentelemetry.instrumentation.replicate\",\n \"opentelemetry.instrumentation.sagemaker\",\n \"opentelemetry.instrumentation.together\",\n \"opentelemetry.instrumentation.transformers\",\n \"opentelemetry.instrumentation.vertexai\",\n \"opentelemetry.instrumentation.watsonx\",\n \"openinference.instrumentation\",\n] as const\n\n/** Substrings in scope names that indicate LLM / GenAI instrumentation (e.g. Traceloop JS). */\nconst LLM_SCOPE_SUBSTRINGS = [\"openinference\", \"traceloop\", \"langsmith\", \"litellm\"] as const\n\nexport type SmartFilterOptions = {\n /**\n * When true, all spans are exported (legacy behavior).\n * Default false — only LLM-relevant spans are exported.\n */\n disableSmartFilter?: boolean\n /**\n * When smart filter is on, also export spans for which this returns true\n * (in addition to {@link isDefaultExportSpan}).\n */\n shouldExportSpan?: (span: ReadableSpan) => boolean\n /** Instrumentation scope names to drop (exact match) even if they pass the default predicate. */\n blockedInstrumentationScopes?: string[]\n}\n\n/** Input for {@link buildShouldExportSpanFromFields}; allows `undefined` field values for ergonomics. */\nexport type SmartFilterFieldsInput = {\n disableSmartFilter?: boolean | undefined\n shouldExportSpan?: ((span: ReadableSpan) => boolean) | undefined\n blockedInstrumentationScopes?: string[] | undefined\n}\n\n/**\n * Builds the export predicate from loose option fields (`exactOptionalPropertyTypes`-safe call sites).\n */\nexport function buildShouldExportSpanFromFields(fields: SmartFilterFieldsInput): (span: ReadableSpan) => boolean {\n return buildShouldExportSpan({\n ...(fields.disableSmartFilter !== undefined ? { disableSmartFilter: fields.disableSmartFilter } : {}),\n ...(fields.shouldExportSpan !== undefined ? { shouldExportSpan: fields.shouldExportSpan } : {}),\n ...(fields.blockedInstrumentationScopes !== undefined\n ? { blockedInstrumentationScopes: fields.blockedInstrumentationScopes }\n : {}),\n })\n}\n\nfunction attributeKeys(span: ReadableSpan): string[] {\n const attrs = span.attributes\n if (!attrs || typeof attrs !== \"object\") return []\n return Object.keys(attrs as Record<string, unknown>)\n}\n\nfunction instrumentationScopeName(span: ReadableSpan): string {\n return span.instrumentationLibrary?.name ?? \"\"\n}\n\n/** True if the span uses OpenTelemetry GenAI semantic conventions or common LLM attribute namespaces. */\nexport function isGenAiOrLlmAttributeSpan(span: ReadableSpan): boolean {\n for (const key of attributeKeys(span)) {\n if (key.startsWith(GEN_AI_PREFIX) || key.startsWith(LLM_PREFIX)) return true\n if (key === OPENINFERENCE_KIND || key.startsWith(\"openinference.\")) return true\n // Vercel AI SDK uses ai.* prefix\n if (key.startsWith(\"ai.\")) return true\n // Latitude context attributes\n if (key.startsWith(\"latitude.\")) return true\n }\n return false\n}\n\n/** True if the span was created with Latitude's tracer scopes. */\nexport function isLatitudeInstrumentationSpan(span: ReadableSpan): boolean {\n const name = instrumentationScopeName(span)\n return name === SCOPE_LATITUDE || name.startsWith(`${SCOPE_LATITUDE}.`)\n}\n\nfunction isKnownLlmInstrumentationScope(span: ReadableSpan): boolean {\n const name = instrumentationScopeName(span)\n if (!name) return false\n for (const prefix of OTEL_LLM_INSTRUMENTATION_SCOPE_PREFIXES) {\n if (name === prefix || name.startsWith(`${prefix}.`)) return true\n }\n const lower = name.toLowerCase()\n for (const part of LLM_SCOPE_SUBSTRINGS) {\n if (lower.includes(part)) return true\n }\n return false\n}\n\n/**\n * Default export predicate (smart filter): Latitude scopes, GenAI / LLM attributes,\n * or known LLM instrumentation scopes.\n */\nexport function isDefaultExportSpan(span: ReadableSpan): boolean {\n if (isLatitudeInstrumentationSpan(span)) return true\n if (isGenAiOrLlmAttributeSpan(span)) return true\n if (isKnownLlmInstrumentationScope(span)) return true\n return false\n}\n\nexport function buildShouldExportSpan(options: SmartFilterOptions): (span: ReadableSpan) => boolean {\n if (options.disableSmartFilter) return () => true\n const blocked = new Set(options.blockedInstrumentationScopes ?? [])\n const extra = options.shouldExportSpan\n return (span: ReadableSpan) => {\n const scope = instrumentationScopeName(span)\n if (blocked.has(scope)) return false\n if (isDefaultExportSpan(span)) return true\n if (extra?.(span)) return true\n return false\n }\n}\n\n/**\n * Drops spans that fail the export predicate before passing them to the inner processor.\n * Inner processor should perform redaction and export.\n */\nexport class ExportFilterSpanProcessor implements SpanProcessor {\n private readonly shouldExport: (span: ReadableSpan) => boolean\n private readonly inner: SpanProcessor\n\n constructor(shouldExport: (span: ReadableSpan) => boolean, inner: SpanProcessor) {\n this.shouldExport = shouldExport\n this.inner = inner\n }\n\n onStart(span: Span, parentContext: Context): void {\n this.inner.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n if (!this.shouldExport(span)) return\n this.inner.onEnd(span)\n }\n\n forceFlush(): Promise<void> {\n return this.inner.forceFlush()\n }\n\n shutdown(): Promise<void> {\n return this.inner.shutdown()\n }\n}\n\n/** Runs optional redaction then the export processor (batch/simple). */\nexport class RedactThenExportSpanProcessor implements SpanProcessor {\n private readonly redact: SpanProcessor | null\n private readonly exportProcessor: SpanProcessor\n\n constructor(redact: SpanProcessor | null, exportProcessor: SpanProcessor) {\n this.redact = redact\n this.exportProcessor = exportProcessor\n }\n\n onStart(span: Span, parentContext: Context): void {\n this.redact?.onStart(span, parentContext)\n this.exportProcessor.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n this.redact?.onEnd(span)\n this.exportProcessor.onEnd(span)\n }\n\n forceFlush(): Promise<void> {\n return this.exportProcessor.forceFlush()\n }\n\n shutdown(): Promise<void> {\n return this.exportProcessor.shutdown()\n }\n}\n"],"mappings":"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","names":["context","context"]}
1
+ {"version":3,"sources":["../src/sdk/context.ts","../src/sdk/init.ts","../src/sdk/instrumentations.ts","../src/sdk/processor.ts","../src/constants/attributes.ts","../src/constants/scope.ts","../src/env/env.ts","../src/sdk/redact.ts","../src/sdk/span-filter.ts"],"sourcesContent":["import { type Context, context, createContextKey, trace } from \"@opentelemetry/api\"\nimport type { ContextOptions } from \"./types.ts\"\n\nexport const LATITUDE_CONTEXT_KEY = createContextKey(\"latitude-internal-context\")\nconst CAPTURE_TRACER_NAME = \"so.latitude.instrumentation.capture\"\n\ntype LatitudeContextData = {\n name: string | undefined\n tags: string[] | undefined\n metadata: Record<string, unknown> | undefined\n sessionId: string | undefined\n userId: string | undefined\n}\n\nexport function getLatitudeContext(ctx: Context): LatitudeContextData | undefined {\n return ctx.getValue(LATITUDE_CONTEXT_KEY) as LatitudeContextData | undefined\n}\n\nfunction mergeArrays<T>(a: T[] | undefined, b: T[] | undefined): T[] | undefined {\n if (!a && !b) return undefined\n if (!a) return b\n if (!b) return a\n return [...new Set([...a, ...b])]\n}\n\nexport function capture<T>(name: string, fn: () => T | Promise<T>, options: ContextOptions = {}): T | Promise<T> {\n const currentContext = context.active()\n const existingData = getLatitudeContext(currentContext)\n\n const mergedData: LatitudeContextData = {\n name: options.name ?? name,\n tags: mergeArrays(existingData?.tags, options.tags),\n metadata: { ...existingData?.metadata, ...options.metadata },\n sessionId: options.sessionId ?? existingData?.sessionId,\n userId: options.userId ?? existingData?.userId,\n }\n\n const newContext = currentContext.setValue(LATITUDE_CONTEXT_KEY, mergedData)\n const existingSpan = trace.getSpan(currentContext)\n\n if (existingSpan) {\n return context.with(newContext, fn)\n }\n\n const tracer = trace.getTracer(CAPTURE_TRACER_NAME)\n\n return tracer.startActiveSpan(name, { attributes: { \"latitude.capture.root\": true } }, newContext, (span) => {\n let result: T | Promise<T>\n try {\n result = fn()\n } catch (error) {\n span.recordException(error as Error)\n span.end()\n throw error\n }\n\n if (result instanceof Promise) {\n return result\n .catch((error) => {\n span.recordException(error as Error)\n throw error\n })\n .finally(() => {\n span.end()\n }) as T | Promise<T>\n }\n\n span.end()\n return result\n })\n}\n","import { context, propagation } from \"@opentelemetry/api\"\nimport { AsyncLocalStorageContextManager } from \"@opentelemetry/context-async-hooks\"\nimport { CompositePropagator, W3CBaggagePropagator, W3CTraceContextPropagator } from \"@opentelemetry/core\"\nimport { resourceFromAttributes } from \"@opentelemetry/resources\"\nimport { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\"\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\"\nimport { registerLatitudeInstrumentations } from \"./instrumentations.ts\"\nimport { LatitudeSpanProcessor } from \"./processor.ts\"\nimport type { InitLatitudeOptions } from \"./types.ts\"\n\nconst SERVICE_NAME = process.env.npm_package_name || \"unknown\"\n\n/** Module-level flag to prevent duplicate signal handler registration on repeated initLatitude calls */\nlet shutdownHandlersRegistered = false\n\nexport function initLatitude(options: InitLatitudeOptions): {\n provider: NodeTracerProvider\n flush: () => Promise<void>\n shutdown: () => Promise<void>\n ready: Promise<void>\n} {\n const { apiKey, projectSlug, instrumentations = [], ...processorOptions } = options\n\n if (!apiKey || apiKey.trim() === \"\") {\n throw new Error(\"[Latitude] apiKey is required and cannot be empty\")\n }\n if (!projectSlug || projectSlug.trim() === \"\") {\n throw new Error(\"[Latitude] projectSlug is required and cannot be empty\")\n }\n\n const contextManager = new AsyncLocalStorageContextManager()\n contextManager.enable()\n\n const propagator = new CompositePropagator({\n propagators: [new W3CTraceContextPropagator(), new W3CBaggagePropagator()],\n })\n\n context.setGlobalContextManager(contextManager)\n propagation.setGlobalPropagator(propagator)\n\n const resourceServiceName =\n typeof processorOptions.serviceName === \"string\" && processorOptions.serviceName.trim() !== \"\"\n ? processorOptions.serviceName.trim()\n : SERVICE_NAME\n\n const provider = new NodeTracerProvider({\n resource: resourceFromAttributes({\n [ATTR_SERVICE_NAME]: resourceServiceName,\n }),\n spanProcessors: [new LatitudeSpanProcessor(apiKey, projectSlug, processorOptions)],\n })\n\n provider.register()\n\n const ready = registerLatitudeInstrumentations({\n instrumentations,\n tracerProvider: provider,\n }).catch((err) => {\n console.warn(\"[Latitude] Failed to register instrumentations:\", err)\n })\n\n const shutdown = async (): Promise<void> => {\n await provider.shutdown()\n }\n\n const flush = async (): Promise<void> => {\n await provider.forceFlush()\n }\n\n const handleShutdown = async () => {\n try {\n await shutdown()\n } catch (err) {\n console.error(\"Error during Latitude Telemetry shutdown:\", err)\n }\n }\n\n if (!shutdownHandlersRegistered) {\n process.once(\"SIGTERM\", handleShutdown)\n process.once(\"SIGINT\", handleShutdown)\n shutdownHandlersRegistered = true\n }\n\n return {\n provider,\n flush,\n shutdown,\n ready,\n }\n}\n","import type { TracerProvider } from \"@opentelemetry/api\"\nimport { type Instrumentation, registerInstrumentations } from \"@opentelemetry/instrumentation\"\nimport { AnthropicInstrumentation } from \"@traceloop/instrumentation-anthropic\"\nimport { BedrockInstrumentation } from \"@traceloop/instrumentation-bedrock\"\nimport { CohereInstrumentation } from \"@traceloop/instrumentation-cohere\"\nimport { LangChainInstrumentation } from \"@traceloop/instrumentation-langchain\"\nimport { LlamaIndexInstrumentation } from \"@traceloop/instrumentation-llamaindex\"\nimport { OpenAIInstrumentation } from \"@traceloop/instrumentation-openai\"\nimport { TogetherInstrumentation } from \"@traceloop/instrumentation-together\"\nimport { AIPlatformInstrumentation, VertexAIInstrumentation } from \"@traceloop/instrumentation-vertexai\"\n\n/**\n * Supported LLM instrumentation types.\n * Use these string identifiers to enable auto-instrumentation.\n */\nexport type InstrumentationType =\n | \"openai\"\n | \"anthropic\"\n | \"bedrock\"\n | \"cohere\"\n | \"langchain\"\n | \"llamaindex\"\n | \"togetherai\"\n | \"vertexai\"\n | \"aiplatform\"\n\n/**\n * Minimal interface for LLM instrumentation instances.\n * Extends OpenTelemetry's Instrumentation interface.\n */\ninterface LlmInstrumentation extends Instrumentation {\n manuallyInstrument?(module: unknown): void\n}\n\n/**\n * Options for creating LLM instrumentations.\n */\ninterface CreateInstrumentationsOptions {\n /** List of instrumentation types to enable. */\n instrumentations: InstrumentationType[]\n /**\n * Optional module references for auto-instrumentation.\n * If not provided, the instrumentation will attempt to require the module.\n * Used for Traceloop-based instrumentations.\n */\n modules?: Partial<Record<InstrumentationType, unknown>>\n /**\n * Per-instrumentation token enrichment settings.\n * @default { openai: true }\n */\n enrichTokens?: Partial<Record<InstrumentationType, boolean>>\n}\n\ninterface InstrumentationConfig {\n ctor: new (config?: Record<string, unknown>) => LlmInstrumentation\n moduleName: string\n defaultEnrichTokens?: boolean\n}\n\nconst INSTRUMENTATION_MAP: Record<InstrumentationType, InstrumentationConfig> = {\n openai: { ctor: OpenAIInstrumentation, moduleName: \"openai\", defaultEnrichTokens: true },\n anthropic: { ctor: AnthropicInstrumentation, moduleName: \"@anthropic-ai/sdk\" },\n bedrock: { ctor: BedrockInstrumentation, moduleName: \"@aws-sdk/client-bedrock-runtime\" },\n cohere: { ctor: CohereInstrumentation, moduleName: \"cohere-ai\" },\n langchain: { ctor: LangChainInstrumentation, moduleName: \"langchain\" },\n llamaindex: { ctor: LlamaIndexInstrumentation, moduleName: \"llamaindex\" },\n togetherai: { ctor: TogetherInstrumentation, moduleName: \"together-ai\", defaultEnrichTokens: false },\n vertexai: { ctor: VertexAIInstrumentation, moduleName: \"@google-cloud/vertexai\" },\n aiplatform: { ctor: AIPlatformInstrumentation, moduleName: \"@google-cloud/aiplatform\" },\n}\n\n/**\n * Internal function to create LLM instrumentation instances.\n * Not exported publicly - use registerLatitudeInstrumentations instead.\n */\nasync function createLatitudeInstrumentations(options: CreateInstrumentationsOptions): Promise<LlmInstrumentation[]> {\n const result: LlmInstrumentation[] = []\n\n for (const type of options.instrumentations) {\n const config = INSTRUMENTATION_MAP[type]\n if (!config) {\n console.warn(`[Latitude] Unknown instrumentation type: ${type}`)\n continue\n }\n\n const enrichTokens = options.enrichTokens?.[type] ?? config.defaultEnrichTokens\n const inst = new config.ctor(enrichTokens !== undefined ? { enrichTokens } : undefined)\n\n // Get module from explicit options or try to auto-require\n const moduleRef = options.modules?.[type] ?? (await tryRequire(config.moduleName))\n if (!moduleRef) {\n console.warn(\n `[Latitude] Module not found for ${type}: ${config.moduleName}. Install it or pass it explicitly in 'modules'.`,\n )\n continue\n }\n inst.manuallyInstrument?.(moduleRef)\n\n result.push(inst)\n }\n\n return result\n}\n\nasync function tryRequire(moduleName: string): Promise<unknown | undefined> {\n try {\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n return require(moduleName)\n } catch {\n // Fallback to dynamic import for ESM environments\n try {\n const mod = await import(moduleName)\n return mod.default ?? mod\n } catch {\n return undefined\n }\n }\n}\n\n/**\n * Registers LLM instrumentations with the global OpenTelemetry instrumentation registry.\n *\n * This is a convenience wrapper around `createLatitudeInstrumentations` and\n * `@opentelemetry/instrumentation`'s `registerInstrumentations`.\n *\n * @example\n * ```typescript\n * import { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\"\n * import { registerLatitudeInstrumentations, LatitudeSpanProcessor } from \"@latitude-data/telemetry\"\n *\n * const provider = new NodeTracerProvider({\n * spanProcessors: [new LatitudeSpanProcessor(apiKey, projectSlug)],\n * })\n *\n * await registerLatitudeInstrumentations({\n * instrumentations: [\"openai\", \"anthropic\"],\n * tracerProvider: provider,\n * })\n *\n * provider.register()\n * ```\n */\nexport async function registerLatitudeInstrumentations(\n options: CreateInstrumentationsOptions & { tracerProvider: TracerProvider },\n): Promise<void> {\n const instrumentations = await createLatitudeInstrumentations(options)\n registerInstrumentations({\n instrumentations,\n tracerProvider: options.tracerProvider,\n })\n}\n","import type { Context } from \"@opentelemetry/api\"\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\"\nimport {\n BatchSpanProcessor,\n type ReadableSpan,\n SimpleSpanProcessor,\n type Span,\n type SpanProcessor,\n} from \"@opentelemetry/sdk-trace-node\"\nimport { ATTR_SERVICE_NAME } from \"@opentelemetry/semantic-conventions\"\nimport { ATTRIBUTES } from \"../constants/index.ts\"\nimport { env } from \"../env/index.ts\"\nimport { getLatitudeContext } from \"./context.ts\"\nimport { DEFAULT_REDACT_SPAN_PROCESSOR, RedactSpanProcessor } from \"./redact.ts\"\nimport {\n buildShouldExportSpanFromFields,\n ExportFilterSpanProcessor,\n RedactThenExportSpanProcessor,\n} from \"./span-filter.ts\"\nimport type { LatitudeSpanProcessorOptions } from \"./types.ts\"\n\nexport class LatitudeSpanProcessor implements SpanProcessor {\n private readonly tail: SpanProcessor\n private readonly serviceName: string | undefined\n\n constructor(apiKey: string, projectSlug: string, options?: LatitudeSpanProcessorOptions) {\n if (!apiKey || apiKey.trim() === \"\") {\n throw new Error(\"[Latitude] apiKey is required and cannot be empty\")\n }\n if (!projectSlug || projectSlug.trim() === \"\") {\n throw new Error(\"[Latitude] projectSlug is required and cannot be empty\")\n }\n\n const exporter =\n options?.exporter ??\n new OTLPTraceExporter({\n url: `${env.EXPORTER_URL}/v1/traces`,\n headers: {\n Authorization: `Bearer ${apiKey}`,\n \"Content-Type\": \"application/json\",\n \"X-Latitude-Project\": projectSlug,\n },\n timeoutMillis: 30_000,\n })\n\n const redact = options?.disableRedact\n ? null\n : options?.redact\n ? new RedactSpanProcessor(options.redact)\n : DEFAULT_REDACT_SPAN_PROCESSOR()\n\n const batchOrSimple = options?.disableBatch ? new SimpleSpanProcessor(exporter) : new BatchSpanProcessor(exporter)\n\n const shouldExport = buildShouldExportSpanFromFields({\n disableSmartFilter: options?.disableSmartFilter,\n shouldExportSpan: options?.shouldExportSpan,\n blockedInstrumentationScopes: options?.blockedInstrumentationScopes,\n })\n\n const redactThenExport = new RedactThenExportSpanProcessor(redact, batchOrSimple)\n this.tail = new ExportFilterSpanProcessor(shouldExport, redactThenExport)\n\n const rawServiceName = options?.serviceName?.trim()\n this.serviceName = rawServiceName === \"\" ? undefined : rawServiceName\n }\n\n onStart(span: Span, parentContext: Context): void {\n if (this.serviceName !== undefined) {\n span.setAttribute(ATTR_SERVICE_NAME, this.serviceName)\n }\n\n const latitudeData = getLatitudeContext(parentContext)\n\n if (latitudeData) {\n if (latitudeData.name) {\n span.setAttribute(ATTRIBUTES.name, latitudeData.name)\n // Only update span name for the capture root span (has latitude.capture.root attr)\n // Child spans keep their original names (database.query, business.validate, etc.)\n if (span.attributes[\"latitude.capture.root\"]) {\n span.updateName(latitudeData.name)\n }\n }\n if (latitudeData.tags && latitudeData.tags.length > 0) {\n span.setAttribute(ATTRIBUTES.tags, JSON.stringify(latitudeData.tags))\n }\n if (latitudeData.metadata && Object.keys(latitudeData.metadata).length > 0) {\n span.setAttribute(ATTRIBUTES.metadata, JSON.stringify(latitudeData.metadata))\n }\n if (latitudeData.sessionId) {\n span.setAttribute(ATTRIBUTES.sessionId, latitudeData.sessionId)\n }\n if (latitudeData.userId) {\n span.setAttribute(ATTRIBUTES.userId, latitudeData.userId)\n }\n }\n\n this.tail.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n this.tail.onEnd(span)\n }\n\n async forceFlush(): Promise<void> {\n await this.tail.forceFlush()\n }\n\n async shutdown(): Promise<void> {\n await this.tail.shutdown()\n }\n}\n","export const ATTRIBUTES = {\n name: \"latitude.capture.name\",\n tags: \"latitude.tags\",\n metadata: \"latitude.metadata\",\n sessionId: \"session.id\",\n userId: \"user.id\",\n} as const\n","export const SCOPE_LATITUDE = \"so.latitude.instrumentation\"\n\nexport enum InstrumentationScope {\n Manual = \"manual\",\n OpenAI = \"openai\",\n Anthropic = \"anthropic\",\n AzureOpenAI = \"azure\",\n VercelAI = \"vercelai\",\n VertexAI = \"vertexai\",\n AIPlatform = \"aiplatform\",\n MistralAI = \"mistralai\",\n Bedrock = \"bedrock\",\n Sagemaker = \"sagemaker\",\n TogetherAI = \"togetherai\",\n Replicate = \"replicate\",\n Groq = \"groq\",\n Cohere = \"cohere\",\n LiteLLM = \"litellm\",\n Langchain = \"langchain\",\n LlamaIndex = \"llamaindex\",\n DSPy = \"dspy\",\n Haystack = \"haystack\",\n Ollama = \"ollama\",\n Transformers = \"transformers\",\n AlephAlpha = \"alephalpha\",\n}\n","const DEFAULT_EXPORTER_URL =\n {\n production: \"https://ingest.latitude.so\",\n development: \"http://localhost:3002\",\n test: \"http://localhost:3002\",\n }[process.env.NODE_ENV ?? \"development\"] ?? \"http://localhost:3002\"\n\nfunction getExporterUrl() {\n if (process.env.LATITUDE_TELEMETRY_URL) {\n return process.env.LATITUDE_TELEMETRY_URL\n }\n\n return DEFAULT_EXPORTER_URL\n}\n\nexport const env = { EXPORTER_URL: getExporterUrl() } as const\n","import type * as otel from \"@opentelemetry/api\"\nimport type { ReadableSpan, Span, SpanProcessor } from \"@opentelemetry/sdk-trace-node\"\n\nexport interface RedactSpanProcessorOptions {\n attributes: (string | RegExp)[]\n mask?: (attribute: string, value: unknown) => string\n}\n\nexport class RedactSpanProcessor implements SpanProcessor {\n private options: RedactSpanProcessorOptions\n\n constructor(options: RedactSpanProcessorOptions) {\n this.options = options\n\n if (!options.mask) {\n this.options.mask = (_attribute: string, _value: unknown) => \"******\"\n }\n }\n\n onStart(_span: Span, _context: otel.Context): void {\n // Noop\n }\n\n onEnd(span: ReadableSpan): void {\n Object.assign(span.attributes, this.redactAttributes(span.attributes))\n for (const event of span.events) {\n if (!event.attributes) continue\n Object.assign(event.attributes, this.redactAttributes(event.attributes))\n }\n for (const link of span.links) {\n if (!link.attributes) continue\n Object.assign(link.attributes, this.redactAttributes(link.attributes))\n }\n }\n\n forceFlush(): Promise<void> {\n return Promise.resolve()\n }\n\n shutdown(): Promise<void> {\n return Promise.resolve()\n }\n\n private shouldRedact(attribute: string) {\n return this.options.attributes.some((pattern) => {\n if (typeof pattern === \"string\") {\n return attribute === pattern\n } else if (pattern instanceof RegExp) {\n return pattern.test(attribute)\n }\n return false\n })\n }\n\n private redactAttributes(attributes: otel.Attributes) {\n const redacted: otel.Attributes = {}\n\n for (const [key, value] of Object.entries(attributes)) {\n if (this.shouldRedact(key)) {\n redacted[key] = this.options.mask?.(key, value)\n }\n }\n\n return redacted\n }\n}\n\nexport const DEFAULT_REDACT_SPAN_PROCESSOR = () =>\n new RedactSpanProcessor({\n attributes: [\n // HTTP security headers\n /^http\\.request\\.header\\.authorization$/i,\n /^http\\.request\\.header\\.cookie$/i,\n /^http\\.request\\.header\\.x[-_]api[-_]key$/i,\n // Database statements may contain sensitive data\n /^db\\.statement$/i,\n ],\n })\n","import type { Context } from \"@opentelemetry/api\"\nimport type { ReadableSpan, Span, SpanProcessor } from \"@opentelemetry/sdk-trace-node\"\nimport { SCOPE_LATITUDE } from \"../constants/scope.ts\"\n\n/** OpenTelemetry GenAI semantic convention attribute prefix. */\nconst GEN_AI_PREFIX = \"gen_ai.\"\n\n/** Legacy / OpenInference-style LLM attribute prefix. */\nconst LLM_PREFIX = \"llm.\"\n\nconst OPENINFERENCE_KIND = \"openinference.span.kind\"\n\n/** OTel Python instrumentation scope prefixes for LLM-related instrumentors we support. */\nconst OTEL_LLM_INSTRUMENTATION_SCOPE_PREFIXES = [\n \"opentelemetry.instrumentation.alephalpha\",\n \"opentelemetry.instrumentation.anthropic\",\n \"opentelemetry.instrumentation.bedrock\",\n \"opentelemetry.instrumentation.cohere\",\n \"opentelemetry.instrumentation.crewai\",\n \"opentelemetry.instrumentation.google_generativeai\",\n \"opentelemetry.instrumentation.groq\",\n \"opentelemetry.instrumentation.haystack\",\n \"opentelemetry.instrumentation.langchain\",\n \"opentelemetry.instrumentation.llamaindex\",\n \"opentelemetry.instrumentation.mistralai\",\n \"opentelemetry.instrumentation.ollama\",\n \"opentelemetry.instrumentation.openai\",\n \"opentelemetry.instrumentation.replicate\",\n \"opentelemetry.instrumentation.sagemaker\",\n \"opentelemetry.instrumentation.together\",\n \"opentelemetry.instrumentation.transformers\",\n \"opentelemetry.instrumentation.vertexai\",\n \"opentelemetry.instrumentation.watsonx\",\n \"openinference.instrumentation\",\n] as const\n\n/** Substrings in scope names that indicate LLM / GenAI instrumentation (e.g. Traceloop JS). */\nconst LLM_SCOPE_SUBSTRINGS = [\"openinference\", \"traceloop\", \"langsmith\", \"litellm\"] as const\n\nexport type SmartFilterOptions = {\n /**\n * When true, all spans are exported (legacy behavior).\n * Default false — only LLM-relevant spans are exported.\n */\n disableSmartFilter?: boolean\n /**\n * When smart filter is on, also export spans for which this returns true\n * (in addition to {@link isDefaultExportSpan}).\n */\n shouldExportSpan?: (span: ReadableSpan) => boolean\n /** Instrumentation scope names to drop (exact match) even if they pass the default predicate. */\n blockedInstrumentationScopes?: string[]\n}\n\n/** Input for {@link buildShouldExportSpanFromFields}; allows `undefined` field values for ergonomics. */\nexport type SmartFilterFieldsInput = {\n disableSmartFilter?: boolean | undefined\n shouldExportSpan?: ((span: ReadableSpan) => boolean) | undefined\n blockedInstrumentationScopes?: string[] | undefined\n}\n\n/**\n * Builds the export predicate from loose option fields (`exactOptionalPropertyTypes`-safe call sites).\n */\nexport function buildShouldExportSpanFromFields(fields: SmartFilterFieldsInput): (span: ReadableSpan) => boolean {\n return buildShouldExportSpan({\n ...(fields.disableSmartFilter !== undefined ? { disableSmartFilter: fields.disableSmartFilter } : {}),\n ...(fields.shouldExportSpan !== undefined ? { shouldExportSpan: fields.shouldExportSpan } : {}),\n ...(fields.blockedInstrumentationScopes !== undefined\n ? { blockedInstrumentationScopes: fields.blockedInstrumentationScopes }\n : {}),\n })\n}\n\nfunction attributeKeys(span: ReadableSpan): string[] {\n const attrs = span.attributes\n if (!attrs || typeof attrs !== \"object\") return []\n return Object.keys(attrs as Record<string, unknown>)\n}\n\nfunction instrumentationScopeName(span: ReadableSpan): string {\n return span.instrumentationScope?.name ?? \"\"\n}\n\n/** True if the span uses OpenTelemetry GenAI semantic conventions or common LLM attribute namespaces. */\nexport function isGenAiOrLlmAttributeSpan(span: ReadableSpan): boolean {\n for (const key of attributeKeys(span)) {\n if (key.startsWith(GEN_AI_PREFIX) || key.startsWith(LLM_PREFIX)) return true\n if (key === OPENINFERENCE_KIND || key.startsWith(\"openinference.\")) return true\n // Vercel AI SDK uses ai.* prefix\n if (key.startsWith(\"ai.\")) return true\n // Latitude context attributes\n if (key.startsWith(\"latitude.\")) return true\n }\n return false\n}\n\n/** True if the span was created with Latitude's tracer scopes. */\nexport function isLatitudeInstrumentationSpan(span: ReadableSpan): boolean {\n const name = instrumentationScopeName(span)\n return name === SCOPE_LATITUDE || name.startsWith(`${SCOPE_LATITUDE}.`)\n}\n\nfunction isKnownLlmInstrumentationScope(span: ReadableSpan): boolean {\n const name = instrumentationScopeName(span)\n if (!name) return false\n for (const prefix of OTEL_LLM_INSTRUMENTATION_SCOPE_PREFIXES) {\n if (name === prefix || name.startsWith(`${prefix}.`)) return true\n }\n const lower = name.toLowerCase()\n for (const part of LLM_SCOPE_SUBSTRINGS) {\n if (lower.includes(part)) return true\n }\n return false\n}\n\n/**\n * Default export predicate (smart filter): Latitude scopes, GenAI / LLM attributes,\n * or known LLM instrumentation scopes.\n */\nexport function isDefaultExportSpan(span: ReadableSpan): boolean {\n if (isLatitudeInstrumentationSpan(span)) return true\n if (isGenAiOrLlmAttributeSpan(span)) return true\n if (isKnownLlmInstrumentationScope(span)) return true\n return false\n}\n\nexport function buildShouldExportSpan(options: SmartFilterOptions): (span: ReadableSpan) => boolean {\n if (options.disableSmartFilter) return () => true\n const blocked = new Set(options.blockedInstrumentationScopes ?? [])\n const extra = options.shouldExportSpan\n return (span: ReadableSpan) => {\n const scope = instrumentationScopeName(span)\n if (blocked.has(scope)) return false\n if (isDefaultExportSpan(span)) return true\n if (extra?.(span)) return true\n return false\n }\n}\n\n/**\n * Drops spans that fail the export predicate before passing them to the inner processor.\n * Inner processor should perform redaction and export.\n */\nexport class ExportFilterSpanProcessor implements SpanProcessor {\n private readonly shouldExport: (span: ReadableSpan) => boolean\n private readonly inner: SpanProcessor\n\n constructor(shouldExport: (span: ReadableSpan) => boolean, inner: SpanProcessor) {\n this.shouldExport = shouldExport\n this.inner = inner\n }\n\n onStart(span: Span, parentContext: Context): void {\n this.inner.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n if (!this.shouldExport(span)) return\n this.inner.onEnd(span)\n }\n\n forceFlush(): Promise<void> {\n return this.inner.forceFlush()\n }\n\n shutdown(): Promise<void> {\n return this.inner.shutdown()\n }\n}\n\n/** Runs optional redaction then the export processor (batch/simple). */\nexport class RedactThenExportSpanProcessor implements SpanProcessor {\n private readonly redact: SpanProcessor | null\n private readonly exportProcessor: SpanProcessor\n\n constructor(redact: SpanProcessor | null, exportProcessor: SpanProcessor) {\n this.redact = redact\n this.exportProcessor = exportProcessor\n }\n\n onStart(span: Span, parentContext: Context): void {\n this.redact?.onStart(span, parentContext)\n this.exportProcessor.onStart(span, parentContext)\n }\n\n onEnd(span: ReadableSpan): void {\n this.redact?.onEnd(span)\n this.exportProcessor.onEnd(span)\n }\n\n forceFlush(): Promise<void> {\n return this.exportProcessor.forceFlush()\n }\n\n shutdown(): Promise<void> {\n return this.exportProcessor.shutdown()\n }\n}\n"],"mappings":"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","names":["context","ATTR_SERVICE_NAME","context","ATTR_SERVICE_NAME"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@latitude-data/telemetry",
3
- "version": "3.0.0-alpha.1",
3
+ "version": "3.0.0-alpha.3",
4
4
  "description": "Latitude Telemetry for TypeScript",
5
5
  "author": "Latitude Data SL <hello@latitude.so>",
6
6
  "license": "MIT",
@@ -36,14 +36,14 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@opentelemetry/api": "^1.9.0",
39
- "@opentelemetry/context-async-hooks": "^1.30.0",
40
- "@opentelemetry/core": "^1.30.0",
41
- "@opentelemetry/exporter-trace-otlp-http": "^0.57.0",
42
- "@opentelemetry/instrumentation": "^0.57.0",
39
+ "@opentelemetry/context-async-hooks": "^2.6.0",
40
+ "@opentelemetry/core": "^2.6.0",
41
+ "@opentelemetry/exporter-trace-otlp-http": "^0.213.0",
42
+ "@opentelemetry/instrumentation": "^0.213.0",
43
43
  "@traceloop/instrumentation-openai": "^0.22.0",
44
- "@opentelemetry/resources": "^1.30.0",
45
- "@opentelemetry/sdk-trace-node": "^1.30.0",
46
- "@opentelemetry/semantic-conventions": "^1.34.0",
44
+ "@opentelemetry/resources": "^2.6.0",
45
+ "@opentelemetry/sdk-trace-node": "^2.6.0",
46
+ "@opentelemetry/semantic-conventions": "^1.40.0",
47
47
  "@traceloop/instrumentation-anthropic": "^0.22.0",
48
48
  "@traceloop/instrumentation-bedrock": "^0.22.0",
49
49
  "@traceloop/instrumentation-cohere": "^0.22.0",
@@ -63,7 +63,7 @@
63
63
  "typescript": "^5.5.4"
64
64
  },
65
65
  "optionalDependencies": {
66
- "@anthropic-ai/sdk": "^0.81.0",
66
+ "@anthropic-ai/sdk": "^0.82.0",
67
67
  "@aws-sdk/client-bedrock-runtime": "^3.1021.0",
68
68
  "@google-cloud/vertexai": "^1.10.4",
69
69
  "@langchain/core": "^1.1.38",