.do
Service TypesData Services

Data Analytics Services

Build intelligent analytics services that generate insights, reports, and dashboards from data

Data analytics services transform raw data into actionable insights through automated reporting, dashboard generation, metrics calculation, and trend analysis. These services are essential for data-driven decision making and business intelligence.

Overview

Analytics services automate the process of extracting meaningful insights from data. Whether you're generating executive reports, calculating KPIs, analyzing trends, or creating interactive dashboards, analytics services make data accessible and actionable for stakeholders at all levels.

Key Capabilities

  • Automated Reporting: Generate scheduled reports with insights and visualizations
  • Dashboard Generation: Create interactive dashboards tailored to specific audiences
  • Metrics Calculation: Compute KPIs, performance metrics, and custom calculations
  • Trend Analysis: Identify patterns, anomalies, and predictions
  • Performance Monitoring: Track goals, SLAs, and business objectives
  • Comparative Analysis: Benchmark against historical data and competitors

Common Use Cases

  1. Executive Dashboards: High-level business metrics and KPIs
  2. Sales Analytics: Pipeline analysis, revenue forecasting, performance tracking
  3. Marketing Analytics: Campaign performance, ROI, customer acquisition
  4. Operational Analytics: Efficiency metrics, resource utilization, bottlenecks
  5. Financial Reporting: P&L statements, cash flow, budget variance
  6. Customer Analytics: Behavior patterns, segmentation, lifetime value

Building Your First Analytics Service

Let's start with an automated reporting service:

import $, { ai, db, on, send } from 'sdk.do'

const reportingService = await $.Service.create({
  name: 'Automated Report Generator',
  description: 'Generate comprehensive reports with insights, visualizations, and recommendations',
  type: $.ServiceType.DataAnalytics,
  subtype: 'reporting',

  input: {
    required: ['dataSource', 'reportType'],
    optional: ['dateRange', 'format', 'recipients', 'schedule'],
  },

  output: {
    report: 'object',
    insights: 'array',
    visualizations: 'array',
    recommendations: 'array',
  },

  reportTypes: ['executive-summary', 'sales-performance', 'marketing-roi', 'financial-overview', 'operational-metrics', 'custom'],

  pricing: {
    model: 'per-report',
    base: 5.0,
    complexity: {
      simple: 1.0,
      moderate: 2.0,
      comprehensive: 3.0,
    },
  },
})

on.ServiceRequest.created(async (request) => {
  if (request.serviceId !== reportingService.id) return

  const { dataSource, reportType, dateRange = 'last-30-days', format = 'pdf', recipients } = request.inputs

  try {
    // Step 1: Fetch and prepare data
    await send.ServiceProgress.updated({
      requestId: request.id,
      stage: 'data-collection',
      progress: 0.1,
    })

    const rawData = await fetchDataFromSource(dataSource, dateRange)
    const preparedData = await prepareDataForAnalysis(rawData)

    // Step 2: Calculate metrics
    await send.ServiceProgress.updated({
      requestId: request.id,
      stage: 'metrics-calculation',
      progress: 0.3,
    })

    const metrics = await calculateMetrics(preparedData, reportType)

    // Step 3: Generate insights using AI
    await send.ServiceProgress.updated({
      requestId: request.id,
      stage: 'insight-generation',
      progress: 0.5,
    })

    const insights = await ai.analyze({
      model: 'gpt-5',
      data: metrics,
      analysisType: 'business-insights',
      instructions: `
        Analyze the following ${reportType} data and provide:
        1. Key findings and trends
        2. Notable changes from previous period
        3. Areas of concern requiring attention
        4. Opportunities for improvement
        5. Actionable recommendations

        Be specific and data-driven in your analysis.
      `,
    })

    // Step 4: Create visualizations
    await send.ServiceProgress.updated({
      requestId: request.id,
      stage: 'visualization-creation',
      progress: 0.7,
    })

    const visualizations = await generateVisualizations(metrics, reportType)

    // Step 5: Generate recommendations
    const recommendations = await ai.generate({
      model: 'gpt-5',
      type: 'recommendations',
      context: {
        metrics,
        insights: insights.findings,
        reportType,
      },
      instructions: 'Provide 3-5 specific, actionable recommendations based on the data.',
    })

    // Step 6: Compile report
    await send.ServiceProgress.updated({
      requestId: request.id,
      stage: 'report-compilation',
      progress: 0.9,
    })

    const report = await compileReport({
      type: reportType,
      dateRange,
      metrics,
      insights: insights.findings,
      visualizations,
      recommendations: recommendations.items,
      format,
    })

    // Step 7: Deliver report
    const reportUrl = await uploadReport(report, format)

    // Send to recipients if specified
    if (recipients && recipients.length > 0) {
      await send.Email.send({
        to: recipients,
        subject: `${reportType} Report - ${formatDateRange(dateRange)}`,
        body: generateReportEmail(insights.summary),
        attachments: [
          {
            filename: `report-${reportType}-${Date.now()}.${format}`,
            url: reportUrl,
          },
        ],
      })
    }

    // Deliver results
    await send.ServiceResult.deliver({
      requestId: request.id,
      outputs: {
        report: {
          url: reportUrl,
          format,
          generatedAt: new Date(),
        },
        insights: insights.findings,
        visualizations: visualizations.map((v) => v.url),
        recommendations: recommendations.items,
        summary: {
          metricsCalculated: Object.keys(metrics).length,
          insightsGenerated: insights.findings.length,
          visualizationsCreated: visualizations.length,
          recipientsSent: recipients?.length || 0,
        },
      },
    })

    // Calculate cost based on complexity
    const complexity = determineReportComplexity(reportType, metrics, visualizations)
    const multiplier = reportingService.pricing.complexity[complexity]
    const cost = reportingService.pricing.base * multiplier

    await send.Payment.charge({
      customerId: request.customerId,
      amount: cost,
      description: `${reportType} report (${complexity})`,
    })
  } catch (error) {
    await send.ServiceRequest.fail({
      requestId: request.id,
      error: error.message,
      retryable: true,
    })
  }
})

async function calculateMetrics(data: any, reportType: string): Promise<any> {
  const metrics = {}

  switch (reportType) {
    case 'sales-performance':
      metrics.totalRevenue = sumField(data, 'revenue')
      metrics.averageOrderValue = averageField(data, 'orderValue')
      metrics.conversionRate = calculateConversionRate(data)
      metrics.customerCount = countUnique(data, 'customerId')
      metrics.growthRate = calculateGrowthRate(data, 'revenue')
      break

    case 'marketing-roi':
      metrics.totalSpend = sumField(data, 'spend')
      metrics.totalRevenue = sumField(data, 'revenue')
      metrics.roi = (metrics.totalRevenue - metrics.totalSpend) / metrics.totalSpend
      metrics.cac = calculateCustomerAcquisitionCost(data)
      metrics.ltv = calculateLifetimeValue(data)
      break

    case 'financial-overview':
      metrics.revenue = sumField(data, 'revenue')
      metrics.expenses = sumField(data, 'expenses')
      metrics.profit = metrics.revenue - metrics.expenses
      metrics.profitMargin = metrics.profit / metrics.revenue
      metrics.burnRate = calculateBurnRate(data)
      break

    default:
      // Calculate generic metrics
      metrics.recordCount = data.length
      metrics.numericFields = calculateNumericFieldStats(data)
  }

  return metrics
}

async function generateVisualizations(metrics: any, reportType: string): Promise<any[]> {
  const visualizations = []

  // Generate appropriate charts based on report type
  switch (reportType) {
    case 'sales-performance':
      visualizations.push(
        await createChart('line', metrics.revenueOverTime, { title: 'Revenue Trend' }),
        await createChart('bar', metrics.productPerformance, { title: 'Top Products' }),
        await createChart('pie', metrics.revenueByRegion, { title: 'Revenue by Region' })
      )
      break

    case 'marketing-roi':
      visualizations.push(
        await createChart('bar', metrics.campaignPerformance, { title: 'Campaign ROI' }),
        await createChart('funnel', metrics.conversionFunnel, { title: 'Conversion Funnel' }),
        await createChart('line', metrics.cacTrend, { title: 'CAC Trend' })
      )
      break

    case 'financial-overview':
      visualizations.push(
        await createChart('line', metrics.revenueVsExpenses, { title: 'Revenue vs Expenses' }),
        await createChart('waterfall', metrics.cashFlow, { title: 'Cash Flow' }),
        await createChart('gauge', metrics.profitMargin, { title: 'Profit Margin' })
      )
      break
  }

  return visualizations
}

Dashboard Generation Service

Create interactive, real-time dashboards:

const dashboardService = await $.Service.create({
  name: 'Interactive Dashboard Builder',
  description: 'Generate customizable, real-time dashboards with live data',
  type: $.ServiceType.DataAnalytics,
  subtype: 'dashboard',

  input: {
    required: ['dataSource', 'dashboardType'],
    optional: ['widgets', 'refreshInterval', 'filters', 'permissions'],
  },

  features: ['real-time-updates', 'interactive-filters', 'drill-down', 'export', 'sharing', 'alerts'],

  pricing: {
    model: 'subscription',
    tiers: [
      { name: 'basic', price: 50, dashboards: 3, users: 5 },
      { name: 'professional', price: 200, dashboards: 15, users: 25 },
      { name: 'enterprise', price: 1000, dashboards: Infinity, users: Infinity },
    ],
  },
})

on.ServiceRequest.created(async (request) => {
  if (request.serviceId !== dashboardService.id) return

  const { dataSource, dashboardType, widgets, refreshInterval = 60, filters, permissions } = request.inputs

  try {
    // Create dashboard structure
    const dashboard = await $.Dashboard.create({
      name: `${dashboardType} Dashboard`,
      type: dashboardType,
      dataSource,
      refreshInterval,
      createdBy: request.customerId,
    })

    // Add widgets
    const widgetConfigs = widgets || getDefaultWidgets(dashboardType)

    for (const widgetConfig of widgetConfigs) {
      const widget = await createWidget(dashboard.id, widgetConfig, dataSource)

      await db.create($.DashboardWidget, {
        dashboardId: dashboard.id,
        widgetId: widget.id,
        position: widgetConfig.position,
        size: widgetConfig.size,
      })
    }

    // Set up real-time data updates
    await setupDataStream(dashboard.id, dataSource, refreshInterval)

    // Configure filters
    if (filters) {
      await $.Dashboard.update(dashboard.id, {
        filters: filters.map((f) => ({
          field: f.field,
          type: f.type,
          options: f.options,
        })),
      })
    }

    // Set permissions
    if (permissions) {
      await setDashboardPermissions(dashboard.id, permissions)
    }

    // Generate embed code and shareable link
    const embedCode = generateEmbedCode(dashboard.id)
    const shareUrl = generateShareUrl(dashboard.id)

    // Deliver results
    await send.ServiceResult.deliver({
      requestId: request.id,
      outputs: {
        dashboard: {
          id: dashboard.id,
          url: `/dashboards/${dashboard.id}`,
          shareUrl,
          embedCode,
        },
        widgets: widgetConfigs.length,
        refreshInterval,
      },
    })

    // Subscription billing handled separately
  } catch (error) {
    await send.ServiceRequest.fail({
      requestId: request.id,
      error: error.message,
      retryable: true,
    })
  }
})

async function createWidget(dashboardId: string, config: any, dataSource: any): Promise<any> {
  const widget = await $.Widget.create({
    type: config.type,
    title: config.title,
    dataSource,
    query: config.query,
    visualization: config.visualization,
  })

  // Set up widget data refresh
  on.Dashboard.refresh(async (event) => {
    if (event.dashboardId !== dashboardId) return

    const data = await queryDataSource(dataSource, config.query)
    await send.Widget.update({
      widgetId: widget.id,
      data,
      updatedAt: new Date(),
    })
  })

  return widget
}

function getDefaultWidgets(dashboardType: string): any[] {
  const widgets = []

  switch (dashboardType) {
    case 'executive':
      widgets.push(
        { type: 'metric', title: 'Total Revenue', query: 'sum(revenue)', position: { x: 0, y: 0 }, size: { w: 3, h: 2 } },
        { type: 'metric', title: 'Active Customers', query: 'count(distinct customerId)', position: { x: 3, y: 0 }, size: { w: 3, h: 2 } },
        { type: 'chart', title: 'Revenue Trend', query: 'revenue by date', visualization: 'line', position: { x: 0, y: 2 }, size: { w: 6, h: 4 } },
        { type: 'chart', title: 'Top Products', query: 'revenue by product', visualization: 'bar', position: { x: 6, y: 0 }, size: { w: 6, h: 6 } }
      )
      break

    case 'sales':
      widgets.push(
        { type: 'metric', title: 'Pipeline Value', query: 'sum(value)', position: { x: 0, y: 0 }, size: { w: 3, h: 2 } },
        { type: 'chart', title: 'Sales Funnel', query: 'count by stage', visualization: 'funnel', position: { x: 0, y: 2 }, size: { w: 6, h: 4 } },
        { type: 'table', title: 'Top Deals', query: 'deals order by value', position: { x: 6, y: 0 }, size: { w: 6, h: 6 } }
      )
      break

    case 'marketing':
      widgets.push(
        { type: 'metric', title: 'Campaign ROI', query: 'roi()', position: { x: 0, y: 0 }, size: { w: 3, h: 2 } },
        { type: 'chart', title: 'Traffic Sources', query: 'traffic by source', visualization: 'pie', position: { x: 3, y: 0 }, size: { w: 3, h: 4 } },
        { type: 'chart', title: 'Conversion Rate', query: 'conversion by campaign', visualization: 'bar', position: { x: 0, y: 4 }, size: { w: 6, h: 4 } }
      )
      break
  }

  return widgets
}

KPI Tracking Service

Calculate and monitor key performance indicators:

const kpiTrackingService = await $.Service.create({
  name: 'KPI Tracker',
  description: 'Calculate, track, and alert on key performance indicators',
  type: $.ServiceType.DataAnalytics,
  subtype: 'kpi-tracking',

  input: {
    required: ['kpiDefinitions', 'dataSource'],
    optional: ['targets', 'alerts', 'frequency'],
  },

  features: ['automated-calculation', 'trend-analysis', 'goal-tracking', 'alerts', 'forecasting'],

  pricing: {
    model: 'per-kpi',
    base: 10.0, // per KPI per month
    volume: [
      { min: 1, max: 10, rate: 10.0 },
      { min: 11, max: 50, rate: 7.5 },
      { min: 51, max: Infinity, rate: 5.0 },
    ],
  },
})

on.ServiceRequest.created(async (request) => {
  if (request.serviceId !== kpiTrackingService.id) return

  const { kpiDefinitions, dataSource, targets = {}, alerts = {}, frequency = 'daily' } = request.inputs

  try {
    const kpiResults = []

    for (const kpiDef of kpiDefinitions) {
      // Calculate current KPI value
      const currentValue = await calculateKPI(kpiDef, dataSource)

      // Get historical values
      const historicalValues = await getHistoricalKPI(kpiDef.id, 30) // Last 30 periods

      // Calculate trends
      const trend = calculateTrend(historicalValues)
      const forecast = forecastKPI(historicalValues)

      // Compare to target
      const target = targets[kpiDef.id]
      const targetComparison = target
        ? {
            target,
            current: currentValue,
            difference: currentValue - target,
            percentOfTarget: (currentValue / target) * 100,
            status: currentValue >= target ? 'on-track' : 'behind',
          }
        : null

      // Check alerts
      const alertConfig = alerts[kpiDef.id]
      if (alertConfig) {
        const shouldAlert = evaluateAlertCondition(currentValue, alertConfig)

        if (shouldAlert) {
          await send.Alert.create({
            type: 'kpi-threshold',
            kpiId: kpiDef.id,
            kpiName: kpiDef.name,
            value: currentValue,
            threshold: alertConfig.threshold,
            condition: alertConfig.condition,
          })
        }
      }

      // Store KPI value
      await db.KPIValue.create({
        kpiId: kpiDef.id,
        value: currentValue,
        timestamp: new Date(),
        metadata: {
          trend,
          forecast: forecast.next,
        },
      })

      kpiResults.push({
        kpiId: kpiDef.id,
        name: kpiDef.name,
        value: currentValue,
        trend,
        forecast: forecast.next,
        target: targetComparison,
        history: historicalValues.slice(-7), // Last 7 periods
      })
    }

    // Generate insights
    const insights = await ai.analyze({
      model: 'gpt-5',
      data: kpiResults,
      analysisType: 'kpi-insights',
      instructions: `
        Analyze these KPI results and provide:
        1. Overall performance summary
        2. KPIs requiring immediate attention
        3. Positive trends to amplify
        4. Recommendations for improvement
      `,
    })

    // Deliver results
    await send.ServiceResult.deliver({
      requestId: request.id,
      outputs: {
        kpis: kpiResults,
        insights: insights.findings,
        summary: {
          totalKPIs: kpiResults.length,
          onTrack: kpiResults.filter((k) => k.target?.status === 'on-track').length,
          behind: kpiResults.filter((k) => k.target?.status === 'behind').length,
          trending: {
            up: kpiResults.filter((k) => k.trend.direction === 'up').length,
            down: kpiResults.filter((k) => k.trend.direction === 'down').length,
            stable: kpiResults.filter((k) => k.trend.direction === 'stable').length,
          },
        },
      },
    })

    // Schedule next calculation
    await scheduleKPICalculation(request, frequency)

    // Charge based on number of KPIs
    const rate = getVolumeRate(kpiDefinitions.length, kpiTrackingService.pricing.volume)
    const cost = kpiDefinitions.length * rate

    await send.Payment.charge({
      customerId: request.customerId,
      amount: cost,
      description: `KPI tracking (${kpiDefinitions.length} KPIs)`,
    })
  } catch (error) {
    await send.ServiceRequest.fail({
      requestId: request.id,
      error: error.message,
      retryable: true,
    })
  }
})

