{"version":3,"sources":["../src/cli/commands/analytics/query.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport ora from \"ora\";\nimport { AnalyticsApiService } from \"@/client-sdk/services/analytics/analytics-api.service\";\nimport { checkApiKey } from \"../../utils/apiKey\";\nimport { failSpinner } from \"../../utils/spinnerError\";\n\nconst METRIC_PRESETS: Record<string, { metric: string; aggregation: string }> = {\n  \"trace-count\": { metric: \"metadata.trace_id\", aggregation: \"cardinality\" },\n  \"user-count\": { metric: \"metadata.user_id\", aggregation: \"cardinality\" },\n  \"total-cost\": { metric: \"performance.total_cost\", aggregation: \"sum\" },\n  \"avg-latency\": { metric: \"performance.completion_time\", aggregation: \"avg\" },\n  \"p95-latency\": { metric: \"performance.completion_time\", aggregation: \"p95\" },\n  \"total-tokens\": { metric: \"performance.total_tokens\", aggregation: \"sum\" },\n  \"avg-tokens\": { metric: \"performance.total_tokens\", aggregation: \"avg\" },\n  \"eval-pass-rate\": { metric: \"evaluations.evaluation_pass_rate\", aggregation: \"avg\" },\n};\n\nexport const queryAnalyticsCommand = async (options: {\n  metric?: string;\n  aggregation?: string;\n  startDate?: string;\n  endDate?: string;\n  groupBy?: string;\n  timeScale?: string;\n  format?: string;\n}): Promise<void> => {\n  checkApiKey();\n\n  const service = new AnalyticsApiService();\n\n  // Resolve metric preset or use raw metric/aggregation\n  let metric: string;\n  let aggregation: string;\n\n  if (options.metric && options.metric in METRIC_PRESETS) {\n    const preset = METRIC_PRESETS[options.metric]!;\n    metric = preset.metric;\n    aggregation = options.aggregation ?? preset.aggregation;\n  } else {\n    metric = options.metric ?? \"metadata.trace_id\";\n    aggregation = options.aggregation ?? \"cardinality\";\n  }\n\n  const now = Date.now();\n  const sevenDaysAgo = now - 7 * 24 * 60 * 60 * 1000;\n\n  const startDate = options.startDate\n    ? new Date(options.startDate).getTime()\n    : sevenDaysAgo;\n  const endDate = options.endDate\n    ? new Date(options.endDate).getTime()\n    : now;\n\n  const spinner = ora(`Querying ${metric} (${aggregation})...`).start();\n\n  try {\n    const result = await service.timeseries({\n      startDate,\n      endDate,\n      series: [\n        {\n          metric: metric as \"metadata.trace_id\",\n          aggregation: aggregation as \"cardinality\",\n        },\n      ],\n      groupBy: options.groupBy as \"metadata.model\" | undefined,\n      timeScale: options.timeScale === \"full\" ? \"full\" : options.timeScale ? Number(options.timeScale) : undefined,\n      timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n    });\n\n    spinner.succeed(\"Analytics query complete\");\n\n    if (options.format === \"json\") {\n      console.log(JSON.stringify(result, null, 2));\n      return;\n    }\n\n    console.log();\n    console.log(chalk.bold(\"Current Period:\"));\n\n    if (result.currentPeriod.length === 0) {\n      console.log(chalk.gray(\"  No data for the current period.\"));\n    } else {\n      for (const dataPoint of result.currentPeriod) {\n        const entries = Object.entries(dataPoint).filter(\n          ([key]) => key !== \"date\",\n        );\n        const dateStr = dataPoint.date\n          ? new Date(dataPoint.date as number).toLocaleDateString()\n          : \"—\";\n\n        if (entries.length === 0) {\n          console.log(`  ${chalk.gray(dateStr)}: ${chalk.gray(\"no data\")}`);\n        } else {\n          const values = entries\n            .map(([key, value]) => `${chalk.cyan(key)}: ${formatValue(value)}`)\n            .join(\", \");\n          console.log(`  ${chalk.gray(dateStr)}: ${values}`);\n        }\n      }\n    }\n\n    if (result.previousPeriod.length > 0) {\n      console.log();\n      console.log(chalk.bold(\"Previous Period:\"));\n      for (const dataPoint of result.previousPeriod) {\n        const entries = Object.entries(dataPoint).filter(\n          ([key]) => key !== \"date\",\n        );\n        const dateStr = dataPoint.date\n          ? new Date(dataPoint.date as number).toLocaleDateString()\n          : \"—\";\n\n        if (entries.length > 0) {\n          const values = entries\n            .map(([key, value]) => `${chalk.cyan(key)}: ${formatValue(value)}`)\n            .join(\", \");\n          console.log(`  ${chalk.gray(dateStr)}: ${values}`);\n        }\n      }\n    }\n\n    console.log();\n    console.log(chalk.gray(\"Available presets: \" + Object.keys(METRIC_PRESETS).join(\", \")));\n    console.log(\n      chalk.gray(\n        `Use ${chalk.cyan(\"langwatch analytics query --metric <preset> -f json\")} for raw data`,\n      ),\n    );\n  } catch (error) {\n    failSpinner({ spinner, error, action: \"query analytics\" });\n    process.exit(1);\n  }\n};\n\nfunction formatValue(value: unknown): string {\n  if (typeof value === \"number\") {\n    return value % 1 === 0 ? value.toLocaleString() : value.toFixed(4);\n  }\n  return String(value);\n}\n"],"mappings":"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","names":[]}