@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
JavaScript
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