async function calculateKPI(kpiDef: any, dataSource: any): Promise<number> {
  const data = await queryDataSource(dataSource, kpiDef.query)

  switch (kpiDef.calculation) {
    case 'sum':
      return data.reduce((sum, record) => sum + record[kpiDef.field], 0)

    case 'average':
      return data.reduce((sum, record) => sum + record[kpiDef.field], 0) / data.length

    case 'count':
      return data.length

    case 'ratio':
      const numerator = data.reduce((sum, record) => sum + record[kpiDef.numeratorField], 0)
      const denominator = data.reduce((sum, record) => sum + record[kpiDef.denominatorField], 0)
      return numerator / denominator

    case 'custom':
      return evaluateCustomFormula(data, kpiDef.formula)

    default:
      return 0
  }
}

function calculateTrend(values: number[]): any {
  if (values.length < 2) return { direction: 'stable', change: 0 }

  const recent = values.slice(-5) // Last 5 values
  const older = values.slice(-10, -5) // Previous 5 values

  const recentAvg = recent.reduce((sum, v) => sum + v, 0) / recent.length
  const olderAvg = older.reduce((sum, v) => sum + v, 0) / older.length

  const change = ((recentAvg - olderAvg) / olderAvg) * 100

  return {
    direction: Math.abs(change) < 5 ? 'stable' : change > 0 ? 'up' : 'down',
    change: change.toFixed(2),
    velocity: Math.abs(change),
  }
}

function forecastKPI(historicalValues: number[]): any {
  // Simple linear regression forecast
  const n = historicalValues.length
  const x = Array.from({ length: n }, (_, i) => i)
  const y = historicalValues

  const sumX = x.reduce((sum, val) => sum + val, 0)
  const sumY = y.reduce((sum, val) => sum + val, 0)
  const sumXY = x.reduce((sum, val, i) => sum + val * y[i], 0)
  const sumXX = x.reduce((sum, val) => sum + val * val, 0)

  const slope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX)
  const intercept = (sumY - slope * sumX) / n

  const next = slope * n + intercept

  return {
    next: Math.round(next),
    confidence: calculateForecastConfidence(historicalValues, slope),
  }
}

Trend Analysis Service

Identify patterns and anomalies in data:

const trendAnalysisService = await $.Service.create({
  name: 'Trend Analyzer',
  description: 'Identify trends, patterns, and anomalies in time-series data',
  type: $.ServiceType.DataAnalytics,
  subtype: 'trend-analysis',

  input: {
    required: ['data', 'timeField'],
    optional: ['metrics', 'granularity', 'detectAnomalies'],
  },

  analyses: ['trend-detection', 'seasonality', 'anomaly-detection', 'correlation', 'forecasting'],

  pricing: {
    model: 'per-analysis',
    base: 20.0,
    dataSize: {
      perThousandRecords: 1.0,
    },
  },
})

on.ServiceRequest.created(async (request) => {
  if (request.serviceId !== trendAnalysisService.id) return

  const { data, timeField, metrics, granularity = 'daily', detectAnomalies = true } = request.inputs

  try {
    // Prepare time-series data
    const timeSeries = prepareTimeSeries(data, timeField, metrics, granularity)

    const analysis = {
      trends: [],
      seasonality: [],
      anomalies: [],
      correlations: [],
      forecasts: [],
    }

    // Analyze each metric
    for (const metric of metrics) {
      const series = timeSeries[metric]

      // Trend detection
      const trend = detectTrend(series)
      analysis.trends.push({
        metric,
        direction: trend.direction,
        strength: trend.strength,
        startDate: trend.startDate,
        changeRate: trend.changeRate,
      })

      // Seasonality analysis
      const seasonality = detectSeasonality(series, granularity)
      if (seasonality.detected) {
        analysis.seasonality.push({
          metric,
          pattern: seasonality.pattern,
          period: seasonality.period,
          strength: seasonality.strength,
        })
      }

      // Anomaly detection
      if (detectAnomalies) {
        const anomalies = detectAnomalies(series)
        analysis.anomalies.push(
          ...anomalies.map((a) => ({
            metric,
            timestamp: a.timestamp,
            value: a.value,
            expectedValue: a.expectedValue,
            deviation: a.deviation,
            severity: a.severity,
          }))
        )
      }

      // Forecast
      const forecast = forecastTimeSeries(series, 30) // Next 30 periods
      analysis.forecasts.push({
        metric,
        values: forecast.values,
        confidenceIntervals: forecast.intervals,
      })
    }

    // Correlation analysis
    if (metrics.length > 1) {
      for (let i = 0; i < metrics.length; i++) {
        for (let j = i + 1; j < metrics.length; j++) {
          const correlation = calculateCorrelation(timeSeries[metrics[i]], timeSeries[metrics[j]])

          if (Math.abs(correlation.coefficient) > 0.5) {
            analysis.correlations.push({
              metric1: metrics[i],
              metric2: metrics[j],
              coefficient: correlation.coefficient,
              strength: correlation.strength,
              direction: correlation.direction,
            })
          }
        }
      }
    }

    // Generate insights using AI
    const insights = await ai.analyze({
      model: 'gpt-5',
      data: analysis,
      analysisType: 'trend-insights',
      instructions: `
        Analyze these trend analysis results and provide:
        1. Key trends and their business implications
        2. Significant patterns or seasonality
        3. Important anomalies requiring attention
        4. Correlations that suggest causation
        5. Forecast implications and recommendations
      `,
    })

    // Deliver results
    await send.ServiceResult.deliver({
      requestId: request.id,
      outputs: {
        analysis,
        insights: insights.findings,
        summary: {
          metricsAnalyzed: metrics.length,
          trendsDetected: analysis.trends.length,
          anomaliesFound: analysis.anomalies.length,
          correlationsFound: analysis.correlations.length,
        },
      },
    })

    // Calculate cost
    const thousands = Math.ceil(data.length / 1000)
    const cost = trendAnalysisService.pricing.base + thousands * trendAnalysisService.pricing.dataSize.perThousandRecords

    await send.Payment.charge({
      customerId: request.customerId,
      amount: cost,
      description: `Trend analysis (${data.length} records, ${metrics.length} metrics)`,
    })
  } catch (error) {
    await send.ServiceRequest.fail({
      requestId: request.id,
      error: error.message,
      retryable: true,
    })
  }
})

