// SPDX-License-Identifier: Apache-2.0
// Copyright 2024-2026 Vorion LLC
/**
 * Metrics Bridge for OpenTelemetry Traces
 *
 * Bridges trace data to Prometheus metrics for observability correlation.
 * Exports span duration histograms, error rates, and operation counts.
 *
 * @packageDocumentation
 */
import { Counter, Histogram, Gauge, } from 'prom-client';
import { vorionRegistry } from '../metrics-registry.js';
import { createLogger } from '../logger.js';
const logger = createLogger({ component: 'telemetry-metrics-bridge' });
// =============================================================================
// Span Duration Histograms
// =============================================================================
/**
 * Histogram buckets for span durations (milliseconds)
 * Covers range from 1ms to 30s with exponential distribution
 */
const DURATION_BUCKETS = [
    1, 2, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, 30000,
];
/**
 * Span duration histogram for all operations
 */
export const spanDurationHistogram = new Histogram({
    name: 'vorion_trace_span_duration_ms',
    help: 'Duration of traced spans in milliseconds',
    labelNames: ['service', 'operation', 'span_kind', 'status'],
    buckets: DURATION_BUCKETS,
    registers: [vorionRegistry],
});
/**
 * Intent processing span duration
 */
export const intentSpanDuration = new Histogram({
    name: 'vorion_trace_intent_span_duration_ms',
    help: 'Duration of intent processing spans in milliseconds',
    labelNames: ['operation', 'intent_type', 'status'],
    buckets: DURATION_BUCKETS,
    registers: [vorionRegistry],
});
/**
 * Policy evaluation span duration
 */
export const policySpanDuration = new Histogram({
    name: 'vorion_trace_policy_span_duration_ms',
    help: 'Duration of policy evaluation spans in milliseconds',
    labelNames: ['namespace', 'action', 'status'],
    buckets: DURATION_BUCKETS,
    registers: [vorionRegistry],
});
/**
 * Security operation span duration
 */
export const securitySpanDuration = new Histogram({
    name: 'vorion_trace_security_span_duration_ms',
    help: 'Duration of security operation spans in milliseconds',
    labelNames: ['operation_type', 'status'],
    buckets: DURATION_BUCKETS,
    registers: [vorionRegistry],
});
/**
 * Database operation span duration
 */
export const dbSpanDuration = new Histogram({
    name: 'vorion_trace_db_span_duration_ms',
    help: 'Duration of database operation spans in milliseconds',
    labelNames: ['operation', 'table', 'status'],
    buckets: DURATION_BUCKETS,
    registers: [vorionRegistry],
});
/**
 * Cache operation span duration
 */
export const cacheSpanDuration = new Histogram({
    name: 'vorion_trace_cache_span_duration_ms',
    help: 'Duration of cache operation spans in milliseconds',
    labelNames: ['operation', 'hit', 'status'],
    buckets: [0.5, 1, 2, 5, 10, 25, 50, 100, 250, 500],
    registers: [vorionRegistry],
});
/**
 * HTTP request span duration
 */
export const httpSpanDuration = new Histogram({
    name: 'vorion_trace_http_span_duration_ms',
    help: 'Duration of HTTP request spans in milliseconds',
    labelNames: ['method', 'route', 'status_code'],
    buckets: DURATION_BUCKETS,
    registers: [vorionRegistry],
});
// =============================================================================
// Error Rate Counters
// =============================================================================
/**
 * Total span count by operation
 */
export const spanCounter = new Counter({
    name: 'vorion_trace_spans_total',
    help: 'Total number of traced spans',
    labelNames: ['service', 'operation', 'span_kind', 'status'],
    registers: [vorionRegistry],
});
/**
 * Span error counter
 */
export const spanErrorCounter = new Counter({
    name: 'vorion_trace_span_errors_total',
    help: 'Total number of span errors',
    labelNames: ['service', 'operation', 'error_type'],
    registers: [vorionRegistry],
});
/**
 * Security event counter
 */
export const securityEventCounter = new Counter({
    name: 'vorion_trace_security_events_total',
    help: 'Total number of security events in traces',
    labelNames: ['event_type', 'risk_level', 'tenant_id'],
    registers: [vorionRegistry],
});
/**
 * Policy decision counter
 */
export const policyDecisionCounter = new Counter({
    name: 'vorion_trace_policy_decisions_total',
    help: 'Total number of policy decisions',
    labelNames: ['namespace', 'action', 'result'],
    registers: [vorionRegistry],
});
/**
 * Trust evaluation counter
 */
export const trustEvalCounter = new Counter({
    name: 'vorion_trace_trust_evaluations_total',
    help: 'Total number of trust evaluations',
    labelNames: ['result', 'trust_level'],
    registers: [vorionRegistry],
});
// =============================================================================
// Active Span Gauges
// =============================================================================
/**
 * Currently active spans
 */
export const activeSpansGauge = new Gauge({
    name: 'vorion_trace_active_spans',
    help: 'Number of currently active spans',
    labelNames: ['service', 'operation'],
    registers: [vorionRegistry],
});
/**
 * Active HTTP requests
 */
export const activeHttpRequests = new Gauge({
    name: 'vorion_trace_active_http_requests',
    help: 'Number of currently active HTTP requests',
    labelNames: ['method', 'route'],
    registers: [vorionRegistry],
});
/**
 * Record span completion metrics
 *
 * @param labels - Span labels
 * @param durationMs - Span duration in milliseconds
 */
export function recordSpanMetrics(labels, durationMs) {
    // Record duration histogram
    spanDurationHistogram.observe({
        service: labels.service,
        operation: labels.operation,
        span_kind: labels.spanKind,
        status: labels.status,
    }, durationMs);
    // Increment span counter
    spanCounter.inc({
        service: labels.service,
        operation: labels.operation,
        span_kind: labels.spanKind,
        status: labels.status,
    });
}
/**
 * Record span error
 *
 * @param service - Service name
 * @param operation - Operation name
 * @param errorType - Error type/name
 */
export function recordSpanError(service, operation, errorType) {
    spanErrorCounter.inc({
        service,
        operation,
        error_type: errorType,
    });
}
/**
 * Record intent span metrics
 *
 * @param operation - Operation name
 * @param intentType - Intent type
 * @param status - Span status
 * @param durationMs - Duration in milliseconds
 */
export function recordIntentSpanMetrics(operation, intentType, status, durationMs) {
    intentSpanDuration.observe({
        operation,
        intent_type: intentType,
        status,
    }, durationMs);
}
/**
 * Record policy span metrics
 *
 * @param namespace - Policy namespace
 * @param action - Policy action
 * @param status - Span status
 * @param durationMs - Duration in milliseconds
 */
export function recordPolicySpanMetrics(namespace, action, status, durationMs) {
    policySpanDuration.observe({
        namespace,
        action,
        status,
    }, durationMs);
}
/**
 * Record security span metrics
 *
 * @param operationType - Security operation type
 * @param status - Span status
 * @param durationMs - Duration in milliseconds
 */
export function recordSecuritySpanMetrics(operationType, status, durationMs) {
    securitySpanDuration.observe({
        operation_type: operationType,
        status,
    }, durationMs);
}
/**
 * Record database span metrics
 *
 * @param operation - DB operation (select, insert, update, delete)
 * @param table - Table name
 * @param status - Span status
 * @param durationMs - Duration in milliseconds
 */
export function recordDbSpanMetrics(operation, table, status, durationMs) {
    dbSpanDuration.observe({
        operation,
        table,
        status,
    }, durationMs);
}
/**
 * Record cache span metrics
 *
 * @param operation - Cache operation (get, set, del)
 * @param hit - Whether cache hit (for get operations)
 * @param status - Span status
 * @param durationMs - Duration in milliseconds
 */
export function recordCacheSpanMetrics(operation, hit, status, durationMs) {
    cacheSpanDuration.observe({
        operation,
        hit: hit ? 'true' : 'false',
        status,
    }, durationMs);
}
/**
 * Record HTTP span metrics
 *
 * @param method - HTTP method
 * @param route - Route pattern
 * @param statusCode - HTTP status code
 * @param durationMs - Duration in milliseconds
 */
export function recordHttpSpanMetrics(method, route, statusCode, durationMs) {
    httpSpanDuration.observe({
        method,
        route,
        status_code: String(statusCode),
    }, durationMs);
}
/**
 * Record security event
 *
 * @param eventType - Security event type
 * @param riskLevel - Risk level (low, medium, high, critical)
 * @param tenantId - Tenant ID (optional)
 */
