mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
Summary
Migrates the HyperDX API and related services from Winston to Pino for standardized,
faster, and more structured logging with improved OpenTelemetry integration.
Changes
Core Migration
- Replaced Winston with Pino across all logging infrastructure
- Upgraded @hyperdx/node-opentelemetry from v0.8.2 to v0.9.0 to support Pino
transport
- Removed deprecated dependencies:
- winston and express-winston
- @opentelemetry/host-metrics and @opentelemetry/sdk-metrics (consolidated into
newer OTel SDK)
- Added new dependencies:
- pino and pino-http for core logging
- pino-pretty for development console output
Logger Configuration (packages/api/src/utils/logger.ts)
Production:
- Outputs stringified JSON to stdout via pino/file transport
- Maintains HyperDX transport integration when API key is configured
- Includes full OpenTelemetry trace context (trace_id, span_id, trace_flags)
<img width="830" height="184" alt="Screenshot 2025-10-14 at 4 31 36 PM" src="https://github.com/user-attachments/assets/82e60919-5c4d-4688-a6f5-d54632aef749" />
Development:
- Uses pino-pretty for human-readable, colorized console output
- Hides verbose fields from console: pid, hostname, trace_id, span_id, trace_flags
- HTTP request/response objects excluded from logs via custom serializers
<img width="825" height="350" alt="image" src="https://github.com/user-attachments/assets/64b293d8-bc95-4715-931a-dbf73483d247" />
HTTP Logging:
- Replaced express-winston with pino-http
- Custom log levels based on HTTP status codes (warn for 4xx, error for 5xx+)
- Simplified log messages: HTTP {method} {url}
Error Logging Updates
Updated error logging patterns throughout the codebase to follow Pino's structured
logging conventions:
// Before (Winston)
logger.error('Error message:', error);
// After (Pino)
logger.error({ err: error }, 'Error message');
Ref: HDX-2588
This PR should also address issue: https://github.com/hyperdxio/hyperdx/issues/1035
47 lines
1.3 KiB
TypeScript
47 lines
1.3 KiB
TypeScript
import mongoose from 'mongoose';
|
|
|
|
import * as config from '@/config';
|
|
import logger from '@/utils/logger';
|
|
|
|
export type ObjectId = mongoose.Types.ObjectId;
|
|
|
|
// set flags
|
|
mongoose.set('strictQuery', false);
|
|
|
|
// Allow empty strings to be set to required fields
|
|
// https://github.com/Automattic/mongoose/issues/7150
|
|
// ex. query in logview can be empty
|
|
mongoose.Schema.Types.String.checkRequired(v => v != null);
|
|
|
|
// connection events handlers
|
|
mongoose.connection.on('connected', () => {
|
|
logger.info('Connection established to MongoDB');
|
|
});
|
|
|
|
mongoose.connection.on('disconnected', () => {
|
|
logger.info('Lost connection to MongoDB server');
|
|
});
|
|
|
|
mongoose.connection.on('error', err => {
|
|
logger.error({ err }, 'Could not connect to MongoDB');
|
|
});
|
|
|
|
mongoose.connection.on('reconnected', () => {
|
|
logger.warn('Reconnected to MongoDB');
|
|
});
|
|
|
|
mongoose.connection.on('reconnectFailed', () => {
|
|
logger.error('Failed to reconnect to MongoDB');
|
|
});
|
|
|
|
export const connectDB = async () => {
|
|
if (config.MONGO_URI == null) {
|
|
throw new Error('MONGO_URI is not set');
|
|
}
|
|
await mongoose.connect(config.MONGO_URI, {
|
|
heartbeatFrequencyMS: 10000, // retry failed heartbeats
|
|
maxPoolSize: 100, // 5 nodes -> max 1000 connections
|
|
});
|
|
};
|
|
|
|
export const mongooseConnection = mongoose.connection;
|