function detectTrend(series: any[]): any {
  const values = series.map((s) => s.value)

  // Calculate moving average
  const windowSize = Math.min(7, Math.floor(values.length / 4))
  const movingAvg = calculateMovingAverage(values, windowSize)

  // Determine trend direction
  const firstHalf = movingAvg.slice(0, Math.floor(movingAvg.length / 2))
  const secondHalf = movingAvg.slice(Math.floor(movingAvg.length / 2))

  const firstAvg = firstHalf.reduce((sum, v) => sum + v, 0) / firstHalf.length
  const secondAvg = secondHalf.reduce((sum, v) => sum + v, 0) / secondHalf.length

  const change = ((secondAvg - firstAvg) / firstAvg) * 100

  return {
    direction: Math.abs(change) < 5 ? 'stable' : change > 0 ? 'increasing' : 'decreasing',
    strength: Math.abs(change) < 10 ? 'weak' : Math.abs(change) < 25 ? 'moderate' : 'strong',
    changeRate: change.toFixed(2),
    startDate: series[0].timestamp,
  }
}

function detectAnomalies(series: any[]): any[] {
  const values = series.map((s) => s.value)

  // Calculate statistics
  const mean = values.reduce((sum, v) => sum + v, 0) / values.length
  const stdDev = Math.sqrt(values.reduce((sum, v) => sum + Math.pow(v - mean, 2), 0) / values.length)

  // Detect anomalies (values beyond 3 standard deviations)
  const anomalies = []

  series.forEach((point, i) => {
    const zScore = Math.abs((point.value - mean) / stdDev)

    if (zScore > 3) {
      anomalies.push({
        timestamp: point.timestamp,
        value: point.value,
        expectedValue: mean,
        deviation: zScore,
        severity: zScore > 4 ? 'high' : zScore > 3.5 ? 'medium' : 'low',
      })
    }
  })

  return anomalies
}

function detectSeasonality(series: any[], granularity: string): any {
  const values = series.map((s) => s.value)

  // Determine expected period based on granularity
  const periods = {
    hourly: 24,
    daily: 7,
    weekly: 4,
    monthly: 12,
  }

  const period = periods[granularity]
  if (!period || values.length < period * 2) {
    return { detected: false }
  }

  // Calculate autocorrelation at expected period
  const autocorr = calculateAutocorrelation(values, period)

  return {
    detected: autocorr > 0.6,
    pattern: granularity,
    period,
    strength: autocorr > 0.8 ? 'strong' : autocorr > 0.6 ? 'moderate' : 'weak',
  }
}

Performance Monitoring Service

Track system and business performance metrics:

