Skip to content

Implement PrometheusCollector as built-in metrics collector #120

@vlavrynovych

Description

@vlavrynovych

Overview

Implement PrometheusCollector as a built-in metrics collector in MSR core, exposing metrics endpoint for Prometheus scraping and Grafana dashboards.

Current State

PrometheusCollector is currently documented as a custom collector example in the documentation (docs/customization/metrics/custom-collectors.md), but not implemented as a built-in collector.

Proposed Implementation

Add PrometheusCollector to src/metrics/collectors/ using the Prometheus client:

import { IMetricsCollector } from '../../interface/IMetricsCollector';
import { register, Counter, Histogram, Gauge } from 'prom-client';

export interface PrometheusCollectorConfig {
  port: number;
  prefix?: string;  // default: 'msr_'
}

export class PrometheusCollector implements IMetricsCollector {
  private migrationsTotal: Counter;
  private migrationDuration: Histogram;
  private pendingMigrations: Gauge;
  private server: any;

  constructor(config: PrometheusCollectorConfig) {
    const prefix = config.prefix || 'msr_';

    this.migrationsTotal = new Counter({
      name: `${prefix}migrations_total`,
      help: 'Total number of migrations executed',
      labelNames: ['status', 'script_name']
    });

    this.migrationDuration = new Histogram({
      name: `${prefix}migration_duration_seconds`,
      help: 'Migration execution duration in seconds',
      labelNames: ['script_name'],
      buckets: [0.1, 0.5, 1, 2, 5, 10, 30, 60]
    });

    this.pendingMigrations = new Gauge({
      name: `${prefix}pending_migrations`,
      help: 'Number of pending migrations'
    });

    this.startServer(config.port);
  }

  recordMigrationStart(context) {
    this.pendingMigrations.set(context.pending);
  }

  recordScriptComplete(script, duration) {
    this.migrationsTotal.inc({ status: 'success', script_name: script.name });
    this.migrationDuration.observe({ script_name: script.name }, duration / 1000);
  }

  recordScriptError(script, error) {
    this.migrationsTotal.inc({ status: 'failed', script_name: script.name });
  }

  private startServer(port) {
    // Start HTTP server for /metrics endpoint
  }

  async close() {
    if (this.server) {
      this.server.close();
    }
  }
}

Requirements

  • Implement PrometheusCollector in src/metrics/collectors/PrometheusCollector.ts
  • Add prom-client as peer dependency
  • Export from src/metrics/collectors/index.ts
  • Write comprehensive unit tests (mock Prometheus client)
  • Update documentation to reflect built-in status
  • Add Grafana dashboard JSON example in docs
  • Add integration example with Prometheus scraping config
  • Add to metrics overview documentation

Dependencies

  • prom-client (peer dependency) - Prometheus client for Node.js

Related

Acceptance Criteria

  • PrometheusCollector implemented with full IMetricsCollector interface
  • HTTP server exposes /metrics endpoint
  • 100% test coverage maintained
  • Peer dependency added to package.json
  • Documentation updated with Grafana dashboard example
  • Example Prometheus scrape config in docs
  • Works with Prometheus and Grafana

Metadata

Metadata

Assignees

Labels

⚡ Priority: HighImportant tasks requiring quick attention✨ Type: FeatureNew functionality or enhancement🟡 Test: MediumModerate testing effort required

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions