[ Log ]
- ์ปดํจํฐ์ ์ฒ๋ฆฌ ๋ด์ฉ์ด๋ ์ด์ฉ ์ํฉ, ์ค๋ฅ ์ถ๋ ฅ ๋ฉ์์ง ๋ฑ์ ์๊ฐ์ ํ๋ฆ์ ๋ฐ๋ผ ๊ธฐ๋กํ ๊ฒ
- ์์คํ ๋ณด์์ด๋ ์ ์ง๋ณด์ ๋ชฉ์ ๋ฑ์ ์ฌ์ฉ๋๋ค.
- ์ ์ ์ ์ด๋ฒคํธ, ๋ฐ์ดํฐ ์์ฒญ, ํธ๋์ญ์ ์๋ฌ ๊ท๋ช ๋ฑ์ ์ ๋ฐ ๋ถ์ ๋ฐ ๊ด๋ฆฌ ๊ฐ๋ฅ
[ Dotenv ]
- Node.js์์ ์ฌ์ฉ์ ํ๊ฒฝ ๋ณ์๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํด์ฃผ๋ ๋ชจ๋
- ๋ณดํต DB ๊ด๋ จ ์ ๋ณด, API_KEY ๋ฑ, ๊ณต๊ฐ๋๋ฉด ์๋๋ ์ ๋ณด๋ค์ ๊ด๋ฆฌ
- ๋ณดํต .env๋ผ๋ ํ์ผ์ ์ธ๋ถ์ ์์ฑํ์ฌ ๋ถ๋ฌ์ ์ฌ์ฉ
1. dotenv ๋ชจ๋ ์์กด์ฑ ์ถ๊ฐ
$ npm install dotenv --save
2. .env ํ๊ฒฝ ๋ณ์ ํ์ผ ์์ฑ
// ๋ณธ์ธ์ ํ๋ก์ ํธ ์ต์์ ๋ฃจํธ ๊ธฐ์ค ./config/.env ์์ฑ
PORT=3000 // ์๋ฒ ํฌํธ ๋ฒํธ ์ง์
NODE_ENV=dev // Node ๊ฐ๋ฐ ํ๊ฒฝ ์ง์
[ Winston ]
- Node.js์์ log๋ฅผ ํธ๋ฆฌํ๊ฒ ๊ด๋ฆฌํ ์ ์๋ ๋ชจ๋
- ์ค์ ์๋ฒ ์ด์ ์ console.log, console.error๋ฅผ ๋์ฒดํ๊ธฐ ์ํ ๋ชจ๋
1. winston, winston-daily-rotate-file ๋ชจ๋ ์์กด์ฑ ์ถ๊ฐ
=> winston-daily-rotate-file์ ๋ก๊ทธ ํ์ผ์ ๊ด๋ฆฌํด์ฃผ๋ ๋ชจ๋
๊ธฐ๋ณธ๊ฐ์ผ๋ก ํ๋ฃจ ๋จ์ ์ ๋ก๊ทธ ํ์ผ์ ์์ฑํ๋ฉฐ, ๋ ์ง๋ณ ๋ก๊ทธํ์ผ ๊ด๋ฆฌ,
๋ก๊ทธ ํ์ผ ์ค์ ๋ฑ์ ๊ด๋ฆฌ๋ฅผ ์ฉ์ดํ๊ฒ ํด์ค
$ npm install winston winston-daily-rotate-file --save
2. logger.js ํ์ผ ์์ฑ
=> dotenv ๋ชจ๋์ ํธ์ถํ์ฌ .env ํ์ผ์ ์ฌ์ฉ์ ํ๊ฒฝ๋ณ์๋ฅผ ์ฐธ์กฐํ ๋
๋ง์ฝ .env ํ์ผ์ด ํ๋ก์ ํธ ์ต์์ ๋ฃจํธ ๊ฒฝ๋ก์ ์์ง ์์ ๊ฒฝ์ฐ dotenv.config() ๋ฉ์๋๋ฅผ ํตํด
{ path : {์ค์ ๊ฒฝ๋ก} } ์ค์ ๊ฒฝ๋ก๋ฅผ ๋ช ์ํด์ฃผ๋ฉด ๋จ.
.env ํ์ผ์ด ์ต์์ ๋ฃจํธ์ ์กด์ฌํ ๊ฒฝ์ฐ ๊ทธ๋ฅ dotenv.config() ์ฌ์ฉ
const winston = require("winston"); // winston ๋ชจ๋ ํธ์ถ
const winstonDaily = require("winston-daily-rotate-file"); // winston-daily-rotate-file ๋ชจ๋ ํธ์ถ
const process = require("process"); // process ๋ชจ๋ ํธ์ถ
const dotenv = require("dotenv"); // dotenv ๋ชจ๋ ํธ์ถ
dotenv.config({ path: `${process.cwd()}/config/.env` });
// Check .env
console.log("NODE ENV : " + process.env.NODE_ENV);
console.log("PORT : " + process.env.PORT);
// Set save logfile root path
const logDir = `${process.cwd() + "/logs"}`;
const { combine, timestamp, label, printf } = winston.format;
// Define log format
const logFormat = printf(({ timestamp, label, level, message }) => {
return `[${timestamp}] [${label}] [${level}] | ${message}`;
});
/*
* Log Level
* Error: 0, Warn: 1, Info: 2, Http: 3, Verbose: 4, Debug: 5, Silly: 6
* low level => high priority
*/
const logger = winston.createLogger({
// Define log output format
format: combine(
timestamp({
format: "YYYY-MM-DD HH:mm:ss",
}),
label({ label: "UMS Express Server" }), // App name
logFormat // Log output Format
),
// Define detail log output format settings
transports: [
/*
* Define info level log settings
* ์๋์ผ๋ก info:2 ๋ ๋ฒจ ๊ฐ๋ณด๋ค ๋์ warn: 1, error: 0 ๋ก๊ทธ๋ค๋ ํฌํจ๋จ
*/
new winstonDaily({
level: "info",
datePattern: "YYYY-MM-DD",
dirname: logDir,
filename: `%DATE%.log`,
maxFiles: 30, // ๊ฐ์ฅ ์ต๊ทผ 30์ผ์น ๋ก๊ทธ ํ์ผ ์ ์ฅ
zippedArchive: true, // ์์นด์ด๋ธ๋ ๋ก๊ทธ ํ์ผ์ gzip ์์ถ ์ฌ๋ถ
}),
/*
* Define error level log settings
* ๊ธฐ๋ณธ์ ์ผ๋ก info level์ ํฌํจ๋๋, ๊ตฌ๋ถ์ ์ํด ํ์ ๋ณ๊ฒฝ ํ ๊ฐ๋ณ ์ง์
*/
new winstonDaily({
level: "error",
datePattern: "YYYY-MM-DD",
dirname: logDir + "/error", // log ๊ธฐ๋ณธ ์ ์ฅ ๊ฒฝ๋ก ํ์ /error ๊ฒฝ๋ก๋ก ์ค์
filename: `%DATE%.error.log`,
maxFiles: 30,
zippedArchive: true,
}),
/*
* http
*/
new winstonDaily({
level: "http",
datePattern: "YYYY-MM-DD",
dirname: logDir + "/http",
filename: `%DATE%.http.log`,
maxFiles: 30,
zippedArchive: true,
}),
],
// UncaughtException file settings
exceptionHandlers: [
new winstonDaily({
level: "error",
datePattern: "YYYY-MM-DD",
dirname: logDir + "/exception",
filename: `%DATE%.exception.log`,
maxFiles: 30,
zippedArchive: true,
}),
],
});
/*
* Production ํ๊ฒฝ์ด ์๋, ๊ฐ๋ฐ ํ๊ฒฝ์ ๊ฒฝ์ฐ ์ฝ์์ ์ถ๋ ฅ
*/
if (process.env.NODE_ENV !== "production") {
logger.add(
new winston.transports.Console({
format: winston.format.combine(
winston.format.colorize({ level: true, message: true }),
// winston.format.label(),
winston.format.simple(), // Output format => JSON.stringify({ ...rest })
logFormat
),
})
);
}
module.exports = logger;
3. ๋ก๊ทธ ์๋ ํ ์คํธ
// test.js
const logger = require("./config/logger");
logger.info("hello world");
logger.error("hello world");
logger.warn("hello world");
[ Morgan ]
- http ์์ฒญ ๋ฐ ์๋ต์ ๋ํ ์ ๋ณด๋ฅผ ๋ก๊น ํ๊ธฐ ์ํ ๋ชจ๋
- winston ๋ก๊ทธ์ http level์ ํ์ฉํ ๋ ์ฌ์ฉ
1. morgan ๋ชจ๋ ์์กด์ฑ ์ถ๊ฐ
$ npm install morgan --save
2. morgan ๋ฏธ๋ค์จ์ด ์์ฑ
// ./utils/morgan.js
const morgan = require("morgan");
const logger = require("../config/logger");
const dotenv = require("dotenv");
dotenv.config({ path: `${process.cwd()}/config/.env` });
/*
* NODE_ENV์ ๋ฐ๋ผ์ morgan ์ต์
format ๋ณ๊ฒฝ
* combined ์ต์
์ด dev ์ต์
๋ณด๋ค ์์ธํจ
*/
const format = () => {
const result = process.env.NODE_ENV === "production" ? "combined" : "dev";
return result;
};
// ๋ก๊ทธ ์์ฑ์ ์ํ Output stream ์ต์
const stream = {
write: (message) => {
logger.http(
message.replace(
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
""
)
);
},
};
/*
* ๋ก๊น
์คํต ์ฌ๋ถ ์ฒดํฌ
* ๋ฐฐํฌํ๊ฒฝ(production | res.statusCode < 400)์ผ ๊ฒฝ์ฐ ๋ก๊ทธ ๊ธฐ๋ก x
*/
const skip = (_, res) => {
if (process.env.NODE_ENV === "production") {
return res.statusCode < 400;
}
return false;
};
const morganMiddleware = morgan(format(), { stream, skip });
module.exports = morganMiddleware;
[ ๋ฉ์ธ ์ฑ ์๋ฒ Winston + Morgan ์ ์ฉ ]
1. ๋ฉ์ธ ์ฑ ์๋ฒ ํ์ผ์ ๋ก๊ทธ, ๋ชจ๊ฑด ๋ชจ๋ ์์ฑ ํ์ผ ๋ฐ ๋ผ์ฐํฐ ๋ฑ๋ก
// app.js
const express = require("express");
const morganMiddleware = require("./utils/morganMiddleware"); // ์ฌ์ฉ์ morgan ๋ชจ๋ ํธ์ถ
const logger = require("./config/logger"); // ์ฌ์ฉ์ log ๋ชจ๋ ํธ์ถ
const router = require("./routes/router"); // ๋ผ์ฐํฐ ๋ชจ๋ ํธ์ถ
const dotenv = require("dotenv");
dotenv.config();
const app = express();
const PORT = process.env.PORT;
// ํ๋ก์ ์๋ฒ์ ip ์ฃผ์ ์ถ๋ ฅ
app.set("trust proxy", true);
app.use(morganMiddleware);
app.use("/router", router);
app.get("/", (req, res) => {
res.send("Hello World");
});
app.listen(PORT, "0.0.0.0", () => {
logger.info(`Server listening on port ${PORT}`);
});
// ./routes/router.js
const express = require("express");
const logger = require("../config/logger");
const router = express.Router();
router.get("/logging", (req, res) => {
logger.info("Get /router/logging : " + req.ip);
res.writeHead(404, { "Content-Type": "text/html" });
res.end("error!!");
});
router.get("/skip", (req, res) => {
logger.info("Get /router/info : " + req.ip);
res.writeHead(200, { "Content-Type": "text/html" });
res.end("success!!");
});
module.exports = router;
2. ๋ฉ์ธ ์ฑ ์๋ฒ ์คํ ๊ฒฐ๊ณผ ํ์ธ
=> logger.js ํ์ผ ์ฝ๋ ํ๋จ๋ถ์ NODE_ENV๊ฐ 'production'์ด ์๋๊ธฐ ๋๋ฌธ์ ๋ก๊ทธ ๋ด์ฉ ์ฝ์ ์ถ๋ ฅ
3. ๋ก๊ทธ ๊ด๋ฆฌ ํด๋ ๋ฐ ํ์ผ ์์ฑ ํ์ธ
์ฐธ๊ณ : https://velog.io/@sung-ik-je/%EA%B0%9C%EB%85%90-Log
Log๋?
์ปดํจํฐ์ ์ฒ๋ฆฌ ๋ด์ฉ์ด๋ ์ด์ฉ ์ํฉ์ ์๊ฐ์ ํ๋ฆ์ ๋ฐ๋ฅธ ๊ธฐ๋ก๊ฐ์ธ์ฉ ์ปดํจํฐ ํต์ ์์ ๋ฉ์ผ ๋ฑ ํต์ ๋ด์ฉ์ ๊ธฐ๋ก์ด๋ฉฐ, ๊ทธ ํ์ผ์ ๋ก๊ทธ ํ์ผ(log file)์ด๋ผ๊ณ ํ๋คํต๋๋ฌด ๋ชฉ์ log on(์น์ ), log out(ํ
velog.io
์ฐธ๊ณ : https://inpa.tistory.com/entry/NODE-%F0%9F%93%9A-Winston-%EB%AA%A8%EB%93%88-%EC%82%AC%EC%9A%A9%EB%B2%95-%EC%84%9C%EB%B2%84-%EB%A1%9C%EA%B7%B8-%EA%B4%80%EB%A6%AC
[NODE] ๐ Winston ๋ชจ๋ ์ฌ์ฉ๋ฒ - ์๋ฒ ๋ก๊ทธ ๊ด๋ฆฌ
Winston ๋ชจ๋ ์ด๋ค ์๋ฒ๋ ์ง ์ค์ ๋ก ์๋น์ค๋ฅผ ์ด์ํ๋ ค๋ฉด ๋ก๊ทธ๋ฅผ ๊ผผ๊ผผํ ๋จ๊ธฐ๋ ๊ฒ์ ํ์์ด๋ค. Log๋ ์๋ฌ๋ฅผ ํ์ ํ ์ ์๋ ์ด์ ์ด๊ธฐ ๋๋ฌธ์ ์๋ฒ๋ฅผ ์ด์ํ๋ค๊ณ ํ๋ฉด ๋ก๊ทธ ์์คํ ์ ๊ตฌ์ถํด์ ์
inpa.tistory.com
์ฐธ๊ณ : https://inpa.tistory.com/entry/EXPRESS-%F0%9F%93%9A-morgan-%EB%AF%B8%EB%93%A4%EC%9B%A8%EC%96%B4#[options]
[EXPRESS] ๐ morgan ๋ฏธ๋ค์จ์ด ๐ฏ ์ฌ์ฉ๋ฒ ์ ๋ฆฌ
morgan ๋ชจ๋ morgan์ ์ฐ๊ฒฐ ํ ํฌํธ์ ์ ์ํ๋ฉด ๊ธฐ์กด ๋ก๊ทธ ์ธ์ ์ถ๊ฐ์ ์ธ ๋ก๊ทธ๋ฅผ ๋ณผ ์ ์๋ค. ์ ์ฝ๋๋ฅผ ์คํํ์ฌ 3000๋ฒ ํฌํธ์ ๋ค์ด๊ฐ ํ ์ฝ์์ ๋ณด๋ฉด ์๋์ ๊ฐ์ ๋ก๊ทธ๊ฐ ์ฐํ์๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
inpa.tistory.com