ESBuild vs SWC vs Vite徹底比較 2025 - 高速ビルドツールの選び方
次世代高速ビルドツールESBuild、SWC、Viteを徹底比較。10倍から100倍の高速化を実現する各ツールの特徴、パフォーマンス、エコシステム、実践的な使い分けまで完全解説します。
5倍以上の高速化を実現するNode.jsロガーPinoを徹底解説。JSONロギング、トランスポートシステム、本番環境での活用方法まで、パフォーマンスを重視したロギング戦略の全てを網羅します。
Pino は、Node.jsアプリケーションのための超高速JSONロガーです。従来のロギングライブラリと比較して5倍以上の高速化を実現し、本番環境でのパフォーマンス低下を最小限に抑えます。
従来のロガーが原因でアプリケーションが遅延
大量のログでメモリ逼迫
構造化されていないログの解析困難
最小オーバーヘッド・JSON形式
Fastify等の主要フレームワークが採用
ロガー | 処理速度 (ops/sec) | Pino比 | メモリ使用量 |
---|---|---|---|
Pino | 150,000 | 1.0x | 10MB |
Winston | 25,000 | 6.0x遅い | 45MB |
Bunyan | 30,000 | 5.0x遅い | 38MB |
Debug | 15,000 | 10.0x遅い | 25MB |
Console.log | 100,000 | 1.5x遅い | 5MB |
// インストール
npm install pino
// 基本的な使用方法
const pino = require('pino');
const logger = pino({
level: process.env.PINO_LOG_LEVEL || 'info',
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'HH:MM:ss Z',
ignore: 'pid,hostname'
}
}
});
logger.info('Hello world');
logger.info({ user: 'john', action: 'login' }, 'User logged in');
logger.error(new Error('Something went wrong'));
// 子ロガーの作成
const childLogger = logger.child({ module: 'auth' });
childLogger.info('Authentication module initialized');
// express-pinoのインストール
npm install express-pino-logger
const express = require('express');
const pino = require('pino');
const expressPino = require('express-pino-logger');
const logger = pino({ level: 'info' });
const expressLogger = expressPino({ logger });
const app = express();
app.use(expressLogger);
app.get('/', (req, res) => {
// req.logが自動的に利用可能
req.log.info('Homepage requested');
res.send('Hello World');
});
// リクエストIDの自動追加
app.use(expressPino({
logger,
genReqId: (req) => req.headers['x-request-id'] || crypto.randomUUID(),
serializers: {
req: (req) => ({
method: req.method,
url: req.url,
headers: req.headers
})
}
}));
// Fastifyには標準搭載
const fastify = require('fastify')({
logger: {
level: 'info',
prettyPrint: process.env.NODE_ENV !== 'production',
serializers: {
res(reply) {
return {
statusCode: reply.statusCode,
responseTime: reply.getResponseTime()
}
},
req(request) {
return {
method: request.method,
url: request.url,
path: request.routerPath,
parameters: request.params
}
}
}
}
});
fastify.get('/', async (request, reply) => {
request.log.info('Homepage route');
return { hello: 'world' };
});
// カスタムログレベル
fastify.log.level = 'debug';
チャートを読み込み中...
// カスタムレベルの定義
const logger = pino({
customLevels: {
audit: 35,
critical: 55
},
useOnlyCustomLevels: false,
level: 'info'
});
// 条件付きロギング
logger.level = 'info';
logger.debug('This will not be logged');
logger.info('This will be logged');
// 動的レベル変更
if (process.env.NODE_ENV === 'development') {
logger.level = 'debug';
}
Pino の強力な機能の 1 つは、ログ処理を別プロセスに委譲するトランスポートシステムです:
// transport.js
module.exports = (options) => {
return require('pino-abstract-transport')(async (source) => {
for await (const obj of source) {
// カスタム処理
if (obj.level >= 50) { // error以上
await sendToSlack(obj);
}
// Elasticsearch送信
await indexToElasticsearch({
...obj,
'@timestamp': new Date(obj.time).toISOString()
});
}
});
};
// 使用方法
const logger = pino({
transport: {
target: './transport.js',
options: {
slackWebhook: process.env.SLACK_WEBHOOK,
esEndpoint: process.env.ES_ENDPOINT
}
}
});
// config/logger.js
const pino = require('pino');
const isProduction = process.env.NODE_ENV === 'production';
const options = {
level: process.env.LOG_LEVEL || (isProduction ? 'info' : 'debug'),
// 本番環境では整形を無効化
...(isProduction
? {}
: {
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'SYS:standard',
ignore: 'pid,hostname'
}
}
}
),
// リダクション設定
redact: {
paths: ['password', 'token', '*.secret'],
remove: true
},
// シリアライザー
serializers: {
err: pino.stdSerializers.err,
req: (req) => ({
id: req.id,
method: req.method,
url: req.url,
remoteAddress: req.remoteAddress
}),
res: (res) => ({
statusCode: res.statusCode
})
}
};
module.exports = pino(options);
// pino-rotating-file-stream の使用
const pino = require('pino');
const { multistream } = require('pino');
const { createStream } = require('rotating-file-stream');
const streams = [
// 標準出力(JSON形式)
{ stream: process.stdout },
// ローテーションファイル
{
level: 'error',
stream: createStream('error.log', {
size: '10M',
interval: '1d',
compress: 'gzip',
path: './logs'
})
}
];
const logger = pino({
level: 'info'
}, multistream(streams));
// 構造化されたログ
const logger = pino();
// ❌ 避けるべきパターン
logger.info(`User ${userId} logged in from ${ip}`);
// ✅ 推奨パターン
logger.info({
event: 'user_login',
userId,
ip,
userAgent: req.headers['user-agent'],
timestamp: Date.now()
}, 'User login successful');
// コンテキスト付きロギング
const userLogger = logger.child({
userId,
sessionId: req.sessionID
});
userLogger.info({ action: 'view_profile' }, 'Profile viewed');
userLogger.info({ action: 'update_settings' }, 'Settings updated');
// エラーログの構造化
class AppError extends Error {
constructor(message, code, statusCode) {
super(message);
this.code = code;
this.statusCode = statusCode;
this.timestamp = new Date().toISOString();
}
}
// エラーハンドリング
app.use((err, req, res, next) => {
const errorLog = {
error: {
message: err.message,
stack: err.stack,
code: err.code || 'INTERNAL_ERROR',
statusCode: err.statusCode || 500
},
request: {
method: req.method,
url: req.url,
headers: req.headers,
body: req.body
},
context: {
userId: req.user?.id,
requestId: req.id
}
};
req.log.error(errorLog, 'Request error');
res.status(errorLog.error.statusCode).json({
error: errorLog.error.message,
requestId: req.id
});
});
// パフォーマンス計測
const logger = pino();
// 時間計測ヘルパー
function createTimer(name) {
const start = process.hrtime.bigint();
return {
end: (metadata = {}) => {
const duration = Number(process.hrtime.bigint() - start) / 1e6;
logger.info({
metric: 'timing',
name,
duration,
unit: 'ms',
...metadata
}, `${name} completed in ${duration}ms`);
return duration;
}
};
}
// 使用例
async function processOrder(orderId) {
const timer = createTimer('order_processing');
try {
const order = await fetchOrder(orderId);
await validateOrder(order);
await processPayment(order);
timer.end({
orderId,
amount: order.total,
success: true
});
} catch (error) {
timer.end({
orderId,
success: false,
error: error.message
});
throw error;
}
}
# インストール
npm install -D pino-pretty
# 使用方法
node app.js | pino-pretty
# カスタマイズ
node app.js | pino-pretty \
--colorize \
--translateTime "SYS:standard" \
--ignore "pid,hostname" \
--messageKey "msg"
// pino-elasticsearch
const pinoElastic = require('pino-elasticsearch');
const streamToElastic = pinoElastic({
index: 'app-logs',
consistency: 'one',
node: 'http://localhost:9200',
'es-version': 8,
'flush-bytes': 1000
});
const logger = pino({ level: 'info' }, streamToElastic);
// pino-cloudwatch
const pinoCloudWatch = require('pino-cloudwatch');
const stream = pinoCloudWatch({
group: '/aws/lambda/my-function',
prefix: process.env.AWS_LAMBDA_FUNCTION_NAME,
interval: 5000,
aws_region: process.env.AWS_REGION
});
const logger = pino({ level: 'info' }, stream);
Pino は単なるロガーではありません。アプリケーションのパフォーマンスを犠牲にすることなく、本番環境で必要な全ての情報を記録できるよう設計されています。
Pino は、パフォーマンスと開発体験の両立を実現した、Node.jsアプリケーションのための理想的なロギングソリューションです:
特に、高トラフィックな API サーバーやマイクロサービスアーキテクチャでの採用を強く推奨します。