const performanceMonitoringService = await $.Service.create({
  name: 'Performance Monitor',
  description: 'Monitor system performance, SLAs, and business goals',
  type: $.ServiceType.DataAnalytics,
  subtype: 'performance-monitoring',

  input: {
    required: ['monitoringConfig'],
    optional: ['alertThresholds', 'dashboardId'],
  },

  metrics: ['latency', 'throughput', 'error-rate', 'availability', 'resource-utilization', 'custom'],

  pricing: {
    model: 'subscription',
    tiers: [
      { name: 'basic', price: 100, metrics: 10, dataRetention: 30 },
      { name: 'professional', price: 500, metrics: 50, dataRetention: 90 },
      { name: 'enterprise', price: 2000, metrics: Infinity, dataRetention: 365 },
    ],
  },
})

on.Metrics.received(async (metrics) => {
  const monitors = await db.PerformanceMonitor.list({
    where: { enabled: true },
  })

  for (const monitor of monitors) {
    // Calculate performance metrics
    const performance = calculatePerformanceMetrics(metrics, monitor.config)

    // Check SLA compliance
    const slaCompliance = checkSLACompliance(performance, monitor.sla)

    // Store metrics
    await db.create($.PerformanceMetric, {
      monitorId: monitor.id,
      timestamp: new Date(),
      metrics: performance,
      slaCompliance,
    })

    // Check thresholds and send alerts
    for (const [metric, value] of Object.entries(performance)) {
      const threshold = monitor.thresholds[metric]

      if (threshold && value > threshold.critical) {
        await send.Alert.create({
          severity: 'critical',
          type: 'performance-threshold',
          monitor: monitor.name,
          metric,
          value,
          threshold: threshold.critical,
        })
      } else if (threshold && value > threshold.warning) {
        await send.Alert.create({
          severity: 'warning',
          type: 'performance-threshold',
          monitor: monitor.name,
          metric,
          value,
          threshold: threshold.warning,
        })
      }
    }

    // Update dashboard if configured
    if (monitor.dashboardId) {
      await send.Dashboard.update({
        dashboardId: monitor.dashboardId,
        metrics: performance,
      })
    }
  }
})

function calculatePerformanceMetrics(metrics: any, config: any): any {
  const performance = {}

  // Latency metrics
  if (config.trackLatency) {
    const latencies = metrics.filter((m) => m.type === 'latency').map((m) => m.value)
    performance.latency = {
      p50: percentile(latencies, 0.5),
      p95: percentile(latencies, 0.95),
      p99: percentile(latencies, 0.99),
      max: Math.max(...latencies),
      avg: latencies.reduce((sum, v) => sum + v, 0) / latencies.length,
    }
  }

  // Throughput metrics
  if (config.trackThroughput) {
    const requests = metrics.filter((m) => m.type === 'request')
    performance.throughput = {
      requestsPerSecond: requests.length / config.windowSize,
      requestsPerMinute: (requests.length / config.windowSize) * 60,
    }
  }

  // Error rate metrics
  if (config.trackErrors) {
    const errors = metrics.filter((m) => m.type === 'error')
    const total = metrics.length
    performance.errorRate = {
      percentage: (errors.length / total) * 100,
      count: errors.length,
      byType: groupBy(errors, 'errorType'),
    }
  }

  // Availability
  if (config.trackAvailability) {
    const uptime = metrics.filter((m) => m.type === 'health' && m.status === 'up').length
    const total = metrics.filter((m) => m.type === 'health').length
    performance.availability = (uptime / total) * 100
  }

  return performance
}

Business Intelligence Service

Generate comprehensive business insights:

const businessIntelligenceService = await $.Service.create({
  name: 'Business Intelligence Engine',
  description: 'Comprehensive business analysis with AI-powered insights',
  type: $.ServiceType.DataAnalytics,
  subtype: 'business-intelligence',

  input: {
    required: ['businessData'],
    optional: ['analysisType', 'timeframe', 'focus'],
  },

  analyses: [
    'revenue-analysis',
    'customer-analysis',
    'product-analysis',
    'market-analysis',
    'competitive-analysis',
    'operational-analysis',
    'financial-analysis',
  ],

  pricing: {
    model: 'per-analysis',
    base: 50.0,
    depth: {
      summary: 1.0,
      detailed: 2.0,
      comprehensive: 4.0,
    },
  },
})

