UNPKG

@mastra/core

Version:
1 lines • 19.7 kB
{"version":3,"file":"index.cjs","names":["PostHog"],"sources":["../../src/telemetry/posthog.ts","../../src/telemetry/context.ts","../../src/telemetry/feature-telemetry.ts","../../src/telemetry/usage-telemetry.ts"],"sourcesContent":["import { createHash } from 'node:crypto';\nimport os from 'node:os';\nimport { PostHog } from 'posthog-node';\n\nconst POSTHOG_API_KEY = 'phc_SBLpZVAB6jmHOct9CABq3PF0Yn5FU3G2FgT4xUr2XrT';\nconst POSTHOG_HOST = 'https://us.posthog.com';\nconst TRUTHY_DISABLED_VALUES = new Set(['1', 'true', 'yes']);\n\nlet client: PostHog | null = null;\n\nexport type EEEventName = 'ee_license_check' | 'ee_feature_used';\n\nexport type TelemetryEventName = EEEventName | 'mastra_model_token_usage' | 'mastra_feature_usage';\n\nexport function isTelemetryEnabled(): boolean {\n const value = process.env['MASTRA_TELEMETRY_DISABLED'];\n if (!value) {\n return true;\n }\n return !TRUTHY_DISABLED_VALUES.has(value.trim().toLowerCase());\n}\n\nexport function hashTelemetryValue(value: string): string {\n return createHash('sha256').update(value).digest('hex');\n}\n\nfunction getHashedHostname(): string {\n return hashTelemetryValue(os.hostname() || 'unknown-host').slice(0, 16);\n}\n\nexport function getEETelemetryFallbackDistinctId(): string {\n return `mastra-${getHashedHostname()}`;\n}\n\nfunction getClient(): PostHog | null {\n if (!isTelemetryEnabled()) {\n return null;\n }\n\n if (!client) {\n client = new PostHog(POSTHOG_API_KEY, {\n host: POSTHOG_HOST,\n flushAt: 1,\n flushInterval: 0,\n disableGeoip: false,\n });\n }\n\n return client;\n}\n\nfunction getSystemProperties(): Record<string, unknown> {\n return {\n os: process.platform,\n os_version: os.release(),\n node_version: process.version,\n platform: process.arch,\n machine_id: getHashedHostname(),\n mastra_version: process.env['npm_package_version'] || 'unknown',\n };\n}\n\nexport function captureTelemetryEvent(\n event: TelemetryEventName,\n distinctId: string | undefined,\n properties?: Record<string, unknown>,\n): void {\n try {\n const posthog = getClient();\n if (!posthog) {\n return;\n }\n\n posthog.capture({\n distinctId: distinctId || getEETelemetryFallbackDistinctId(),\n event,\n properties: {\n ...getSystemProperties(),\n ...properties,\n },\n });\n } catch {\n // Telemetry must never affect auth or EE feature behavior.\n }\n}\n\nexport function captureEEEvent(\n event: EEEventName,\n distinctId: string | undefined,\n properties?: Record<string, unknown>,\n): void {\n captureTelemetryEvent(event, distinctId, properties);\n}\n\nexport function resetEETelemetryForTests(): void {\n client = null;\n}\n","import { hashTelemetryValue } from './posthog';\n\nexport interface ServerTelemetryContext {\n projectId: string;\n distinctId: string | undefined;\n command: string;\n nodeEnv: string;\n}\n\nexport function getServerTelemetryContext(): ServerTelemetryContext {\n return {\n projectId: hashTelemetryValue(process.env.MASTRA_PROJECT_ROOT || process.cwd()).slice(0, 16),\n distinctId: process.env.MASTRA_CLI_DISTINCT_ID || undefined,\n command: process.env.MASTRA_TELEMETRY_COMMAND || 'server',\n nodeEnv: process.env.NODE_ENV || 'development',\n };\n}\n","import type { Mastra } from '../mastra';\nimport { getServerTelemetryContext } from './context';\nimport { captureTelemetryEvent, isTelemetryEnabled } from './posthog';\n\nexport const FEATURE_USAGE_EVENT = 'mastra_feature_usage';\n\ntype StorageLike = {\n constructor?: { name?: string };\n stores?: { observability?: unknown };\n};\n\ntype AgentLike = {\n hasOwnMemory?: () => boolean;\n};\n\nfunction countCollection(collection: unknown): number {\n if (!collection || typeof collection !== 'object') {\n return 0;\n }\n if (collection instanceof Map || collection instanceof Set) {\n return collection.size;\n }\n\n return Object.keys(collection).length;\n}\n\nfunction countAgentsWithMemory(agents: unknown): number {\n if (!agents || typeof agents !== 'object') {\n return 0;\n }\n\n return Object.values(agents).filter(agent => {\n try {\n return (agent as AgentLike | undefined)?.hasOwnMemory?.() === true;\n } catch {\n return false;\n }\n }).length;\n}\n\nfunction bucketStorageType(storage: StorageLike | undefined): string | null {\n if (!storage) {\n return null;\n }\n\n const constructorName = storage.constructor?.name?.toLowerCase();\n if (!constructorName) {\n return 'unknown';\n }\n\n if (constructorName.includes('memory')) {\n return 'in-memory';\n }\n if (constructorName.includes('libsql')) {\n return 'libsql';\n }\n if (constructorName.includes('postgres')) {\n return 'postgres';\n }\n if (constructorName.includes('mongo')) {\n return 'mongo';\n }\n if (constructorName.includes('upstash')) {\n return 'upstash';\n }\n if (constructorName.includes('dynamodb')) {\n return 'dynamodb';\n }\n if (constructorName.includes('redis')) {\n return 'redis';\n }\n\n return 'unknown';\n}\n\nexport function trackFeatureUsage(name: string, metadata?: Record<string, unknown>): void {\n try {\n if (!isTelemetryEnabled()) {\n return;\n }\n\n const { projectId, distinctId, command, nodeEnv } = getServerTelemetryContext();\n captureTelemetryEvent(FEATURE_USAGE_EVENT, distinctId, {\n feature_name: name,\n project_id: projectId,\n command,\n node_env: nodeEnv,\n ...metadata,\n });\n } catch {\n // Feature telemetry must never affect server startup or runtime behavior.\n }\n}\n\nexport function syncFeatureUsageTelemetry(mastra: Mastra): void {\n try {\n if (!isTelemetryEnabled()) {\n return;\n }\n\n const agents = mastra.listAgents?.();\n const agentsWithMemoryCount = countAgentsWithMemory(agents);\n const memory = mastra.listMemory?.();\n const workspaces = mastra.listWorkspaces?.();\n const tts = mastra.getTTS?.();\n const promptBlocks = mastra.listPromptBlocks?.();\n const processorConfigurations = mastra.listProcessorConfigurations?.();\n const agentChannels = mastra.getChannels?.();\n const storage = mastra.getStorage?.() as StorageLike | undefined;\n\n trackFeatureUsage('mastra_instance_summary', {\n agent_count: countCollection(agents),\n agents_with_memory_count: agentsWithMemoryCount,\n agent_controller_count: countCollection(mastra.listAgentControllers?.()),\n workflow_count: countCollection(mastra.listWorkflows?.()),\n tool_count: countCollection(mastra.listTools?.()),\n processor_count: countCollection(mastra.listProcessors?.()),\n processor_configuration_count: countCollection(processorConfigurations),\n memory_count: countCollection(memory),\n vector_count: countCollection(mastra.listVectors?.()),\n scorer_count: countCollection(mastra.listScorers?.()),\n workspace_count: countCollection(workspaces),\n mcp_server_count: countCollection(mastra.listMCPServers?.()),\n gateway_count: countCollection(mastra.listGateways?.()),\n channel_count: countCollection(mastra.getChannelProviders?.()),\n agent_channel_count: countCollection(agentChannels),\n tts_count: countCollection(tts),\n prompt_block_count: countCollection(promptBlocks),\n editor_enabled: !!mastra.getEditor?.(),\n studio_enabled: !!mastra.getStudio?.(),\n server_middleware_enabled: !!mastra.getServerMiddleware?.(),\n storage_type: bucketStorageType(storage),\n observability_enabled: !!storage?.stores?.observability,\n });\n } catch {\n // Feature telemetry must never affect server startup or runtime behavior.\n }\n}\n","import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\nimport type { Mastra } from '../mastra';\nimport type { GetMetricBreakdownResponse, ObservabilityStorage } from '../storage/domains';\nimport { getServerTelemetryContext } from './context';\nimport { captureTelemetryEvent, isTelemetryEnabled } from './posthog';\n\nconst INPUT_TOKENS_METRIC = 'mastra_model_total_input_tokens';\nconst OUTPUT_TOKENS_METRIC = 'mastra_model_total_output_tokens';\nconst BREAKDOWN_LIMIT = 200;\n\nexport const USAGE_TELEMETRY_EVENT = 'mastra_model_token_usage';\n\nexport interface SyncUsageTelemetryOptions {\n /** Override the cursor file location (used by tests). */\n cursorPath?: string;\n /** Override the current time (used by tests). */\n now?: Date;\n}\n\ninterface UsageTelemetryCursors {\n projects: Record<string, string>;\n}\n\ninterface UsageRow {\n provider: string | null;\n model: string | null;\n inputTokens: number;\n outputTokens: number;\n totalInputTokens: number;\n totalOutputTokens: number;\n}\n\nfunction getDefaultCursorPath(): string {\n return path.join(os.homedir(), '.mastra', 'usage-telemetry.json');\n}\n\nfunction readCursors(cursorPath: string): UsageTelemetryCursors {\n try {\n const parsed = JSON.parse(readFileSync(cursorPath, 'utf-8')) as Partial<UsageTelemetryCursors> | null;\n if (parsed && typeof parsed === 'object' && parsed.projects && typeof parsed.projects === 'object') {\n return { projects: parsed.projects };\n }\n } catch {\n // Missing or corrupt cursor file - treat as first sync.\n }\n return { projects: {} };\n}\n\nfunction readCursor(cursorPath: string, projectId: string): Date | undefined {\n const value = readCursors(cursorPath).projects[projectId];\n if (!value) {\n return undefined;\n }\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n\nfunction writeCursor(cursorPath: string, projectId: string, syncedAt: Date): void {\n const cursors = readCursors(cursorPath);\n cursors.projects[projectId] = syncedAt.toISOString();\n mkdirSync(path.dirname(cursorPath), { recursive: true });\n writeFileSync(cursorPath, JSON.stringify(cursors));\n}\n\nfunction applyBreakdown(\n rows: Map<string, UsageRow>,\n response: GetMetricBreakdownResponse,\n field: keyof Pick<UsageRow, 'inputTokens' | 'outputTokens' | 'totalInputTokens' | 'totalOutputTokens'>,\n): void {\n for (const group of response.groups) {\n const provider = group.dimensions.provider ?? null;\n const model = group.dimensions.model ?? null;\n const key = `${provider}\\u0000${model}`;\n let row = rows.get(key);\n if (!row) {\n row = { provider, model, inputTokens: 0, outputTokens: 0, totalInputTokens: 0, totalOutputTokens: 0 };\n rows.set(key, row);\n }\n row[field] += group.value ?? 0;\n }\n}\n\n/**\n * Sends aggregated model token usage (input/output tokens per provider+model) to\n * Mastra's anonymous telemetry when the project has observability metrics enabled.\n *\n * Sync strategy: deltas since the last successful sync, tracked per project via a\n * cursor file in `~/.mastra/usage-telemetry.json`. Each event also carries lifetime\n * totals so consumers can read either incremental or cumulative usage. Runs once at\n * server startup; respects `MASTRA_TELEMETRY_DISABLED`. Never throws.\n */\nexport async function syncUsageTelemetry(mastra: Mastra, options: SyncUsageTelemetryOptions = {}): Promise<void> {\n try {\n if (!isTelemetryEnabled()) {\n return;\n }\n\n const observability = mastra.getStorage()?.stores?.observability as ObservabilityStorage | undefined;\n if (!observability || typeof observability.getMetricBreakdown !== 'function') {\n return;\n }\n\n const { projectId, distinctId, command, nodeEnv } = getServerTelemetryContext();\n const cursorPath = options.cursorPath ?? getDefaultCursorPath();\n const lastSyncedAt = readCursor(cursorPath, projectId);\n const now = options.now ?? new Date();\n if (lastSyncedAt && lastSyncedAt.getTime() >= now.getTime()) {\n return;\n }\n\n const baseArgs = {\n groupBy: ['provider', 'model'],\n aggregation: 'sum' as const,\n limit: BREAKDOWN_LIMIT,\n };\n const deltaFilters = {\n timestamp: { ...(lastSyncedAt ? { start: lastSyncedAt, startExclusive: true } : {}), end: now },\n };\n const totalFilters = { timestamp: { end: now } };\n\n const [inputDelta, outputDelta, inputTotal, outputTotal] = await Promise.all([\n observability.getMetricBreakdown({ ...baseArgs, name: [INPUT_TOKENS_METRIC], filters: deltaFilters }),\n observability.getMetricBreakdown({ ...baseArgs, name: [OUTPUT_TOKENS_METRIC], filters: deltaFilters }),\n observability.getMetricBreakdown({ ...baseArgs, name: [INPUT_TOKENS_METRIC], filters: totalFilters }),\n observability.getMetricBreakdown({ ...baseArgs, name: [OUTPUT_TOKENS_METRIC], filters: totalFilters }),\n ]);\n\n const rows = new Map<string, UsageRow>();\n applyBreakdown(rows, inputDelta, 'inputTokens');\n applyBreakdown(rows, outputDelta, 'outputTokens');\n applyBreakdown(rows, inputTotal, 'totalInputTokens');\n applyBreakdown(rows, outputTotal, 'totalOutputTokens');\n\n const isFirstSync = !lastSyncedAt;\n\n for (const row of rows.values()) {\n if (row.inputTokens <= 0 && row.outputTokens <= 0) {\n continue;\n }\n captureTelemetryEvent(USAGE_TELEMETRY_EVENT, distinctId, {\n provider: row.provider,\n model: row.model,\n input_tokens: row.inputTokens,\n output_tokens: row.outputTokens,\n total_input_tokens: row.totalInputTokens,\n total_output_tokens: row.totalOutputTokens,\n command,\n node_env: nodeEnv,\n project_id: projectId,\n is_first_sync: isFirstSync,\n window_start: lastSyncedAt?.toISOString() ?? null,\n window_end: now.toISOString(),\n });\n }\n\n writeCursor(cursorPath, projectId, now);\n } catch {\n // Usage telemetry must never affect server startup or runtime behavior.\n }\n}\n"],"mappings":"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"}