Skip to content

Orchestration Metrics & Monitoring ​

Comprehensive observability framework for orchestration layer components with metrics collection, alerting, and performance analysis.

Overview ​

Monitoring Philosophy ​

  • Proactive Detection: Catch issues before they impact users
  • Performance Optimization: Continuous improvement through data
  • Resource Management: Track costs and optimize budgets
  • Quality Assurance: Monitor output quality and user satisfaction

Monitoring Stack ​

text
Metrics Collection β†’ Time Series DB β†’ Alerting β†’ Dashboards
     ↓                   ↓              ↓           ↓
  Components         Prometheus      AlertManager  Grafana
    Events           InfluxDB         PagerDuty    Custom
   Logging           DataDog          Slack        Mobile

Core Metrics (v0) ​

Request-Level Metrics ​

typescript
interface RequestMetrics {
  // Request identification
  request_id: string;
  user_id: string;
  timestamp: Date;
  
  // CEO metrics
  ceo_intent_parsing_ms: number;
  ceo_budget_allocation_ms: number;
  ceo_total_ms: number;
  
  // ACS metrics  
  acs_provider_scoring_ms: number;
  acs_provider_selection_ms: number;
  acs_execution_ms: number;
  acs_total_ms: number;
  
  // Resource utilization
  used_tokens: number;
  total_cost_cents: number;
  max_budget_cents: number;
  budget_utilization_ratio: number; // 0.0-1.0
  
  // Quality metrics
  quality_achieved: number; // 0.0-1.0
  quality_target: number;   // 0.0-1.0
  quality_gap: number;      // target - achieved
  
  // Provider metrics
  providers_attempted: string[];
  providers_succeeded: string[];
  providers_failed: string[];
  provider_fallback_count: number;
  
  // Coverage metrics (v0 compatibility)
  coverage_entities: number; // ratio of covered entities (0..1)
  
  // Error tracking
  errors: ErrorMetric[];
  warnings: WarningMetric[];
}

interface ErrorMetric {
  component: 'ceo' | 'acs' | 'provider' | 'system';
  error_type: string;
  error_message: string;
  error_code?: string;
  recoverable: boolean;
  timestamp: Date;
}

interface WarningMetric {
  component: 'ceo' | 'acs' | 'provider' | 'system';
  warning_type: string;
  warning_message: string;
  impact_level: 'low' | 'medium' | 'high';
  timestamp: Date;
}

System-Level Metrics ​

typescript
interface SystemMetrics {
  // Performance metrics
  requests_per_second: number;
  avg_response_time_ms: number;
  p50_response_time_ms: number;
  p95_response_time_ms: number;
  p99_response_time_ms: number;
  
  // Reliability metrics
  success_rate: number;           // 0.0-1.0
  error_rate: number;             // 0.0-1.0
  timeout_rate: number;           // 0.0-1.0
  provider_failure_rate: number; // 0.0-1.0
  
  // Resource metrics
  cpu_utilization: number;        // 0.0-1.0
  memory_utilization: number;     // 0.0-1.0
  disk_usage: number;            // bytes
  network_io: number;            // bytes/sec
  
  // Cost metrics
  total_cost_per_hour: number;   // cents
  cost_per_request: number;      // cents
  cost_trend_24h: number;        // percent change
  budget_burn_rate: number;      // cents/hour
  
  // Provider health
  provider_health_scores: Record<string, number>; // provider_id -> health (0.0-1.0)
  provider_response_times: Record<string, number>; // provider_id -> avg_ms
  provider_success_rates: Record<string, number>;  // provider_id -> success_rate
}

Metrics Collection Implementation ​

Metrics Collector Service ​

typescript
// services/metrics-collector.ts
import { EventEmitter } from 'events';

export class MetricsCollector extends EventEmitter {
  private metrics: Map<string, any[]> = new Map();
  private systemMetrics: SystemMetrics = this.initializeSystemMetrics();
  private metricsBuffer: RequestMetrics[] = [];
  private flushInterval: NodeJS.Timer;

  constructor(private config: MetricsConfig) {
    super();
    this.startMetricsFlush();
    this.startSystemMetricsCollection();
  }

