UNPKG

@pulzar/core

Version:

Next-generation Node.js framework for ultra-fast web applications with zero-reflection DI, GraphQL, WebSockets, events, and edge runtime support

235 lines 8.33 kB
import { NodeSDK } from "@opentelemetry/sdk-node"; import { Resource } from "@opentelemetry/resources"; import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions"; import { getNodeAutoInstrumentations } from "@opentelemetry/auto-instrumentations-node"; import { PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics"; import { logger } from "../utils/logger"; export class TelemetryManager { sdk; config; isInitialized = false; constructor(config = {}) { this.config = { serviceName: process.env.SERVICE_NAME || "ignite-app", serviceVersion: process.env.SERVICE_VERSION || "1.0.0", environment: process.env.NODE_ENV || "development", enableTracing: true, enableMetrics: true, enableLogs: true, exporters: { traces: { type: "console" }, metrics: { type: "console" }, logs: { type: "console" }, }, instrumentations: { http: true, express: true, fs: false, dns: false, redis: true, mysql: true, postgres: true, }, ...config, }; } /** * Initialize OpenTelemetry SDK */ async initialize() { if (this.isInitialized) { logger.warn("Telemetry already initialized"); return; } try { // Create resource const resource = new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: this.config.serviceName, [SemanticResourceAttributes.SERVICE_VERSION]: this.config.serviceVersion, [SemanticResourceAttributes.DEPLOYMENT_ENVIRONMENT]: this.config.environment, [SemanticResourceAttributes.SERVICE_INSTANCE_ID]: this.generateInstanceId(), }); // Configure instrumentations const instrumentations = this.getInstrumentations(); // Configure trace exporters const traceExporter = this.getTraceExporter(); // Configure metric readers const metricReaders = this.getMetricReaders(); // Create SDK this.sdk = new NodeSDK({ resource, instrumentations, ...(traceExporter && { traceExporter }), ...(metricReaders.length > 0 && { metricReaders }), }); // Start SDK await this.sdk.start(); this.isInitialized = true; logger.info("OpenTelemetry initialized successfully", { serviceName: this.config.serviceName, environment: this.config.environment, }); } catch (error) { logger.error("Failed to initialize OpenTelemetry", { error }); throw error; } } /** * Shutdown telemetry */ async shutdown() { if (!this.sdk || !this.isInitialized) { return; } try { await this.sdk.shutdown(); this.isInitialized = false; logger.info("OpenTelemetry shutdown successfully"); } catch (error) { logger.error("Failed to shutdown OpenTelemetry", { error }); throw error; } } /** * Get configured instrumentations */ getInstrumentations() { const autoInstrumentations = getNodeAutoInstrumentations({ "@opentelemetry/instrumentation-http": { enabled: this.config.instrumentations?.http || false, }, "@opentelemetry/instrumentation-express": { enabled: this.config.instrumentations?.express || false, }, "@opentelemetry/instrumentation-fs": { enabled: this.config.instrumentations?.fs || false, }, "@opentelemetry/instrumentation-dns": { enabled: this.config.instrumentations?.dns || false, }, "@opentelemetry/instrumentation-redis": { enabled: this.config.instrumentations?.redis || false, }, "@opentelemetry/instrumentation-mysql": { enabled: this.config.instrumentations?.mysql || false, }, "@opentelemetry/instrumentation-pg": { enabled: this.config.instrumentations?.postgres || false, }, }); return [autoInstrumentations]; } /** * Get trace exporter */ getTraceExporter() { if (!this.config.enableTracing || !this.config.exporters.traces) { return null; } const { type, endpoint } = this.config.exporters.traces; switch (type) { case "console": const { ConsoleSpanExporter, } = require("@opentelemetry/sdk-trace-base"); return new ConsoleSpanExporter(); case "jaeger": const { JaegerExporter } = require("@opentelemetry/exporter-jaeger"); return new JaegerExporter({ endpoint: endpoint || "http://localhost:14268/api/traces", }); case "otlp": const { OTLPTraceExporter, } = require("@opentelemetry/exporter-trace-otlp-http"); return new OTLPTraceExporter({ url: endpoint || "http://localhost:4318/v1/traces", }); default: logger.warn(`Unknown trace exporter type: ${type}`); return null; } } /** * Get metric readers */ getMetricReaders() { const readers = []; if (!this.config.enableMetrics || !this.config.exporters.metrics) { return readers; } const { type, endpoint, interval = 5000 } = this.config.exporters.metrics; switch (type) { case "console": const { ConsoleMetricExporter } = require("@opentelemetry/sdk-metrics"); readers.push(new PeriodicExportingMetricReader({ exporter: new ConsoleMetricExporter(), exportIntervalMillis: interval, })); break; case "prometheus": const { PrometheusExporter, } = require("@opentelemetry/exporter-prometheus"); readers.push(new PrometheusExporter({ port: 9090, endpoint: "/metrics", })); break; case "otlp": const { OTLPMetricExporter, } = require("@opentelemetry/exporter-metrics-otlp-http"); readers.push(new PeriodicExportingMetricReader({ exporter: new OTLPMetricExporter({ url: endpoint || "http://localhost:4318/v1/metrics", }), exportIntervalMillis: interval, })); break; default: logger.warn(`Unknown metric exporter type: ${type}`); } return readers; } /** * Generate service instance ID */ generateInstanceId() { const hostname = process.env.HOSTNAME || "localhost"; const pid = process.pid; const timestamp = Date.now(); return `${hostname}-${pid}-${timestamp}`; } /** * Get current configuration */ getConfig() { return { ...this.config }; } /** * Update configuration */ updateConfig(config) { this.config = { ...this.config, ...config }; } /** * Check if telemetry is initialized */ isActive() { return this.isInitialized; } } // Default instance export const telemetry = new TelemetryManager(); // Helper functions export async function initializeTelemetry(config) { if (config) { telemetry.updateConfig(config); } await telemetry.initialize(); } export async function shutdownTelemetry() { await telemetry.shutdown(); } export function getTelemetryConfig() { return telemetry.getConfig(); } export function isTelemetryActive() { return telemetry.isActive(); } //# sourceMappingURL=otel.js.map