Skip to content

Instantly share code, notes, and snippets.

@suissa
Created July 18, 2025 14:32
Show Gist options
  • Save suissa/1bc49c59ebc18a9a0aceddc1eef5d32a to your computer and use it in GitHub Desktop.
Save suissa/1bc49c59ebc18a9a0aceddc1eef5d32a to your computer and use it in GitHub Desktop.
import { MeterProvider, PeriodicExportingMetricReader } from '@opentelemetry/sdk-metrics';
import { OTLPMetricExporter } from '@opentelemetry/exporter-metrics-otlp-websocket';
import WebSocket, { WebSocketServer } from 'ws';
const metricExporter = new OTLPMetricExporter({
url: 'ws://localhost:4318/v1/metrics',
});
const meterProvider = new MeterProvider({
readers: [new PeriodicExportingMetricReader({
exporter: metricExporter,
exportIntervalMillis: 5000,
})],
});
const meter = meterProvider.getMeter('websocket-metrics');
const activeConnections = meter.createUpDownCounter('websocket_active_connections', {
description: 'Total de conexões WebSocket abertas no momento.',
});
const connectionsOpened = meter.createCounter('websocket_connections_opened_total', {
description: 'Total acumulado de conexões WebSocket abertas.',
});
const connectionsClosed = meter.createCounter('websocket_connections_closed_total', {
description: 'Total acumulado de conexões WebSocket fechadas.',
});
const connectionDuration = meter.createHistogram('websocket_connection_duration_ms', {
description: 'Duração em milissegundos das conexões WebSocket.',
});
const messagesSent = meter.createCounter('websocket_messages_sent_total', {
description: 'Total acumulado de mensagens WebSocket enviadas.',
});
const messagesReceived = meter.createCounter('websocket_messages_received_total', {
description: 'Total acumulado de mensagens WebSocket recebidas.',
});
const messageSize = meter.createHistogram('websocket_message_size_bytes', {
description: 'Tamanho das mensagens WebSocket em bytes.',
});
const messageLatency = meter.createHistogram('websocket_message_latency_ms', {
description: 'Latência das mensagens (ping/pong) em ms.',
});
const messageProcessingTime = meter.createHistogram('websocket_message_processing_time_ms', {
description: 'Tempo gasto para processar cada mensagem.',
});
const connectionErrors = meter.createCounter('websocket_connection_errors_total', {
description: 'Total de erros ocorridos nas conexões WebSocket.',
});
const reconnectionsPerClient = meter.createCounter('websocket_reconnections_total', {
description: 'Número total de reconexões automáticas feitas por clientes.',
});
const messageSendFailures = meter.createCounter('websocket_message_send_failures_total', {
description: 'Falhas no envio das mensagens WebSocket.',
});
const concurrentClients = meter.createUpDownCounter('websocket_concurrent_clients', {
description: 'Número simultâneo de clientes WebSocket.',
});
const connectionRejectionRate = meter.createCounter('websocket_connection_rejections_total', {
description: 'Número total de conexões recusadas devido à sobrecarga.',
});
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', (ws: WebSocket, req) => {
const connectionStart = Date.now();
activeConnections.add(1);
concurrentClients.add(1);
connectionsOpened.add(1);
ws.on('message', async (message: WebSocket.RawData) => {
const messageStart = Date.now();
messagesReceived.add(1);
messageSize.record(Buffer.byteLength(message));
// Simulando ping/pong latency
const latencyStart = Date.now();
ws.ping();
ws.once('pong', () => {
const latency = Date.now() - latencyStart;
messageLatency.record(latency);
});
try {
// Simulando processamento
await processMessage(message);
const processingTime = Date.now() - messageStart;
messageProcessingTime.record(processingTime);
} catch (error) {
messageSendFailures.add(1);
}
});
ws.on('close', () => {
const duration = Date.now() - connectionStart;
connectionDuration.record(duration);
activeConnections.add(-1);
concurrentClients.add(-1);
connectionsClosed.add(1);
});
ws.on('error', () => {
connectionErrors.add(1);
});
});
async function processMessage(msg: WebSocket.RawData): Promise<void> {
messagesSent.add(1);
// Simulando delay no processamento
await new Promise(resolve => setTimeout(resolve, Math.random() * 200));
}
const MAX_CONNECTIONS = 500;
wss.on('headers', (_, request) => {
if (wss.clients.size >= MAX_CONNECTIONS) {
connectionRejectionRate.add(1);
request.destroy();
}
});
console.log(`🚀 Servidor WebSocket rodando na porta 8080`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment