mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
migration: migrate to Pino (logger) (#1269)
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
This commit is contained in:
parent
43e32aafc7
commit
348a4044e8
22 changed files with 484 additions and 329 deletions
6
.changeset/wet-stingrays-behave.md
Normal file
6
.changeset/wet-stingrays-behave.md
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
"@hyperdx/api": minor
|
||||
"@hyperdx/app": minor
|
||||
---
|
||||
|
||||
migration: migrate to Pino for standardized and faster logging
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
"@ai-sdk/anthropic": "^2.0.23",
|
||||
"@esm2cjs/p-queue": "^7.3.0",
|
||||
"@hyperdx/common-utils": "^0.7.0",
|
||||
"@hyperdx/node-opentelemetry": "^0.8.2",
|
||||
"@hyperdx/node-opentelemetry": "^0.9.0",
|
||||
"@hyperdx/passport-local-mongoose": "^9.0.1",
|
||||
"@opentelemetry/api": "^1.8.0",
|
||||
"@opentelemetry/host-metrics": "^0.35.5",
|
||||
|
|
@ -27,7 +27,6 @@
|
|||
"express": "^4.19.2",
|
||||
"express-rate-limit": "^6.7.1",
|
||||
"express-session": "^1.17.3",
|
||||
"express-winston": "^4.2.0",
|
||||
"handlebars": "^4.7.8",
|
||||
"http-graceful-shutdown": "^3.1.13",
|
||||
"http-proxy-middleware": "^3.0.5",
|
||||
|
|
@ -40,12 +39,13 @@
|
|||
"on-headers": "^1.1.0",
|
||||
"passport": "^0.6.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"pino": "^10.0.0",
|
||||
"pino-http": "^11.0.0",
|
||||
"promised-handlebars": "^2.0.1",
|
||||
"protobufjs": "^7.5.2",
|
||||
"semver": "^7.5.2",
|
||||
"serialize-error": "^8.1.0",
|
||||
"uuid": "^8.3.2",
|
||||
"winston": "^3.10.0",
|
||||
"zod": "3.25",
|
||||
"zod-express-middleware": "^1.4.0"
|
||||
},
|
||||
|
|
@ -67,6 +67,7 @@
|
|||
"jest": "^28.1.3",
|
||||
"migrate-mongo": "^11.0.0",
|
||||
"nodemon": "^2.0.20",
|
||||
"pino-pretty": "^13.1.1",
|
||||
"rimraf": "^4.4.1",
|
||||
"supertest": "^6.3.1",
|
||||
"swagger-jsdoc": "^6.2.8",
|
||||
|
|
|
|||
|
|
@ -63,10 +63,7 @@ const healthCheck = async () => {
|
|||
const client = await getClickhouseClient();
|
||||
const result = await client.ping();
|
||||
if (!result.success) {
|
||||
logger.error({
|
||||
message: 'ClickHouse health check failed',
|
||||
error: result.error,
|
||||
});
|
||||
logger.error({ error: result.error }, 'ClickHouse health check failed');
|
||||
throw result.error;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ if (config.IS_DEV) {
|
|||
const server = new Server();
|
||||
|
||||
process.on('uncaughtException', (err: Error) => {
|
||||
logger.error(serializeError(err));
|
||||
logger.error({ err: serializeError(err) }, 'Uncaught exception');
|
||||
|
||||
// FIXME: disable server restart until
|
||||
// we make sure all expected exceptions are handled properly
|
||||
|
|
@ -32,7 +32,9 @@ process.on('uncaughtException', (err: Error) => {
|
|||
|
||||
process.on('unhandledRejection', (err: any) => {
|
||||
// TODO: do we want to throw here ?
|
||||
logger.error(serializeError(err));
|
||||
logger.error({ err: serializeError(err) }, 'Unhandled rejection');
|
||||
});
|
||||
|
||||
server.start().catch(e => logger.error(serializeError(e)));
|
||||
server
|
||||
.start()
|
||||
.catch(e => logger.error({ err: serializeError(e) }, 'Server start failed'));
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ export function redirectToDashboard(req: Request, res: Response) {
|
|||
return res.redirect(`${config.FRONTEND_URL}/search`);
|
||||
} else {
|
||||
logger.error(
|
||||
`Password login for user failed, user or team not found ${req?.user?._id}`,
|
||||
{ userId: req?.user?._id },
|
||||
'Password login for user failed, user or team not found',
|
||||
);
|
||||
res.redirect(`${config.FRONTEND_URL}/login?err=unknown`);
|
||||
}
|
||||
|
|
@ -43,7 +44,7 @@ export function handleAuthError(
|
|||
res: Response,
|
||||
next: NextFunction,
|
||||
) {
|
||||
logger.debug({ message: 'Auth error', authErr: serializeError(err) });
|
||||
logger.debug({ authErr: serializeError(err) }, 'Auth error');
|
||||
if (res.headersSent) {
|
||||
return next(err);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@ mongoose.connection.on('disconnected', () => {
|
|||
logger.info('Lost connection to MongoDB server');
|
||||
});
|
||||
|
||||
mongoose.connection.on('error', () => {
|
||||
logger.error('Could not connect to MongoDB');
|
||||
mongoose.connection.on('error', err => {
|
||||
logger.error({ err }, 'Could not connect to MongoDB');
|
||||
});
|
||||
|
||||
mongoose.connection.on('reconnected', () => {
|
||||
logger.error('Reconnected to MongoDB');
|
||||
logger.warn('Reconnected to MongoDB');
|
||||
});
|
||||
|
||||
mongoose.connection.on('reconnectFailed', () => {
|
||||
|
|
|
|||
|
|
@ -303,7 +303,7 @@ export class OpampController {
|
|||
|
||||
// Decode the AgentToServer message
|
||||
const agentToServer = decodeAgentToServer(req.body);
|
||||
logger.debug('agentToServer', agentToServer);
|
||||
logger.debug({ agentToServer }, 'agentToServer');
|
||||
logger.debug(
|
||||
// @ts-ignore
|
||||
`Received message from agent: ${agentToServer.instanceUid?.toString(
|
||||
|
|
@ -353,7 +353,7 @@ export class OpampController {
|
|||
res.setHeader('Content-Type', 'application/x-protobuf');
|
||||
res.send(encodedResponse);
|
||||
} catch (error) {
|
||||
logger.error('Error handling OpAMP message:', error);
|
||||
logger.error({ err: error }, 'Error handling OpAMP message');
|
||||
res.status(500).send('Internal Server Error');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ export class AgentService {
|
|||
|
||||
return agent;
|
||||
} catch (error) {
|
||||
logger.error('Error processing agent status:', error);
|
||||
logger.error({ err: error }, 'Error processing agent status');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ try {
|
|||
root = protobuf.loadSync(PROTO_PATH);
|
||||
logger.debug('OpAMP proto definition loaded successfully');
|
||||
} catch (error) {
|
||||
logger.error('Failed to load OpAMP proto definition:', error);
|
||||
logger.error({ err: error }, 'Failed to load OpAMP proto definition');
|
||||
throw error;
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ export function decodeAgentToServer(data: Buffer): protobuf.Message {
|
|||
try {
|
||||
return AgentToServer.decode(data);
|
||||
} catch (error) {
|
||||
logger.error('Failed to decode AgentToServer message:', error);
|
||||
logger.error({ err: error }, 'Failed to decode AgentToServer message');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -68,7 +68,7 @@ export function encodeServerToAgent(message: any): Buffer {
|
|||
// Encode the message
|
||||
return Buffer.from(ServerToAgent.encode(serverToAgent).finish());
|
||||
} catch (error) {
|
||||
logger.error('Failed to encode ServerToAgent message:', error);
|
||||
logger.error({ err: error }, 'Failed to encode ServerToAgent message');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -105,7 +105,7 @@ export function createRemoteConfig(
|
|||
configHash: configHash,
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error('Failed to create remote config message:', error);
|
||||
logger.error({ err: error }, 'Failed to create remote config message');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
@ -130,7 +130,7 @@ function calculateConfigHash(configFiles: Map<string, Buffer>): Buffer {
|
|||
|
||||
return hash.digest();
|
||||
} catch (error) {
|
||||
logger.error('Failed to calculate config hash:', error);
|
||||
logger.error({ err: error }, 'Failed to calculate config hash');
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ router.post(
|
|||
const source = await getSource(teamId.toString(), sourceId);
|
||||
|
||||
if (source == null) {
|
||||
logger.error({ message: 'invalid source id', sourceId, teamId });
|
||||
logger.error({ sourceId, teamId }, 'invalid source id');
|
||||
return res.status(400).json({
|
||||
error: 'Invalid source',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -90,7 +90,10 @@ router.post(
|
|||
password,
|
||||
async (err: Error, user: any) => {
|
||||
if (err) {
|
||||
logger.error(serializeError(err));
|
||||
logger.error(
|
||||
{ err: serializeError(err) },
|
||||
'User registration error',
|
||||
);
|
||||
return res.status(400).json({ error: 'invalid' });
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +110,8 @@ router.post(
|
|||
await setupTeamDefaults(team._id.toString());
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
`Failed to setup team defaults: ${serializeError(error)}`,
|
||||
{ err: serializeError(error) },
|
||||
'Failed to setup team defaults',
|
||||
);
|
||||
// Continue with registration even if setup defaults fails
|
||||
}
|
||||
|
|
@ -118,7 +122,8 @@ router.post(
|
|||
}
|
||||
|
||||
logger.error(
|
||||
`Password login for user failed, user or team not found ${req?.user?._id}`,
|
||||
{ userId: req?.user?._id },
|
||||
'Password login for user failed, user or team not found',
|
||||
);
|
||||
return res.status(400).json({ error: 'invalid' });
|
||||
});
|
||||
|
|
@ -167,7 +172,7 @@ router.post('/team/setup/:token', async (req, res, next) => {
|
|||
password, // TODO: validate password
|
||||
async (err: Error, user: any) => {
|
||||
if (err) {
|
||||
logger.error(serializeError(err));
|
||||
logger.error({ err: serializeError(err) }, 'Team setup error');
|
||||
return res.redirect(
|
||||
`${config.FRONTEND_URL}/join-team?token=${token}&err=500`,
|
||||
);
|
||||
|
|
@ -196,7 +201,7 @@ router.get('/ext/silence-alert/:token', async (req, res) => {
|
|||
await silenceAlertByToken(token);
|
||||
} catch (e) {
|
||||
isError = true;
|
||||
logger.error(e);
|
||||
logger.error({ err: e }, 'Failed to silence alert');
|
||||
}
|
||||
|
||||
// TODO: Create a template for utility pages
|
||||
|
|
|
|||
|
|
@ -31,7 +31,10 @@ export default class Server {
|
|||
|
||||
if (mongoCloseResult.status === 'rejected') {
|
||||
hasError = true;
|
||||
logger.error(serializeError(mongoCloseResult.reason));
|
||||
logger.error(
|
||||
{ err: serializeError(mongoCloseResult.reason) },
|
||||
'MongoDB client close failed',
|
||||
);
|
||||
} else {
|
||||
logger.info('MongoDB client closed.');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export async function setupTeamDefaults(teamId: string) {
|
|||
// Get the team object
|
||||
const team = await getTeam(teamId);
|
||||
if (!team) {
|
||||
logger.warn(`Team not found with ID: ${teamId}`);
|
||||
logger.warn({ teamId }, 'Team not found');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ export async function setupTeamDefaults(teamId: string) {
|
|||
`Created default connection: ${connectionConfig.name} (${newConnection._id})`,
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(`Failed to create connection: ${error}`);
|
||||
logger.error({ err: error }, 'Failed to create connection');
|
||||
}
|
||||
}
|
||||
} else if (parsedDefaultConnections) {
|
||||
|
|
@ -136,7 +136,7 @@ export async function setupTeamDefaults(teamId: string) {
|
|||
c => c.name === connectionId,
|
||||
);
|
||||
if (!connection) {
|
||||
logger.warn(`Connection not found with name: ${connectionId}`);
|
||||
logger.warn({ connectionId }, 'Connection not found with name');
|
||||
continue;
|
||||
}
|
||||
connectionId = connection._id.toString();
|
||||
|
|
@ -166,7 +166,7 @@ export async function setupTeamDefaults(teamId: string) {
|
|||
// Store the created source for the second pass
|
||||
createdSources[sourceConfig.name] = newSource;
|
||||
} catch (error) {
|
||||
logger.error(`Failed to create source: ${error}`);
|
||||
logger.error({ err: error }, 'Failed to create source');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -227,7 +227,7 @@ export async function setupTeamDefaults(teamId: string) {
|
|||
);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Failed to update source references: ${error}`);
|
||||
logger.error({ err: error }, 'Failed to update source references');
|
||||
}
|
||||
}
|
||||
} else if (parsedDefaultSources) {
|
||||
|
|
|
|||
|
|
@ -92,11 +92,13 @@ const fireChannelEvent = async ({
|
|||
}
|
||||
|
||||
if ((alert.silenced?.until?.getTime() ?? 0) > Date.now()) {
|
||||
logger.info({
|
||||
message: 'Skipped firing alert due to silence',
|
||||
alertId: alert.id,
|
||||
silenced: alert.silenced,
|
||||
});
|
||||
logger.info(
|
||||
{
|
||||
alertId: alert.id,
|
||||
silenced: alert.silenced,
|
||||
},
|
||||
'Skipped firing alert due to silence',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -157,14 +159,16 @@ export const processAlert = async (
|
|||
previous &&
|
||||
fns.getTime(previous.createdAt) === fns.getTime(nowInMinsRoundDown)
|
||||
) {
|
||||
logger.info({
|
||||
message: `Skipped to check alert since the time diff is still less than 1 window size`,
|
||||
windowSizeInMins,
|
||||
nowInMinsRoundDown,
|
||||
previous,
|
||||
now,
|
||||
alertId: alert.id,
|
||||
});
|
||||
logger.info(
|
||||
{
|
||||
windowSizeInMins,
|
||||
nowInMinsRoundDown,
|
||||
previous,
|
||||
now,
|
||||
alertId: alert.id,
|
||||
},
|
||||
`Skipped to check alert since the time diff is still less than 1 window size`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
const checkStartTime = previous
|
||||
|
|
@ -218,20 +222,24 @@ export const processAlert = async (
|
|||
};
|
||||
}
|
||||
} else {
|
||||
logger.error({
|
||||
message: `Unsupported alert source: ${alert.source}`,
|
||||
alertId: alert.id,
|
||||
});
|
||||
logger.error(
|
||||
{
|
||||
alertId: alert.id,
|
||||
},
|
||||
`Unsupported alert source: ${alert.source}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch data
|
||||
if (chartConfig == null) {
|
||||
logger.error({
|
||||
message: 'Failed to build chart config',
|
||||
chartConfig,
|
||||
alertId: alert.id,
|
||||
});
|
||||
logger.error(
|
||||
{
|
||||
chartConfig,
|
||||
alertId: alert.id,
|
||||
},
|
||||
'Failed to build chart config',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -241,13 +249,15 @@ export const processAlert = async (
|
|||
metadata,
|
||||
});
|
||||
|
||||
logger.info({
|
||||
message: `Received alert metric [${alert.source} source]`,
|
||||
alertId: alert.id,
|
||||
checksData,
|
||||
checkStartTime,
|
||||
checkEndTime,
|
||||
});
|
||||
logger.info(
|
||||
{
|
||||
alertId: alert.id,
|
||||
checksData,
|
||||
checkStartTime,
|
||||
checkEndTime,
|
||||
},
|
||||
`Received alert metric [${alert.source} source]`,
|
||||
);
|
||||
|
||||
// TODO: support INSUFFICIENT_DATA state
|
||||
const history: IAlertHistory = {
|
||||
|
|
@ -276,19 +286,23 @@ export const processAlert = async (
|
|||
);
|
||||
|
||||
if (timestampColumnName == null) {
|
||||
logger.error({
|
||||
message: 'Failed to find timestamp column',
|
||||
meta,
|
||||
alertId: alert.id,
|
||||
});
|
||||
logger.error(
|
||||
{
|
||||
meta,
|
||||
alertId: alert.id,
|
||||
},
|
||||
'Failed to find timestamp column',
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (valueColumnNames.size === 0) {
|
||||
logger.error({
|
||||
message: 'Failed to find value column',
|
||||
meta,
|
||||
alertId: alert.id,
|
||||
});
|
||||
logger.error(
|
||||
{
|
||||
meta,
|
||||
alertId: alert.id,
|
||||
},
|
||||
'Failed to find value column',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,11 +34,13 @@ const main = async (argv: TaskArgs) => {
|
|||
`Task [${task.name()}] finished in ${(performance.now() - t0).toFixed(2)} ms`,
|
||||
);
|
||||
} catch (e: unknown) {
|
||||
logger.error({
|
||||
message: `Task [${task.name()}] failed: ${serializeError(e)}`,
|
||||
cause: e,
|
||||
task,
|
||||
});
|
||||
logger.error(
|
||||
{
|
||||
cause: e,
|
||||
task,
|
||||
},
|
||||
`Task [${task.name()}] failed: ${serializeError(e)}`,
|
||||
);
|
||||
} finally {
|
||||
await task.asyncDispose();
|
||||
span.end();
|
||||
|
|
@ -70,19 +72,19 @@ if (!RUN_SCHEDULED_TASKS_EXTERNALLY) {
|
|||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
logger.error(serializeError(err));
|
||||
logger.error({ err: serializeError(err) }, 'Task execution failed');
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
process.on('uncaughtException', (err: Error) => {
|
||||
console.log(err);
|
||||
logger.error(serializeError(err));
|
||||
logger.error({ err: serializeError(err) }, 'Uncaught exception');
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
process.on('unhandledRejection', (err: any) => {
|
||||
console.log(err);
|
||||
logger.error(serializeError(err));
|
||||
logger.error({ err: serializeError(err) }, 'Unhandled rejection');
|
||||
process.exit(1);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -102,11 +102,13 @@ export async function loadProvider(
|
|||
try {
|
||||
return providerFn();
|
||||
} catch (err) {
|
||||
logger.error({
|
||||
message: `error creating instance of ${providerName} provider; using default`,
|
||||
cause: err,
|
||||
providerName,
|
||||
});
|
||||
logger.error(
|
||||
{
|
||||
cause: err,
|
||||
providerName,
|
||||
},
|
||||
`error creating instance of ${providerName} provider; using default`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,15 +106,17 @@ function validateWebhookUrl(
|
|||
// check that hostname ends in "slack.com"
|
||||
if (!isValidSlackUrl(webhook.url)) {
|
||||
const message = `Slack Webhook URL ${webhook.url} does not have hostname that ends in 'slack.com'`;
|
||||
logger.warn({
|
||||
webhook: {
|
||||
id: webhook._id.toString(),
|
||||
name: webhook.name,
|
||||
url: webhook.url,
|
||||
body: webhook.body,
|
||||
logger.warn(
|
||||
{
|
||||
webhook: {
|
||||
id: webhook._id.toString(),
|
||||
name: webhook.name,
|
||||
url: webhook.url,
|
||||
body: webhook.body,
|
||||
},
|
||||
},
|
||||
message,
|
||||
});
|
||||
);
|
||||
throw new Error(`SSRF AllowedDomainError: ${message}`);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -124,15 +126,17 @@ function validateWebhookUrl(
|
|||
const message = `Webhook attempting to query blacklisted route ${blacklistedWebhookHosts.get(
|
||||
url.host,
|
||||
)}`;
|
||||
logger.warn({
|
||||
webhook: {
|
||||
id: webhook._id.toString(),
|
||||
name: webhook.name,
|
||||
url: webhook.url,
|
||||
body: webhook.body,
|
||||
logger.warn(
|
||||
{
|
||||
webhook: {
|
||||
id: webhook._id.toString(),
|
||||
name: webhook.name,
|
||||
url: webhook.url,
|
||||
body: webhook.body,
|
||||
},
|
||||
},
|
||||
message,
|
||||
});
|
||||
);
|
||||
throw new Error(`SSRF AllowedDomainError: ${message}`);
|
||||
}
|
||||
}
|
||||
|
|
@ -200,10 +204,12 @@ export const handleSendGenericWebhook = async (
|
|||
title: escapeJsonString(message.title),
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error({
|
||||
message: 'Failed to compile generic webhook body',
|
||||
error: serializeError(e),
|
||||
});
|
||||
logger.error(
|
||||
{
|
||||
error: serializeError(e),
|
||||
},
|
||||
'Failed to compile generic webhook body',
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -220,10 +226,12 @@ export const handleSendGenericWebhook = async (
|
|||
throw new Error(errorText);
|
||||
}
|
||||
} catch (e) {
|
||||
logger.error({
|
||||
message: 'Failed to send generic webhook message',
|
||||
error: serializeError(e),
|
||||
});
|
||||
logger.error(
|
||||
{
|
||||
error: serializeError(e),
|
||||
},
|
||||
'Failed to send generic webhook message',
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -347,15 +355,18 @@ const getPopulatedChannel = (
|
|||
findWebhookByName(channelIdOrNamePrefix, teamWebhooksById);
|
||||
|
||||
if (!webhook) {
|
||||
logger.error('webhook not found', {
|
||||
webhookId: channelIdOrNamePrefix,
|
||||
});
|
||||
logger.error(
|
||||
{
|
||||
webhookId: channelIdOrNamePrefix,
|
||||
},
|
||||
'webhook not found',
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
return { type: 'webhook', channel: webhook };
|
||||
}
|
||||
default: {
|
||||
logger.error(`unsupported alert channel type: ${channelType}`);
|
||||
logger.error({ channelType }, 'Unsupported alert channel type');
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
|
@ -505,12 +516,14 @@ export const renderAlertTemplate = async ({
|
|||
2500,
|
||||
);
|
||||
} catch (e) {
|
||||
logger.error({
|
||||
message: 'Failed to fetch sample logs',
|
||||
savedSearchId: savedSearch.id,
|
||||
chartConfig,
|
||||
error: serializeError(e),
|
||||
});
|
||||
logger.error(
|
||||
{
|
||||
savedSearchId: savedSearch.id,
|
||||
chartConfig,
|
||||
error: serializeError(e),
|
||||
},
|
||||
'Failed to fetch sample logs',
|
||||
);
|
||||
}
|
||||
|
||||
rawTemplateBody = `${group ? `Group: "${group}"` : ''}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { MetricsDataType, SourceKind } from '@hyperdx/common-utils/dist/types';
|
|||
import * as HyperDX from '@hyperdx/node-opentelemetry';
|
||||
import ms from 'ms';
|
||||
import os from 'os';
|
||||
import winston from 'winston';
|
||||
import pino from 'pino';
|
||||
|
||||
import * as config from '@/config';
|
||||
import Connection from '@/models/connection';
|
||||
|
|
@ -12,19 +12,19 @@ import { Source, SourceDocument } from '@/models/source';
|
|||
import Team from '@/models/team';
|
||||
import User from '@/models/user';
|
||||
|
||||
const logger = winston.createLogger({
|
||||
const logger = pino({
|
||||
level: 'info',
|
||||
format: winston.format.json(),
|
||||
transports: [
|
||||
HyperDX.getWinstonTransport('info', {
|
||||
headers: {
|
||||
Authorization: '3f26ffad-14cf-4fb7-9dc9-e64fa0b84ee0', // hyperdx usage stats service api key
|
||||
},
|
||||
baseUrl: 'https://in-otel.hyperdx.io/v1/logs',
|
||||
maxLevel: 'info',
|
||||
service: 'hyperdx-oss-usage-stats',
|
||||
}),
|
||||
],
|
||||
transport: {
|
||||
targets: [
|
||||
HyperDX.getPinoTransport('info', {
|
||||
headers: {
|
||||
Authorization: '3f26ffad-14cf-4fb7-9dc9-e64fa0b84ee0', // hyperdx usage stats service api key
|
||||
},
|
||||
baseUrl: 'https://in-otel.hyperdx.io/v1/logs',
|
||||
service: 'hyperdx-oss-usage-stats',
|
||||
}),
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
function extractTableNames(source: SourceDocument): string[] {
|
||||
|
|
@ -128,37 +128,39 @@ async function getUsageStats() {
|
|||
getClickhouseTableSize(),
|
||||
]);
|
||||
const clusterId = team[0]?._id.toString();
|
||||
logger.info({
|
||||
message: 'track-hyperdx-oss-usage-stats',
|
||||
clusterId,
|
||||
version: config.CODE_VERSION,
|
||||
userCounts,
|
||||
os: {
|
||||
arch: os.arch(),
|
||||
freemem: os.freemem(),
|
||||
uptime: os.uptime(),
|
||||
logger.info(
|
||||
{
|
||||
clusterId,
|
||||
version: config.CODE_VERSION,
|
||||
userCounts,
|
||||
os: {
|
||||
arch: os.arch(),
|
||||
freemem: os.freemem(),
|
||||
uptime: os.uptime(),
|
||||
},
|
||||
chStats: {
|
||||
tables: chTables.reduce(
|
||||
(acc, curr) => ({
|
||||
...acc,
|
||||
[curr.table]: {
|
||||
avgDaySize: parseInt(curr.avgDaySize),
|
||||
days: parseInt(curr.days),
|
||||
lastModified: new Date(curr.latestModification).getTime(),
|
||||
maxTime: new Date(curr.max_time).getTime(),
|
||||
minTime: new Date(curr.min_time).getTime(),
|
||||
rows: parseInt(curr.rows),
|
||||
size: parseInt(curr.size),
|
||||
},
|
||||
}),
|
||||
{},
|
||||
),
|
||||
rows: chTables.reduce((acc, curr) => acc + parseInt(curr.rows), 0),
|
||||
size: chTables.reduce((acc, curr) => acc + parseInt(curr.size), 0),
|
||||
},
|
||||
timestamp: nowInMs,
|
||||
},
|
||||
chStats: {
|
||||
tables: chTables.reduce(
|
||||
(acc, curr) => ({
|
||||
...acc,
|
||||
[curr.table]: {
|
||||
avgDaySize: parseInt(curr.avgDaySize),
|
||||
days: parseInt(curr.days),
|
||||
lastModified: new Date(curr.latestModification).getTime(),
|
||||
maxTime: new Date(curr.max_time).getTime(),
|
||||
minTime: new Date(curr.min_time).getTime(),
|
||||
rows: parseInt(curr.rows),
|
||||
size: parseInt(curr.size),
|
||||
},
|
||||
}),
|
||||
{},
|
||||
),
|
||||
rows: chTables.reduce((acc, curr) => acc + parseInt(curr.rows), 0),
|
||||
size: chTables.reduce((acc, curr) => acc + parseInt(curr.size), 0),
|
||||
},
|
||||
timestamp: nowInMs,
|
||||
});
|
||||
'track-hyperdx-oss-usage-stats',
|
||||
);
|
||||
} catch (err) {
|
||||
// ignore
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,57 +1,100 @@
|
|||
import { getWinstonTransport } from '@hyperdx/node-opentelemetry';
|
||||
import expressWinston from 'express-winston';
|
||||
import winston, { addColors } from 'winston';
|
||||
|
||||
import {
|
||||
APP_TYPE,
|
||||
HYPERDX_API_KEY,
|
||||
HYPERDX_LOG_LEVEL,
|
||||
IS_PROD,
|
||||
} from '@/config';
|
||||
getPinoMixinFunction,
|
||||
getPinoTransport,
|
||||
} from '@hyperdx/node-opentelemetry';
|
||||
import type { Request, Response } from 'express';
|
||||
import pino from 'pino';
|
||||
import pinoHttp from 'pino-http';
|
||||
|
||||
// LOCAL DEV ONLY
|
||||
addColors({
|
||||
error: 'bold red',
|
||||
warn: 'bold yellow',
|
||||
info: 'white',
|
||||
http: 'gray',
|
||||
verbose: 'bold magenta',
|
||||
debug: 'green',
|
||||
silly: 'cyan',
|
||||
});
|
||||
import * as config from '@/config';
|
||||
|
||||
const MAX_LEVEL = HYPERDX_LOG_LEVEL ?? 'debug';
|
||||
const DEFAULT_FORMAT = winston.format.combine(
|
||||
winston.format.errors({ stack: true }),
|
||||
winston.format.json(),
|
||||
);
|
||||
const MAX_LEVEL = config.HYPERDX_LOG_LEVEL ?? 'debug';
|
||||
|
||||
const hyperdxTransport = HYPERDX_API_KEY
|
||||
? getWinstonTransport(MAX_LEVEL, {
|
||||
bufferSize: APP_TYPE === 'scheduled-task' ? 1 : 100,
|
||||
const hyperdxTransport = config.HYPERDX_API_KEY
|
||||
? getPinoTransport(MAX_LEVEL, {
|
||||
detectResources: true,
|
||||
})
|
||||
: null;
|
||||
|
||||
export const expressLogger = expressWinston.logger({
|
||||
// Configure transport based on environment and whether HyperDX is enabled
|
||||
const getTransport = () => {
|
||||
const targets: any[] = [];
|
||||
|
||||
// Add HyperDX transport if API key is configured
|
||||
if (hyperdxTransport) {
|
||||
targets.push(hyperdxTransport);
|
||||
}
|
||||
|
||||
if (config.IS_DEV || config.IS_CI) {
|
||||
// In development, use pino-pretty for nice console output
|
||||
targets.push({
|
||||
target: 'pino-pretty',
|
||||
level: MAX_LEVEL,
|
||||
options: {
|
||||
colorize: true,
|
||||
translateTime: 'SYS:standard',
|
||||
ignore: 'pid,hostname,trace_id,span_id,trace_flags',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
targets.push({
|
||||
target: 'pino/file',
|
||||
level: MAX_LEVEL,
|
||||
options: { destination: 1 }, // this writes to STDOUT
|
||||
});
|
||||
}
|
||||
|
||||
// If only one target, return it directly; otherwise return multi-transport
|
||||
if (targets.length === 0) {
|
||||
return undefined;
|
||||
} else if (targets.length === 1) {
|
||||
return targets[0];
|
||||
} else {
|
||||
return { targets };
|
||||
}
|
||||
};
|
||||
|
||||
const logger = pino({
|
||||
level: MAX_LEVEL,
|
||||
format: DEFAULT_FORMAT,
|
||||
msg: IS_PROD
|
||||
? undefined
|
||||
: 'HTTP {{res.statusCode}} {{req.method}} {{req.url}} {{res.responseTime}}ms',
|
||||
transports: [
|
||||
new winston.transports.Console(),
|
||||
...(hyperdxTransport ? [hyperdxTransport] : []),
|
||||
],
|
||||
meta: IS_PROD,
|
||||
transport: getTransport(),
|
||||
mixin: getPinoMixinFunction,
|
||||
});
|
||||
|
||||
const logger = winston.createLogger({
|
||||
level: MAX_LEVEL,
|
||||
format: DEFAULT_FORMAT,
|
||||
transports: [
|
||||
new winston.transports.Console(),
|
||||
...(hyperdxTransport ? [hyperdxTransport] : []),
|
||||
],
|
||||
export const expressLogger = pinoHttp({
|
||||
logger,
|
||||
customLogLevel: (_req, res, err) => {
|
||||
if (res.statusCode >= 400 && res.statusCode < 500) {
|
||||
return 'warn';
|
||||
} else if (res.statusCode >= 500 || err) {
|
||||
return 'error';
|
||||
}
|
||||
return 'info';
|
||||
},
|
||||
customSuccessMessage: (req: Request, res: Response) => {
|
||||
return `HTTP ${req.method} ${req.originalUrl}`;
|
||||
},
|
||||
customErrorMessage: (req: Request, res: Response, err) => {
|
||||
return `HTTP ${req.method} ${req.originalUrl}`;
|
||||
},
|
||||
customProps: (req: Request, res: Response) => {
|
||||
const user = req.user;
|
||||
if (user) {
|
||||
return {
|
||||
userId: user._id?.toString(),
|
||||
userEmail: user.email,
|
||||
};
|
||||
}
|
||||
return {};
|
||||
},
|
||||
// Only disable req/res serializers in development/CI
|
||||
...(config.IS_DEV || config.IS_CI
|
||||
? {
|
||||
serializers: {
|
||||
req: () => undefined,
|
||||
res: () => undefined,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
|
||||
export default logger;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ passport.use(
|
|||
}
|
||||
return done(null, user, error);
|
||||
} catch (err) {
|
||||
logger.error(`Login for "${username}" failed, error: ${err}"`);
|
||||
logger.error({ err, username }, 'Login failed with error');
|
||||
return done(err);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
"@hookform/resolvers": "^3.9.0",
|
||||
"@hyperdx/browser": "^0.21.1",
|
||||
"@hyperdx/common-utils": "^0.7.0",
|
||||
"@hyperdx/node-opentelemetry": "^0.8.2",
|
||||
"@hyperdx/node-opentelemetry": "^0.9.0",
|
||||
"@lezer/highlight": "^1.2.0",
|
||||
"@mantine/core": "7.9.2",
|
||||
"@mantine/dates": "^7.11.2",
|
||||
|
|
|
|||
306
yarn.lock
306
yarn.lock
|
|
@ -3402,17 +3402,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@dabh/diagnostics@npm:^2.0.2":
|
||||
version: 2.0.3
|
||||
resolution: "@dabh/diagnostics@npm:2.0.3"
|
||||
dependencies:
|
||||
colorspace: "npm:1.1.x"
|
||||
enabled: "npm:2.0.x"
|
||||
kuler: "npm:^2.0.0"
|
||||
checksum: 10c0/a5133df8492802465ed01f2f0a5784585241a1030c362d54a602ed1839816d6c93d71dde05cf2ddb4fd0796238c19774406bd62fa2564b637907b495f52425fe
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@discoveryjs/json-ext@npm:^0.5.3":
|
||||
version: 0.5.7
|
||||
resolution: "@discoveryjs/json-ext@npm:0.5.7"
|
||||
|
|
@ -4496,7 +4485,7 @@ __metadata:
|
|||
"@ai-sdk/anthropic": "npm:^2.0.23"
|
||||
"@esm2cjs/p-queue": "npm:^7.3.0"
|
||||
"@hyperdx/common-utils": "npm:^0.7.0"
|
||||
"@hyperdx/node-opentelemetry": "npm:^0.8.2"
|
||||
"@hyperdx/node-opentelemetry": "npm:^0.9.0"
|
||||
"@hyperdx/passport-local-mongoose": "npm:^9.0.1"
|
||||
"@opentelemetry/api": "npm:^1.8.0"
|
||||
"@opentelemetry/host-metrics": "npm:^0.35.5"
|
||||
|
|
@ -4527,7 +4516,6 @@ __metadata:
|
|||
express: "npm:^4.19.2"
|
||||
express-rate-limit: "npm:^6.7.1"
|
||||
express-session: "npm:^1.17.3"
|
||||
express-winston: "npm:^4.2.0"
|
||||
handlebars: "npm:^4.7.8"
|
||||
http-graceful-shutdown: "npm:^3.1.13"
|
||||
http-proxy-middleware: "npm:^3.0.5"
|
||||
|
|
@ -4543,6 +4531,9 @@ __metadata:
|
|||
on-headers: "npm:^1.1.0"
|
||||
passport: "npm:^0.6.0"
|
||||
passport-local: "npm:^1.0.0"
|
||||
pino: "npm:^10.0.0"
|
||||
pino-http: "npm:^11.0.0"
|
||||
pino-pretty: "npm:^13.1.1"
|
||||
promised-handlebars: "npm:^2.0.1"
|
||||
protobufjs: "npm:^7.5.2"
|
||||
rimraf: "npm:^4.4.1"
|
||||
|
|
@ -4557,7 +4548,6 @@ __metadata:
|
|||
tsconfig-paths: "npm:^4.2.0"
|
||||
typescript: "npm:5.9.3"
|
||||
uuid: "npm:^8.3.2"
|
||||
winston: "npm:^3.10.0"
|
||||
zod: "npm:3.25"
|
||||
zod-express-middleware: "npm:^1.4.0"
|
||||
languageName: unknown
|
||||
|
|
@ -4574,7 +4564,7 @@ __metadata:
|
|||
"@hookform/resolvers": "npm:^3.9.0"
|
||||
"@hyperdx/browser": "npm:^0.21.1"
|
||||
"@hyperdx/common-utils": "npm:^0.7.0"
|
||||
"@hyperdx/node-opentelemetry": "npm:^0.8.2"
|
||||
"@hyperdx/node-opentelemetry": "npm:^0.9.0"
|
||||
"@jedmao/location": "npm:^3.0.0"
|
||||
"@lezer/highlight": "npm:^1.2.0"
|
||||
"@mantine/core": "npm:7.9.2"
|
||||
|
|
@ -4786,9 +4776,9 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@hyperdx/node-opentelemetry@npm:^0.8.2":
|
||||
version: 0.8.2
|
||||
resolution: "@hyperdx/node-opentelemetry@npm:0.8.2"
|
||||
"@hyperdx/node-opentelemetry@npm:^0.9.0":
|
||||
version: 0.9.0
|
||||
resolution: "@hyperdx/node-opentelemetry@npm:0.9.0"
|
||||
dependencies:
|
||||
"@hyperdx/instrumentation-exception": "npm:^0.1.0"
|
||||
"@hyperdx/instrumentation-sentry-node": "npm:^0.1.0"
|
||||
|
|
@ -4796,8 +4786,11 @@ __metadata:
|
|||
"@opentelemetry/api-logs": "npm:^0.57.2"
|
||||
"@opentelemetry/auto-instrumentations-node": "npm:^0.56.1"
|
||||
"@opentelemetry/core": "npm:^1.30.1"
|
||||
"@opentelemetry/exporter-logs-otlp-grpc": "npm:^0.57.2"
|
||||
"@opentelemetry/exporter-logs-otlp-http": "npm:^0.57.2"
|
||||
"@opentelemetry/exporter-metrics-otlp-grpc": "npm:^0.57.2"
|
||||
"@opentelemetry/exporter-metrics-otlp-proto": "npm:^0.57.2"
|
||||
"@opentelemetry/exporter-trace-otlp-grpc": "npm:^0.57.2"
|
||||
"@opentelemetry/exporter-trace-otlp-proto": "npm:^0.57.2"
|
||||
"@opentelemetry/instrumentation": "npm:^0.57.2"
|
||||
"@opentelemetry/instrumentation-http": "npm:^0.57.2"
|
||||
|
|
@ -4823,7 +4816,7 @@ __metadata:
|
|||
winston-transport: "npm:^4.7.0"
|
||||
bin:
|
||||
opentelemetry-instrument: build/bin/opentelemetry-instrument.js
|
||||
checksum: 10c0/9f723d78b3f0da6fb3fab38826385384f3aeeeb4e2852609151effac336627d006522bcc74618f5384b1ec778b488d5dcf51c992d013f9310e780bc7349e0975
|
||||
checksum: 10c0/dc4101e78b1aca867377b68568a29ad2c1a12ae79ecd07486fbd152d1bc9d4b057469154cb49c7b4a8f6f690f9851d0cb497381bd7dd11ce11bca71e0f884981
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
@ -6416,7 +6409,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/exporter-logs-otlp-grpc@npm:0.57.2":
|
||||
"@opentelemetry/exporter-logs-otlp-grpc@npm:0.57.2, @opentelemetry/exporter-logs-otlp-grpc@npm:^0.57.2":
|
||||
version: 0.57.2
|
||||
resolution: "@opentelemetry/exporter-logs-otlp-grpc@npm:0.57.2"
|
||||
dependencies:
|
||||
|
|
@ -6464,7 +6457,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/exporter-metrics-otlp-grpc@npm:0.57.2":
|
||||
"@opentelemetry/exporter-metrics-otlp-grpc@npm:0.57.2, @opentelemetry/exporter-metrics-otlp-grpc@npm:^0.57.2":
|
||||
version: 0.57.2
|
||||
resolution: "@opentelemetry/exporter-metrics-otlp-grpc@npm:0.57.2"
|
||||
dependencies:
|
||||
|
|
@ -6526,7 +6519,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@opentelemetry/exporter-trace-otlp-grpc@npm:0.57.2":
|
||||
"@opentelemetry/exporter-trace-otlp-grpc@npm:0.57.2, @opentelemetry/exporter-trace-otlp-grpc@npm:^0.57.2":
|
||||
version: 0.57.2
|
||||
resolution: "@opentelemetry/exporter-trace-otlp-grpc@npm:0.57.2"
|
||||
dependencies:
|
||||
|
|
@ -12127,6 +12120,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"atomic-sleep@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "atomic-sleep@npm:1.0.0"
|
||||
checksum: 10c0/e329a6665512736a9bbb073e1761b4ec102f7926cce35037753146a9db9c8104f5044c1662e4a863576ce544fb8be27cd2be6bc8c1a40147d03f31eb1cfb6e8a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"attr-accept@npm:^2.2.4":
|
||||
version: 2.2.5
|
||||
resolution: "attr-accept@npm:2.2.5"
|
||||
|
|
@ -13486,7 +13486,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"color@npm:^3.1.3, color@npm:^3.2.1":
|
||||
"color@npm:^3.2.1":
|
||||
version: 3.2.1
|
||||
resolution: "color@npm:3.2.1"
|
||||
dependencies:
|
||||
|
|
@ -13513,7 +13513,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"colorette@npm:^2.0.10":
|
||||
"colorette@npm:^2.0.10, colorette@npm:^2.0.7":
|
||||
version: 2.0.20
|
||||
resolution: "colorette@npm:2.0.20"
|
||||
checksum: 10c0/e94116ff33b0ff56f3b83b9ace895e5bf87c2a7a47b3401b8c3f3226e050d5ef76cf4072fb3325f9dc24d1698f9b730baf4e05eeaf861d74a1883073f4c98a40
|
||||
|
|
@ -13527,16 +13527,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"colorspace@npm:1.1.x":
|
||||
version: 1.1.4
|
||||
resolution: "colorspace@npm:1.1.4"
|
||||
dependencies:
|
||||
color: "npm:^3.1.3"
|
||||
text-hex: "npm:1.0.x"
|
||||
checksum: 10c0/af5f91ff7f8e146b96e439ac20ed79b197210193bde721b47380a75b21751d90fa56390c773bb67c0aedd34ff85091883a437ab56861c779bd507d639ba7e123
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"combined-stream@npm:^1.0.8":
|
||||
version: 1.0.8
|
||||
resolution: "combined-stream@npm:1.0.8"
|
||||
|
|
@ -14271,6 +14261,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"dateformat@npm:^4.6.3":
|
||||
version: 4.6.3
|
||||
resolution: "dateformat@npm:4.6.3"
|
||||
checksum: 10c0/e2023b905e8cfe2eb8444fb558562b524807a51cdfe712570f360f873271600b5c94aebffaf11efb285e2c072264a7cf243eadb68f3eba0f8cc85fb86cd25df6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"dayjs@npm:^1.10.0":
|
||||
version: 1.11.7
|
||||
resolution: "dayjs@npm:1.11.7"
|
||||
|
|
@ -14974,13 +14971,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"enabled@npm:2.0.x":
|
||||
version: 2.0.0
|
||||
resolution: "enabled@npm:2.0.0"
|
||||
checksum: 10c0/3b2c2af9bc7f8b9e291610f2dde4a75cf6ee52a68f4dd585482fbdf9a55d65388940e024e56d40bb03e05ef6671f5f53021fa8b72a20e954d7066ec28166713f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"encodeurl@npm:~1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "encodeurl@npm:1.0.2"
|
||||
|
|
@ -16375,18 +16365,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"express-winston@npm:^4.2.0":
|
||||
version: 4.2.0
|
||||
resolution: "express-winston@npm:4.2.0"
|
||||
dependencies:
|
||||
chalk: "npm:^2.4.2"
|
||||
lodash: "npm:^4.17.21"
|
||||
peerDependencies:
|
||||
winston: ">=3.x <4"
|
||||
checksum: 10c0/8f80993e7d7696b22a12c68ffb72ea0cd3ad980d8394073fd972162cdca116b8f506974dd504987e350cddfdbf55402871762dcb9c69f2f7feaef2df6d93ef09
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"express@npm:^4.17.3, express@npm:^4.19.2":
|
||||
version: 4.19.2
|
||||
resolution: "express@npm:4.19.2"
|
||||
|
|
@ -16460,6 +16438,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-copy@npm:^3.0.2":
|
||||
version: 3.0.2
|
||||
resolution: "fast-copy@npm:3.0.2"
|
||||
checksum: 10c0/02e8b9fd03c8c024d2987760ce126456a0e17470850b51e11a1c3254eed6832e4733ded2d93316c82bc0b36aeb991ad1ff48d1ba95effe7add7c3ab8d8eb554a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3":
|
||||
version: 3.1.3
|
||||
resolution: "fast-deep-equal@npm:3.1.3"
|
||||
|
|
@ -16875,13 +16860,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fn.name@npm:1.x.x":
|
||||
version: 1.1.0
|
||||
resolution: "fn.name@npm:1.1.0"
|
||||
checksum: 10c0/8ad62aa2d4f0b2a76d09dba36cfec61c540c13a0fd72e5d94164e430f987a7ce6a743112bbeb14877c810ef500d1f73d7f56e76d029d2e3413f20d79e3460a9a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"focus-visible@npm:^5.2.0":
|
||||
version: 5.2.0
|
||||
resolution: "focus-visible@npm:5.2.0"
|
||||
|
|
@ -17973,6 +17951,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"help-me@npm:^5.0.0":
|
||||
version: 5.0.0
|
||||
resolution: "help-me@npm:5.0.0"
|
||||
checksum: 10c0/054c0e2e9ae2231c85ab5e04f75109b9d068ffcc54e58fb22079822a5ace8ff3d02c66fd45379c902ad5ab825e5d2e1451fcc2f7eab1eb49e7d488133ba4cacb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"hmac-drbg@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "hmac-drbg@npm:1.0.1"
|
||||
|
|
@ -20191,13 +20176,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"kuler@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "kuler@npm:2.0.0"
|
||||
checksum: 10c0/0a4e99d92ca373f8f74d1dc37931909c4d0d82aebc94cf2ba265771160fc12c8df34eaaac80805efbda367e2795cb1f1dd4c3d404b6b1cf38aec94035b503d2d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"ky-universal@npm:^0.10.1":
|
||||
version: 0.10.1
|
||||
resolution: "ky-universal@npm:0.10.1"
|
||||
|
|
@ -20564,7 +20542,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"logform@npm:^2.3.2, logform@npm:^2.4.0":
|
||||
"logform@npm:^2.3.2":
|
||||
version: 2.5.1
|
||||
resolution: "logform@npm:2.5.1"
|
||||
dependencies:
|
||||
|
|
@ -22925,6 +22903,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"on-exit-leak-free@npm:^2.1.0":
|
||||
version: 2.1.2
|
||||
resolution: "on-exit-leak-free@npm:2.1.2"
|
||||
checksum: 10c0/faea2e1c9d696ecee919026c32be8d6a633a7ac1240b3b87e944a380e8a11dc9c95c4a1f8fb0568de7ab8db3823e790f12bda45296b1d111e341aad3922a0570
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"on-finished@npm:2.4.1":
|
||||
version: 2.4.1
|
||||
resolution: "on-finished@npm:2.4.1"
|
||||
|
|
@ -22957,15 +22942,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"one-time@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "one-time@npm:1.0.0"
|
||||
dependencies:
|
||||
fn.name: "npm:1.x.x"
|
||||
checksum: 10c0/6e4887b331edbb954f4e915831cbec0a7b9956c36f4feb5f6de98c448ac02ff881fd8d9b55a6b1b55030af184c6b648f340a76eb211812f4ad8c9b4b8692fdaa
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"onetime@npm:^5.1.0, onetime@npm:^5.1.2":
|
||||
version: 5.1.2
|
||||
resolution: "onetime@npm:5.1.2"
|
||||
|
|
@ -23623,6 +23599,78 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pino-abstract-transport@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "pino-abstract-transport@npm:2.0.0"
|
||||
dependencies:
|
||||
split2: "npm:^4.0.0"
|
||||
checksum: 10c0/02c05b8f2ffce0d7c774c8e588f61e8b77de8ccb5f8125afd4a7325c9ea0e6af7fb78168999657712ae843e4462bb70ac550dfd6284f930ee57f17f486f25a9f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pino-http@npm:^11.0.0":
|
||||
version: 11.0.0
|
||||
resolution: "pino-http@npm:11.0.0"
|
||||
dependencies:
|
||||
get-caller-file: "npm:^2.0.5"
|
||||
pino: "npm:^10.0.0"
|
||||
pino-std-serializers: "npm:^7.0.0"
|
||||
process-warning: "npm:^5.0.0"
|
||||
checksum: 10c0/75110c7a7f1b1c4eadfbff3b87599ef9d100c20c3ffd19541f0cb37cd11285a3f221bb90d33df0772ed94a3f7d5b2007bd7365c5f5525cff2178d4deef140ee5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pino-pretty@npm:^13.1.1":
|
||||
version: 13.1.1
|
||||
resolution: "pino-pretty@npm:13.1.1"
|
||||
dependencies:
|
||||
colorette: "npm:^2.0.7"
|
||||
dateformat: "npm:^4.6.3"
|
||||
fast-copy: "npm:^3.0.2"
|
||||
fast-safe-stringify: "npm:^2.1.1"
|
||||
help-me: "npm:^5.0.0"
|
||||
joycon: "npm:^3.1.1"
|
||||
minimist: "npm:^1.2.6"
|
||||
on-exit-leak-free: "npm:^2.1.0"
|
||||
pino-abstract-transport: "npm:^2.0.0"
|
||||
pump: "npm:^3.0.0"
|
||||
secure-json-parse: "npm:^4.0.0"
|
||||
sonic-boom: "npm:^4.0.1"
|
||||
strip-json-comments: "npm:^5.0.2"
|
||||
bin:
|
||||
pino-pretty: bin.js
|
||||
checksum: 10c0/845c07afd3d73cb96ad2049cfa7fca12b8280a51e30d6db8b490857690637556bb8e7f05b2fa640b3e4a7edd9b1369110042d670fda743ef98fe3be29876c8c7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pino-std-serializers@npm:^7.0.0":
|
||||
version: 7.0.0
|
||||
resolution: "pino-std-serializers@npm:7.0.0"
|
||||
checksum: 10c0/73e694d542e8de94445a03a98396cf383306de41fd75ecc07085d57ed7a57896198508a0dec6eefad8d701044af21eb27253ccc352586a03cf0d4a0bd25b4133
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pino@npm:^10.0.0":
|
||||
version: 10.0.0
|
||||
resolution: "pino@npm:10.0.0"
|
||||
dependencies:
|
||||
atomic-sleep: "npm:^1.0.0"
|
||||
on-exit-leak-free: "npm:^2.1.0"
|
||||
pino-abstract-transport: "npm:^2.0.0"
|
||||
pino-std-serializers: "npm:^7.0.0"
|
||||
process-warning: "npm:^5.0.0"
|
||||
quick-format-unescaped: "npm:^4.0.3"
|
||||
real-require: "npm:^0.2.0"
|
||||
safe-stable-stringify: "npm:^2.3.1"
|
||||
slow-redact: "npm:^0.3.0"
|
||||
sonic-boom: "npm:^4.0.1"
|
||||
thread-stream: "npm:^3.0.0"
|
||||
bin:
|
||||
pino: bin.js
|
||||
checksum: 10c0/f95fcc51523310e9ece1822f8ef4d8e6c2b35f67eca9805fe18fdef21dfac81fa128f1ebaa3c9a11571120854391b10b3b339f2e5836f805edaf6936781c6e6f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"pirates@npm:^4.0.1, pirates@npm:^4.0.6":
|
||||
version: 4.0.6
|
||||
resolution: "pirates@npm:4.0.6"
|
||||
|
|
@ -24132,6 +24180,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"process-warning@npm:^5.0.0":
|
||||
version: 5.0.0
|
||||
resolution: "process-warning@npm:5.0.0"
|
||||
checksum: 10c0/941f48863d368ec161e0b5890ba0c6af94170078f3d6b5e915c19b36fb59edb0dc2f8e834d25e0d375a8bf368a49d490f080508842168832b93489d17843ec29
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"process@npm:^0.11.10":
|
||||
version: 0.11.10
|
||||
resolution: "process@npm:0.11.10"
|
||||
|
|
@ -24450,6 +24505,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"quick-format-unescaped@npm:^4.0.3":
|
||||
version: 4.0.4
|
||||
resolution: "quick-format-unescaped@npm:4.0.4"
|
||||
checksum: 10c0/fe5acc6f775b172ca5b4373df26f7e4fd347975578199e7d74b2ae4077f0af05baa27d231de1e80e8f72d88275ccc6028568a7a8c9ee5e7368ace0e18eff93a4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"quick-lru@npm:^4.0.1":
|
||||
version: 4.0.1
|
||||
resolution: "quick-lru@npm:4.0.1"
|
||||
|
|
@ -25215,6 +25277,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"real-require@npm:^0.2.0":
|
||||
version: 0.2.0
|
||||
resolution: "real-require@npm:0.2.0"
|
||||
checksum: 10c0/23eea5623642f0477412ef8b91acd3969015a1501ed34992ada0e3af521d3c865bb2fe4cdbfec5fe4b505f6d1ef6a03e5c3652520837a8c3b53decff7e74b6a0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"recast@npm:^0.23.3, recast@npm:^0.23.5":
|
||||
version: 0.23.7
|
||||
resolution: "recast@npm:0.23.7"
|
||||
|
|
@ -26106,6 +26175,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"secure-json-parse@npm:^4.0.0":
|
||||
version: 4.1.0
|
||||
resolution: "secure-json-parse@npm:4.1.0"
|
||||
checksum: 10c0/52b3f8125ea974db1333a5b63e6a1df550c36c0d5f9a263911d6732812bd02e938b30be324dcbbb9da3ef9bf5a84849e0dd911f56544003d3c09e8eee12504de
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"semver@npm:2 || 3 || 4 || 5, semver@npm:^5.7.1":
|
||||
version: 5.7.1
|
||||
resolution: "semver@npm:5.7.1"
|
||||
|
|
@ -26558,6 +26634,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"slow-redact@npm:^0.3.0":
|
||||
version: 0.3.1
|
||||
resolution: "slow-redact@npm:0.3.1"
|
||||
checksum: 10c0/7f495a85108f554ea492b7fa1c8892b690a8172cb6d8cd77c56fef00a15d15f46b497a8eb61355a61cc06cbb34246088dc3372ed2ffb22e645c8c5dabc334563
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"smart-buffer@npm:^4.2.0":
|
||||
version: 4.2.0
|
||||
resolution: "smart-buffer@npm:4.2.0"
|
||||
|
|
@ -26619,6 +26702,15 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"sonic-boom@npm:^4.0.1":
|
||||
version: 4.2.0
|
||||
resolution: "sonic-boom@npm:4.2.0"
|
||||
dependencies:
|
||||
atomic-sleep: "npm:^1.0.0"
|
||||
checksum: 10c0/ae897e6c2cd6d3cb7cdcf608bc182393b19c61c9413a85ce33ffd25891485589f39bece0db1de24381d0a38fc03d08c9862ded0c60f184f1b852f51f97af9684
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "source-map-js@npm:1.0.2"
|
||||
|
|
@ -26806,13 +26898,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stack-trace@npm:0.0.x":
|
||||
version: 0.0.10
|
||||
resolution: "stack-trace@npm:0.0.10"
|
||||
checksum: 10c0/9ff3dabfad4049b635a85456f927a075c9d0c210e3ea336412d18220b2a86cbb9b13ec46d6c37b70a302a4ea4d49e30e5d4944dd60ae784073f1cde778ac8f4b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"stack-utils@npm:^2.0.3":
|
||||
version: 2.0.6
|
||||
resolution: "stack-utils@npm:2.0.6"
|
||||
|
|
@ -27162,6 +27247,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"strip-json-comments@npm:^5.0.2":
|
||||
version: 5.0.3
|
||||
resolution: "strip-json-comments@npm:5.0.3"
|
||||
checksum: 10c0/daaf20b29f69fb51112698f4a9a662490dbb78d5baf6127c75a0a83c2ac6c078a8c0f74b389ad5e0519d6fc359c4a57cb9971b1ae201aef62ce45a13247791e0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"strnum@npm:^1.0.5":
|
||||
version: 1.0.5
|
||||
resolution: "strnum@npm:1.0.5"
|
||||
|
|
@ -27724,13 +27816,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"text-hex@npm:1.0.x":
|
||||
version: 1.0.0
|
||||
resolution: "text-hex@npm:1.0.0"
|
||||
checksum: 10c0/57d8d320d92c79d7c03ffb8339b825bb9637c2cbccf14304309f51d8950015c44464b6fd1b6820a3d4821241c68825634f09f5a2d9d501e84f7c6fd14376860d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"text-table@npm:^0.2.0":
|
||||
version: 0.2.0
|
||||
resolution: "text-table@npm:0.2.0"
|
||||
|
|
@ -27756,6 +27841,15 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"thread-stream@npm:^3.0.0":
|
||||
version: 3.1.0
|
||||
resolution: "thread-stream@npm:3.1.0"
|
||||
dependencies:
|
||||
real-require: "npm:^0.2.0"
|
||||
checksum: 10c0/c36118379940b77a6ef3e6f4d5dd31e97b8210c3f7b9a54eb8fe6358ab173f6d0acfaf69b9c3db024b948c0c5fd2a7df93e2e49151af02076b35ada3205ec9a6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"through2@npm:^2.0.3":
|
||||
version: 2.0.5
|
||||
resolution: "through2@npm:2.0.5"
|
||||
|
|
@ -29644,17 +29738,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"winston-transport@npm:^4.5.0":
|
||||
version: 4.5.0
|
||||
resolution: "winston-transport@npm:4.5.0"
|
||||
dependencies:
|
||||
logform: "npm:^2.3.2"
|
||||
readable-stream: "npm:^3.6.0"
|
||||
triple-beam: "npm:^1.3.0"
|
||||
checksum: 10c0/110a47c5acc87c3aa0f101741c0a992e52a86802272838c18aede8178d2b5e80254d2433dcac3439cefbc2777d9e22e65f84e9cee3130681c58e4ae5d58f50c3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"winston-transport@npm:^4.7.0":
|
||||
version: 4.7.0
|
||||
resolution: "winston-transport@npm:4.7.0"
|
||||
|
|
@ -29666,25 +29749,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"winston@npm:^3.10.0":
|
||||
version: 3.10.0
|
||||
resolution: "winston@npm:3.10.0"
|
||||
dependencies:
|
||||
"@colors/colors": "npm:1.5.0"
|
||||
"@dabh/diagnostics": "npm:^2.0.2"
|
||||
async: "npm:^3.2.3"
|
||||
is-stream: "npm:^2.0.0"
|
||||
logform: "npm:^2.4.0"
|
||||
one-time: "npm:^1.0.0"
|
||||
readable-stream: "npm:^3.4.0"
|
||||
safe-stable-stringify: "npm:^2.3.1"
|
||||
stack-trace: "npm:0.0.x"
|
||||
triple-beam: "npm:^1.3.0"
|
||||
winston-transport: "npm:^4.5.0"
|
||||
checksum: 10c0/eb9298ae9c335f54d4731525231df9f216d39a55bc1676b0375cbd9d2a14e302d0a700972ffb97626ab352e41f607739b5b8ee5feaadcf06c11977cb8ecd834a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"word-wrap@npm:~1.2.3":
|
||||
version: 1.2.5
|
||||
resolution: "word-wrap@npm:1.2.5"
|
||||
|
|
|
|||
Loading…
Reference in a new issue