export function recordSecurityEvent(eventType, riskLevel, tenantId) {
    securityEventCounter.inc({
        event_type: eventType,
        risk_level: riskLevel,
        tenant_id: tenantId ?? 'unknown',
    });
}
/**
 * Record policy decision
 *
 * @param namespace - Policy namespace
 * @param action - Policy action
 * @param result - Decision result (allow, deny, escalate)
 */
export function recordPolicyDecision(namespace, action, result) {
    policyDecisionCounter.inc({
        namespace,
        action,
        result,
    });
}
/**
 * Record trust evaluation
 *
 * @param result - Evaluation result (passed, failed, insufficient)
 * @param trustLevel - Required trust level
 */
export function recordTrustEvaluation(result, trustLevel) {
    trustEvalCounter.inc({
        result,
        trust_level: String(trustLevel),
    });
}
/**
 * Increment active span count
 *
 * @param service - Service name
 * @param operation - Operation name
 */
export function incrementActiveSpans(service, operation) {
    activeSpansGauge.inc({
        service,
        operation,
    });
}
/**
 * Decrement active span count
 *
 * @param service - Service name
 * @param operation - Operation name
 */
export function decrementActiveSpans(service, operation) {
    activeSpansGauge.dec({
        service,
        operation,
    });
}
/**
 * Increment active HTTP requests
 *
 * @param method - HTTP method
 * @param route - Route pattern
 */
export function incrementActiveHttpRequests(method, route) {
    activeHttpRequests.inc({
        method,
        route,
    });
}
/**
 * Decrement active HTTP requests
 *
 * @param method - HTTP method
 * @param route - Route pattern
 */
export function decrementActiveHttpRequests(method, route) {
    activeHttpRequests.dec({
        method,
        route,
    });
}
/**
 * Process span end for metrics recording
 *
 * Call this from span processor or instrumentation hooks to
 * automatically record metrics for completed spans.
 *
 * @param data - Span end data
 */
export function processSpanForMetrics(data) {
    try {
        // Record general span metrics
        recordSpanMetrics({
            service: data.service,
            operation: data.name,
            spanKind: data.kind,
            status: data.status,
        }, data.durationMs);
        // Record error if present
        if (data.error) {
            recordSpanError(data.service, data.name, data.error.name);
        }
        // Route to specific metric handlers based on span attributes
        if (data.attributes['vorion.intent.id']) {
            recordIntentSpanMetrics(data.name, data.attributes['vorion.intent.type'] ?? 'default', data.status === 'error' ? 'error' : 'ok', data.durationMs);
        }
        if (data.attributes['vorion.policy.namespace']) {
            recordPolicySpanMetrics(data.attributes['vorion.policy.namespace'], data.attributes['vorion.policy.action'] ?? 'evaluate', data.status === 'error' ? 'error' : 'ok', data.durationMs);
        }
        if (data.attributes['vorion.security.event']) {
            recordSecuritySpanMetrics(data.attributes['security.operation_type'] ?? 'unknown', data.status === 'error' ? 'error' : 'ok', data.durationMs);
        }
        if (data.attributes['db.operation']) {
            recordDbSpanMetrics(data.attributes['db.operation'], data.attributes['vorion.db.table'] ?? 'unknown', data.status === 'error' ? 'error' : 'ok', data.durationMs);
        }
        if (data.attributes['vorion.cache.key']) {
            recordCacheSpanMetrics(data.attributes['db.operation'] ?? 'unknown', data.attributes['vorion.cache.hit'] === true, data.status === 'error' ? 'error' : 'ok', data.durationMs);
        }
        if (data.kind === 'server' && data.attributes['http.method']) {
            recordHttpSpanMetrics(data.attributes['http.method'], data.attributes['http.route'] ?? data.name, data.attributes['http.status_code'] ?? 0, data.durationMs);
        }
    }
    catch (error) {
        logger.error({ error }, 'Error processing span for metrics');
    }
}
/**
 * Initialize metrics bridge
 *
 * Sets up any required initialization for the metrics bridge.
 */
export function initializeMetricsBridge() {
    logger.info('Trace metrics bridge initialized');
}
/**
 * Get all trace-related metrics for debugging
 */
export function getTraceMetrics() {
    return {
        spanDurationCount: spanDurationHistogram.hashMap?.length ?? 0,
        spanTotalCount: spanCounter.hashMap?.length ?? 0,
        errorCount: spanErrorCounter.hashMap?.length ?? 0,
    };
}
//# sourceMappingURL=metrics-bridge.js.map