  // Request-level metrics
  recordRequestStart(requestId: string, userId: string): void {
    const metric: Partial<RequestMetrics> = {
      request_id: requestId,
      user_id: userId,
      timestamp: new Date(),
      errors: [],
      warnings: []
    };
    
    this.metrics.set(requestId, metric);
    this.emit('request_started', metric);
  }

  recordCEOMetrics(requestId: string, ceoMetrics: {
    intent_parsing_ms: number;
    budget_allocation_ms: number;
    total_ms: number;
  }): void {
    const metric = this.metrics.get(requestId);
    if (metric) {
      Object.assign(metric, {
        ceo_intent_parsing_ms: ceoMetrics.intent_parsing_ms,
        ceo_budget_allocation_ms: ceoMetrics.budget_allocation_ms,
        ceo_total_ms: ceoMetrics.total_ms
      });
    }
  }

  recordACSMetrics(requestId: string, acsMetrics: {
    provider_scoring_ms: number;
    provider_selection_ms: number;
    execution_ms: number;
    total_ms: number;
    providers_attempted: string[];
    providers_succeeded: string[];
    providers_failed: string[];
    total_cost_cents: number;
    quality_achieved: number;
  }): void {
    const metric = this.metrics.get(requestId);
    if (metric) {
      Object.assign(metric, {
        acs_provider_scoring_ms: acsMetrics.provider_scoring_ms,
        acs_provider_selection_ms: acsMetrics.provider_selection_ms,
        acs_execution_ms: acsMetrics.execution_ms,
        acs_total_ms: acsMetrics.total_ms,
        providers_attempted: acsMetrics.providers_attempted,
        providers_succeeded: acsMetrics.providers_succeeded,
        providers_failed: acsMetrics.providers_failed,
        total_cost_cents: acsMetrics.total_cost_cents,
        quality_achieved: acsMetrics.quality_achieved,
        provider_fallback_count: acsMetrics.providers_attempted.length - 1
      });
    }
  }

  recordError(requestId: string, error: ErrorMetric): void {
    const metric = this.metrics.get(requestId);
    if (metric) {
      metric.errors.push(error);
      this.emit('error_recorded', { requestId, error });
    }
  }

  recordWarning(requestId: string, warning: WarningMetric): void {
    const metric = this.metrics.get(requestId);
    if (metric) {
      metric.warnings.push(warning);
      this.emit('warning_recorded', { requestId, warning });
    }
  }

  completeRequest(requestId: string): void {
    const metric = this.metrics.get(requestId) as RequestMetrics;
    if (metric) {
      // Finalize metrics
      metric.budget_utilization_ratio = metric.total_cost_cents / (metric.max_budget_cents || 1);
      metric.quality_gap = (metric.quality_target || 0.8) - (metric.quality_achieved || 0);
      
      // Add to buffer for batch processing
      this.metricsBuffer.push(metric);
      
      // Update system metrics
      this.updateSystemMetrics(metric);
      
      // Clean up
      this.metrics.delete(requestId);
      
      this.emit('request_completed', metric);
    }
  }

  private updateSystemMetrics(requestMetric: RequestMetrics): void {
    // Update rolling averages and counters
    const totalTime = (requestMetric.ceo_total_ms || 0) + (requestMetric.acs_total_ms || 0);
    
    // Simple moving average (can be enhanced with proper time-series calculations)
    this.systemMetrics.avg_response_time_ms = (this.systemMetrics.avg_response_time_ms + totalTime) / 2;
    
    // Update success/error rates
    const hasErrors = requestMetric.errors.length > 0;
    this.systemMetrics.error_rate = this.updateRate(this.systemMetrics.error_rate, hasErrors);
    this.systemMetrics.success_rate = 1.0 - this.systemMetrics.error_rate;
    
    // Update cost metrics
    this.systemMetrics.cost_per_request = (this.systemMetrics.cost_per_request + requestMetric.total_cost_cents) / 2;
  }

  private updateRate(currentRate: number, isEvent: boolean): number {
    const alpha = 0.1; // Exponential moving average factor
    return alpha * (isEvent ? 1.0 : 0.0) + (1 - alpha) * currentRate;
  }

  private startMetricsFlush(): void {
    this.flushInterval = setInterval(() => {
      if (this.metricsBuffer.length > 0) {
        this.flushMetrics();
      }
    }, this.config.flush_interval_ms);
  }

  private flushMetrics(): void {
    const batch = [...this.metricsBuffer];
    this.metricsBuffer = [];
    
    // Send to time-series database
    this.sendToTimeSeriesDB(batch);
    
    // Send to logging system
    this.sendToLogSystem(batch);
    
    this.emit('metrics_flushed', { count: batch.length });
  }

  private sendToTimeSeriesDB(metrics: RequestMetrics[]): void {
    // Implementation depends on your time-series DB (Prometheus, InfluxDB, etc.)
    // This is a placeholder
    console.log(`Flushing ${metrics.length} metrics to time-series DB`);
  }

  private sendToLogSystem(metrics: RequestMetrics[]): void {
    // Send structured logs for analysis
    for (const metric of metrics) {
      console.log(JSON.stringify({
        level: 'info',
        type: 'request_metric',
        ...metric
      }));
    }
  }

  getSystemMetrics(): SystemMetrics {
    return { ...this.systemMetrics };
  }

  private startSystemMetricsCollection(): void {
    setInterval(() => {
      this.collectSystemMetrics();
    }, this.config.system_metrics_interval_ms);
  }

  private collectSystemMetrics(): void {
    // Collect system-level metrics (CPU, memory, etc.)
    // This would integrate with system monitoring tools
    this.systemMetrics.cpu_utilization = process.cpuUsage().system / 1000000; // Simplified
    this.systemMetrics.memory_utilization = process.memoryUsage().heapUsed / process.memoryUsage().heapTotal;
  }

  private initializeSystemMetrics(): SystemMetrics {
    return {
      requests_per_second: 0,
      avg_response_time_ms: 0,
      p50_response_time_ms: 0,
      p95_response_time_ms: 0,
      p99_response_time_ms: 0,
      success_rate: 1.0,
      error_rate: 0.0,
      timeout_rate: 0.0,
      provider_failure_rate: 0.0,
      cpu_utilization: 0,
      memory_utilization: 0,
      disk_usage: 0,
      network_io: 0,
      total_cost_per_hour: 0,
      cost_per_request: 0,
      cost_trend_24h: 0,
      budget_burn_rate: 0,
      provider_health_scores: {},
      provider_response_times: {},
      provider_success_rates: {}
    };
  }
}

interface MetricsConfig {
  flush_interval_ms: number;
  system_metrics_interval_ms: number;
  retention_days: number;
  alerting_enabled: boolean;
}

Integration with Components ​

typescript
// Example: Integrating with CEO service
export class BasicCEO {
  constructor(private metricsCollector: MetricsCollector) {}

  async processQuery(query: UserQuery): Promise<CEORequest> {
    const requestId = uuidv4();
    this.metricsCollector.recordRequestStart(requestId, query.user_id || 'anonymous');

    const startTime = Date.now();
    try {
      // Intent parsing
      const intentStart = Date.now();
      const intent = this.intentParser.parseIntent(query);
      const intentTime = Date.now() - intentStart;

      // Budget allocation  
      const budgetStart = Date.now();
      const budget = this.budgetAllocator.allocateBudget(intent);
      const budgetTime = Date.now() - budgetStart;

      const totalTime = Date.now() - startTime;

      // Record CEO metrics
      this.metricsCollector.recordCEOMetrics(requestId, {
        intent_parsing_ms: intentTime,
        budget_allocation_ms: budgetTime,
        total_ms: totalTime
      });

      return {
        query,
        intent,
        budget,
        request_id: requestId,
        timestamp: new Date()
      };

    } catch (error) {
      this.metricsCollector.recordError(requestId, {
        component: 'ceo',
        error_type: 'processing_failed',
        error_message: error.message,
        recoverable: false,
        timestamp: new Date()
      });
      throw error;
    }
  }
}

Alerting & SLOs ​

Service Level Objectives (SLOs) ​

yaml
# Production SLOs
slos:
  availability:
    target: 99.5%
    measurement_window: 30d
    alert_threshold: 99.0%
    
  response_time:
    target: 95th_percentile < 2000ms
    measurement_window: 24h
    alert_threshold: 95th_percentile > 3000ms
    
  error_rate:
    target: < 1.0%
    measurement_window: 1h
    alert_threshold: > 2.0%
    
  cost_efficiency:
    target: < $0.10 per request
    measurement_window: 24h
    alert_threshold: > $0.15 per request
    
  quality_score:
    target: > 0.8
    measurement_window: 1h
    alert_threshold: < 0.7

Alert Configurations ​

typescript
interface AlertRule {
  name: string;
  condition: string;
  severity: 'critical' | 'warning' | 'info';
  threshold: number;
  duration: string;
  notification_channels: string[];
  runbook_url?: string;
}

const alertRules: AlertRule[] = [
  {
    name: 'High Error Rate',
    condition: 'error_rate > threshold',
    severity: 'critical',
    threshold: 0.05, // 5%
    duration: '5m',
    notification_channels: ['pagerduty', 'slack-alerts'],
    runbook_url: 'https://docs.company.com/runbooks/orchestration-errors'
  },
  {
    name: 'Response Time Degradation',
    condition: 'p95_response_time_ms > threshold',
    severity: 'warning',
    threshold: 3000,
    duration: '10m',
    notification_channels: ['slack-alerts'],
    runbook_url: 'https://docs.company.com/runbooks/performance-issues'
  },
  {
    name: 'Provider Health Degradation',
    condition: 'provider_success_rate < threshold',
    severity: 'warning',
    threshold: 0.9, // 90%
    duration: '5m',
    notification_channels: ['slack-alerts']
  },
  {
    name: 'Budget Burn Rate High',
    condition: 'budget_burn_rate > threshold',
    severity: 'warning',
    threshold: 100, // cents per hour
    duration: '30m',
    notification_channels: ['email-finance', 'slack-alerts']
  },
  {
    name: 'Memory Usage High',
    condition: 'memory_utilization > threshold',
    severity: 'warning',
    threshold: 0.85, // 85%
    duration: '15m',
    notification_channels: ['slack-alerts']
  }
];

Dashboards ​

Executive Dashboard (High-Level) ​

json
{
  "dashboard": "Orchestration Executive View",
  "panels": [
    {
      "title": "Request Volume",
      "type": "graph",
      "metrics": ["requests_per_second"],
      "timeframe": "24h"
    },
    {
      "title": "Success Rate",
      "type": "stat",
      "metrics": ["success_rate"],
      "target": 0.995
    },
    {
      "title": "Cost Efficiency",
      "type": "graph", 
      "metrics": ["cost_per_request", "total_cost_per_hour"],
      "timeframe": "7d"
    },
    {
      "title": "Quality Score",
      "type": "gauge",
      "metrics": ["avg_quality_achieved"],
      "target": 0.8
    }
  ]
}

Technical Dashboard (Detailed) ​

json
{
  "dashboard": "Orchestration Technical View",
  "panels": [
    {
      "title": "Component Latency Breakdown",
      "type": "stacked_graph",
      "metrics": [
        "ceo_total_ms",
        "acs_provider_scoring_ms", 
        "acs_execution_ms"
      ],
      "timeframe": "6h"
    },
    {
      "title": "Provider Performance",
      "type": "table",
      "metrics": [
        "provider_response_times",
        "provider_success_rates",
        "provider_health_scores"
      ]
    },
    {
      "title": "Error Distribution",
      "type": "pie_chart",
      "metrics": ["errors_by_component"],
      "timeframe": "24h"
    },
    {
      "title": "Resource Utilization",
      "type": "multi_stat",
      "metrics": [
        "cpu_utilization",
        "memory_utilization",
        "budget_utilization_ratio"
      ]
    }
  ]
}

Performance Analysis ​

Query Patterns ​

sql
-- Top expensive queries (cost analysis)
SELECT 
  intent.domain,
  intent.complexity,
  AVG(total_cost_cents) as avg_cost,
  COUNT(*) as request_count,
  AVG(quality_achieved) as avg_quality
FROM request_metrics 
WHERE timestamp >= NOW() - INTERVAL '24 hours'
GROUP BY intent.domain, intent.complexity
ORDER BY avg_cost DESC;

-- Provider effectiveness analysis
SELECT 
  provider_id,
  COUNT(*) as requests,
  AVG(execution_time_ms) as avg_latency,
  SUM(CASE WHEN success THEN 1 ELSE 0 END) * 100.0 / COUNT(*) as success_rate,
  AVG(quality_score) as avg_quality
FROM provider_executions
WHERE timestamp >= NOW() - INTERVAL '7 days'
GROUP BY provider_id
ORDER BY success_rate DESC, avg_quality DESC;