on.ServiceRequest.created(async (request) => {
  if (request.serviceId !== businessIntelligenceService.id) return

  const { businessData, analysisType = 'comprehensive', timeframe = 'quarterly', focus } = request.inputs

  try {
    const analysis = {
      executive: {},
      detailed: {},
      insights: [],
      recommendations: [],
      forecasts: [],
    }

    // Executive Summary
    analysis.executive = await generateExecutiveSummary(businessData, timeframe)

    // Detailed Analysis
    const analysisAreas = focus || businessIntelligenceService.analyses

    for (const area of analysisAreas) {
      analysis.detailed[area] = await performDetailedAnalysis(businessData, area, timeframe)
    }

    // AI-Powered Insights
    const insights = await ai.analyze({
      model: 'gpt-5',
      data: { executive: analysis.executive, detailed: analysis.detailed },
      analysisType: 'business-intelligence',
      instructions: `
        As a business analyst, provide comprehensive insights:
        1. Key performance drivers and inhibitors
        2. Opportunities for growth and optimization
        3. Risks and threats to address
        4. Strategic recommendations
        5. Tactical next steps

        Be specific, data-driven, and actionable.
      `,
    })

    analysis.insights = insights.findings
    analysis.recommendations = insights.recommendations

    // Generate forecasts
    for (const area of ['revenue', 'customers', 'market-share']) {
      const forecast = await forecastBusinessMetric(businessData, area, 12) // Next 12 months
      analysis.forecasts.push({
        metric: area,
        forecast,
      })
    }

    // Create visualizations
    const visualizations = await generateBIVisualizations(analysis)

    // Compile comprehensive report
    const report = await compileBIReport(analysis, visualizations)
    const reportUrl = await uploadReport(report, 'pdf')

    // Deliver results
    await send.ServiceResult.deliver({
      requestId: request.id,
      outputs: {
        analysis,
        reportUrl,
        visualizations: visualizations.map((v) => v.url),
        summary: {
          areasAnalyzed: analysisAreas.length,
          insightsGenerated: analysis.insights.length,
          recommendationsMade: analysis.recommendations.length,
          forecastsCreated: analysis.forecasts.length,
        },
      },
    })

    // Calculate cost
    const depth = analysisAreas.length > 5 ? 'comprehensive' : analysisAreas.length > 2 ? 'detailed' : 'summary'
    const multiplier = businessIntelligenceService.pricing.depth[depth]
    const cost = businessIntelligenceService.pricing.base * multiplier

    await send.Payment.charge({
      customerId: request.customerId,
      amount: cost,
      description: `Business intelligence analysis (${depth})`,
    })
  } catch (error) {
    await send.ServiceRequest.fail({
      requestId: request.id,
      error: error.message,
      retryable: true,
    })
  }
})

Pricing Models for Analytics Services

Per-Report Pricing

Best for: Automated reporting

pricing: {
  model: 'per-report',
  base: 5.0,
  complexity: {
    simple: 1.0,
    moderate: 2.0,
    comprehensive: 3.0,
  },
}

Subscription Pricing

Best for: Dashboards, monitoring, continuous analytics

pricing: {
  model: 'subscription',
  tiers: [
    { name: 'basic', price: 100, features: ['basic-reports', '3-dashboards'] },
    { name: 'professional', price: 500, features: ['advanced-reports', '15-dashboards', 'kpi-tracking'] },
    { name: 'enterprise', price: 2000, features: ['unlimited', 'custom-analytics', 'api-access'] },
  ],
}

Per-Analysis Pricing

Best for: One-off analyses, business intelligence

pricing: {
  model: 'per-analysis',
  base: 50.0,
  depth: {
    summary: 1.0,
    detailed: 2.0,
    comprehensive: 4.0,
  },
}

Best Practices

1. Cache Expensive Calculations

const metricsCache = new Map()

async function getCachedMetrics(key: string, calculateFn: () => Promise<any>, ttl = 300000): Promise<any> {
  if (metricsCache.has(key)) {
    const cached = metricsCache.get(key)
    if (Date.now() - cached.timestamp < ttl) {
      return cached.data
    }
  }

  const data = await calculateFn()
  metricsCache.set(key, { data, timestamp: Date.now() })
  return data
}

2. Optimize Data Queries

async function optimizeQuery(query: any, dataSource: any): Promise<any> {
  // Add indexes for common query patterns
  const indexes = identifyRequiredIndexes(query)
  await ensureIndexes(dataSource, indexes)

  // Use aggregation pipelines when possible
  if (canUseAggregation(query)) {
    return executeAggregation(dataSource, query)
  }

  return executeQuery(dataSource, query)
}

3. Implement Progressive Loading

async function generateDashboard(config: any): Promise<any> {
  // Load critical widgets first
  const criticalWidgets = config.widgets.filter((w) => w.priority === 'high')
  await loadWidgets(criticalWidgets)

  // Load remaining widgets in background
  const remainingWidgets = config.widgets.filter((w) => w.priority !== 'high')
  loadWidgets(remainingWidgets).catch(console.error)
}

Next Steps