-- Budget utilization trends
SELECT 
  DATE(timestamp) as date,
  AVG(budget_utilization_ratio) as avg_utilization,
  MAX(budget_utilization_ratio) as max_utilization,
  COUNT(CASE WHEN budget_utilization_ratio > 0.8 THEN 1 END) as high_utilization_count
FROM request_metrics
WHERE timestamp >= NOW() - INTERVAL '30 days'
GROUP BY DATE(timestamp)
ORDER BY date;

Optimization Recommendations ​

typescript
interface OptimizationInsight {
  type: 'cost' | 'performance' | 'quality' | 'reliability';
  priority: 'high' | 'medium' | 'low';
  description: string;
  impact_estimate: string;
  action_required: string;
}

const generateOptimizationInsights = (metrics: SystemMetrics): OptimizationInsight[] => {
  const insights: OptimizationInsight[] = [];
  
  // Cost optimization
  if (metrics.cost_per_request > 15) {
    insights.push({
      type: 'cost',
      priority: 'high',
      description: 'Average cost per request is above target',
      impact_estimate: 'Potential 20-30% cost reduction',
      action_required: 'Review provider selection algorithms and budget allocation'
    });
  }
  
  // Performance optimization
  if (metrics.p95_response_time_ms > 3000) {
    insights.push({
      type: 'performance',
      priority: 'medium',
      description: '95th percentile response time exceeds 3 seconds',
      impact_estimate: 'Improved user experience',
      action_required: 'Analyze slow queries and optimize provider selection'
    });
  }
  
  // Quality optimization
  const avgQuality = Object.values(metrics.provider_health_scores).reduce((a, b) => a + b, 0) / 
                    Object.values(metrics.provider_health_scores).length;
  if (avgQuality < 0.8) {
    insights.push({
      type: 'quality',
      priority: 'high',
      description: 'Average quality score below target',
      impact_estimate: 'Better user satisfaction',
      action_required: 'Review quality scoring models and provider capabilities'
    });
  }
  
  return insights;
};

Configuration & Setup ​

Environment Configuration ​

typescript
const metricsConfig: MetricsConfig = {
  // Collection settings
  flush_interval_ms: process.env.NODE_ENV === 'production' ? 30000 : 60000,
  system_metrics_interval_ms: 15000,
  retention_days: 90,
  alerting_enabled: process.env.NODE_ENV === 'production',
  
  // Database settings
  timeseries_db: {
    type: 'prometheus', // or 'influxdb', 'datadog'
    endpoint: process.env.METRICS_DB_ENDPOINT,
    auth: process.env.METRICS_DB_AUTH
  },
  
  // Alerting settings
  alert_manager: {
    endpoint: process.env.ALERT_MANAGER_ENDPOINT,
    channels: {
      slack: process.env.SLACK_WEBHOOK_URL,
      pagerduty: process.env.PAGERDUTY_API_KEY,
      email: process.env.EMAIL_SMTP_CONFIG
    }
  }
};

Deployment Integration ​

yaml
# docker-compose.yml monitoring stack
version: '3.8'
services:
  orchestration:
    build: .
    environment:
      - METRICS_DB_ENDPOINT=http://prometheus:9090
      - ALERT_MANAGER_ENDPOINT=http://alertmanager:9093
    depends_on:
      - prometheus
      - grafana
      
  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      
  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - ./grafana-dashboards:/var/lib/grafana/dashboards
      
  alertmanager:
    image: prom/alertmanager
    ports:
      - "9093:9093"
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml

Quick Start Checklist ​

Implementation (First Hour) ​

  • [ ] Add MetricsCollector to your services
  • [ ] Implement basic request tracking
  • [ ] Set up console logging for metrics
  • [ ] Test with sample requests

Monitoring Setup (First Day) ​

  • [ ] Deploy Prometheus/InfluxDB for time-series storage
  • [ ] Configure Grafana dashboards
  • [ ] Set up basic alerting rules
  • [ ] Test alert notifications

Production Readiness (First Week) ​

  • [ ] Configure SLOs based on business requirements
  • [ ] Set up comprehensive alerting
  • [ ] Create runbooks for common issues
  • [ ] Implement log aggregation and analysis

Next: Troubleshooting Guide β†’