In the previous article [II] created @ vue / cli3 plug and integrated function ---- [ssr SSR The second , we have created a @vue/cli3
plug-in, and ssr
integrated into the plug-in service.
This article, let's plug-in to ssr
create a log system services.
We will come gradually following aspects:
- Select the log tool library
- Logging tools integrated into the
ssr
plug-in - Log support distinguish environment, support the classification of the log, the log level of support
- Cutting logs
Select the log tool library
Some logging tools based nodejs library to choose from:
Here we choose winston
as the basis for logging tools, access to our ssr
engineering
Logging tools integrated into the ssr
plug-in
We opened winston
the the README , refer to Creating your own Logger one, to start creating ourlogger
Create a logger
In the last article we opened [II] created @ vue / cli3 plug-in, and integrate ssr SSR The second function ---- [ created vue-cli-plugin-my_ssr_plugin_demo
project
installation winston
yarn add winston
复制代码
In the root folder app
create folder lib
and lib
create the logger.js
files, customize our own logger in this document
Directory structure is as follows:
├── app
│ ├── lib
│ │ ├── logger.js
│ ├── middlewares
│ │ ├── dev.ssr.js
│ │ ├── dev.static.js
│ │ └── prod.ssr.js
│ └── server.js
...
复制代码
logger.js
It reads as follows:
const winston = require('winston')
const logger = winston.createLogger({
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'combined.log' })
]
})
module.exports = {
logger
}
复制代码
Then open our app/server.js
, in the course of the service starts, the global object mounted on we just createdlogger
...
const { logger } = require('./lib/logger.js')
...
app.listen(port, host, () => {
logger.info(`[${process.pid}]server started at ${host}:${port}`)
})
...
复制代码
Start the service, in addition to seeing the output terminal, it will also find more than one in the root directory of combined.log
the file, the contents of which are consistent with the output terminal
{"message":"[46071]server started at 127.0.0.1:3000","level":"info"}
复制代码
So far, we have access to the most basic logging into the server, then, let us consider the actual log scene.
Log support distinguish environment, support the classification of the log, the log level of support
For simplicity, we will distinguish between the environment, the log classification, log level simplified into the following specific requirements:
- Log needs to be written to the file.
- Logs need to support custom level, level in descending order
error
are:warning
,notice
,info
,debug
, . - Development environment, the best output log colored, can be more easily read format in the terminal.
- Increase user request log
access
type, this log needs to be written to a separate file, separate from other types of log area.
On the first request, we in the previous example, has passed winston.transports.File
realized.
For the second, three requirements, we turn lib/logger.js
to add the relevant code, the final code is as follows:
const winston = require('winston')
const options = {
// 我们在这里定义日志的等级
levels: { error: 0, warning: 1, notice: 2, info: 3, debug: 4 },
transports: [
// 文件中我们只打印 warning 级别以上的日志(包含 warning)
new winston.transports.File({ filename: 'combined.log', level: 'warning' })
]
}
// 开发环境,我们将日志也输出到终端,并设置上颜色
if (process.env.NODE_ENV === 'development') {
options.format = winston.format.combine(
winston.format.colorize(),
winston.format.json()
)
// 输出到终端的信息,我们调整为 simple 格式,方便看到颜色;
// 并设置打印 debug 以上级别的日志(包含 debug)
options.transports.push(new winston.transports.Console({
format: winston.format.simple(), level: 'debug'
}))
}
const logger = winston.createLogger(options)
module.exports = {
logger
}
复制代码
We app/servier.js
enter the following code:
...
logger.error('this is the error log')
logger.warning('this is the warning log')
logger.notice('this is the info log')
logger.info('this is the info log')
logger.debug('this is the debug log')
...
复制代码
After hair open environment to start the service, to see the terminal prints out the following:
error: this is the error log
warning: this is the warning log
notice: this is the info log
info: this is the info log
debug: this is the debug log
复制代码
The log file combined.log
contents are as follows:
{"message":"this is the error log","level":"\u001b[31merror\u001b[39m"}
{"message":"this is the warning log","level":"\u001b[31mwarning\u001b[39m"}
复制代码
After the test and production environments start the service, and the log will not be output to the terminal, only the output to a file:
{"message":"this is the error log","level":"error"}
{"message":"this is the warning log","level":"warning"}
复制代码
Next we look at Article IV requirements:
Increase user request log
access
type, this log needs to be written to a separate file, separate from other types of log area.
If we need to add a access
log type, and outputs its contents to a separate file, the easiest way is to create one logger
instance:
...
winston.loggers.add('access', {
levels: { access: 0 },
level: 'access',
format: winston.format.combine(
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'access.log', level: 'access' })
]
})
...
复制代码
We app/servier.js
add printing access
logs code:
const { logger, accessLogger } = require('./log.js')
...
accessLogger.access('this is the access log')
复制代码
After starting the service development environment, we found that in addition to combined.log
outside the log file, the addition of a access.log
file, reads:
{"message":"this is the access log","level":"access"}
复制代码
So far, we have not log automatically records the current time, we have lib/logger.js
two categories are added on a log time, add the following code:
const winston = require('winston')
const options = {
// 我们在这里定义日志的等级
levels: { error: 0, warning: 1, notice: 2, info: 3, debug: 4 },
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' })
),
transports: [
// 文件中我们只打印 warning 级别以上的日志(包含 warning)
new winston.transports.File({ filename: 'combined.log', level: 'warning' })
]
}
// 开发环境,我们将日志也输出到终端,并设置上颜色
if (process.env.NODE_ENV === 'development') {
options.format = winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
winston.format.colorize(),
winston.format.json()
)
// 输出到终端的信息,我们调整为 simple 格式,方便看到颜色;
// 并设置打印 debug 以上级别的日志(包含 debug)
options.transports.push(new winston.transports.Console({
format: winston.format.simple(), level: 'debug'
}))
}
winston.loggers.add('access', {
levels: { access: 0 },
level: 'access',
format: winston.format.combine(
winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'access.log', level: 'access' })
]
})
const logger = winston.createLogger(options)
module.exports = {
logger,
accessLogger: winston.loggers.get('access')
}
复制代码
After development environment to start the service, we found the log carrying current time information, the terminal reads:
error: this is the error log {"timestamp":"2019-06-06 17:02:36.736"}
warning: this is the warning log {"timestamp":"2019-06-06 17:02:36.740"}
notice: this is the info log {"timestamp":"2019-06-06 17:02:36.741"}
info: this is the info log {"timestamp":"2019-06-06 17:02:36.741"}
debug: this is the debug log {"timestamp":"2019-06-06 17:02:36.741"}
复制代码
`` File contents are as follows:
{"message":"this is the error log","level":"\u001b[31merror\u001b[39m","timestamp":"2019-06-06 17:02:36.736"}
{"message":"this is the warning log","level":"\u001b[31mwarning\u001b[39m","timestamp":"2019-06-06 17:02:36.740"}
复制代码
`` File contents are as follows:
{"message":"this is the access log","level":"access","timestamp":"2019-06-06 17:02:36.741"}
复制代码
Cutting logs
After our future deployment of on-line service, the server logs recorded content will continue to have written to the log to the same file, which for long-running services, is there a log too big risks.
Here, we split logs per hour in accordance with the contents of the log within each hour, write different files.
In addition, since the deployment of goods and services have multiple worker
processes and services, so we assign a separate folder (in order to distinguish between the process id + date) for each process to store all logs this process:
logs
├──your_project_name
│ ├──pid_1236_2019_01_01
│ │ ├──access-2019-01-01-23.log
│ │ └──combined-2019-01-01-23.log
│ └──pid_1237_2019_01_01
│ ├──access-2019-01-01-23.log
│ └──combined-2019-01-01-23.log
复制代码
In order to achieve our expected log cutting function, we need to introduce a library:winston-daily-rotate-file
yarn add winston-daily-rotate-file
复制代码
After installation, we have lib/logger.js
introduced in
require('winston-daily-rotate-file')
复制代码
After the introduction, we can winston.transports.DailyRotateFile
have automatic cutting function tracsports instance creation
const _getToday = (now = new Date()) => `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`
let dirPath += '/pid_' + pid + '_' + _getToday() + '/'
let accessTransport = new (winston.transports.DailyRotateFile)({
filename: dirPath + 'access-%DATE%.log', // 日志文件存储路径 + 日志文件名称
datePattern: 'YYYY-MM-DD-HH', // 日志文件切割的粒度,这里为每小时
zippedArchive: true, // 是否压缩
maxSize: '1g', // 每个日志文件最大的容量,如果达到此容量则触发切割
maxFiles: '30d' // 日志文件保留的时间,这里为 30 天,30天之前的日志会被删除掉
})
复制代码
After adding cutting function lib/logger.js
as follows:
const winston = require('winston')
const { format } = winston
const { combine, timestamp, json } = format
const _getToday = (now = new Date()) => `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`
const rotateMap = {
'hourly': 'YYYY-MM-DD-HH',
'daily': 'YYYY-MM-DD',
'monthly': 'YYYY-MM'
}
module.exports = (dirPath = './', rotateMode = '') => {
if (!~Object.keys(rotateMap).indexOf(rotateMode)) rotateMode = ''
let accessTransport
let combineTransport
if (rotateMode) {
require('winston-daily-rotate-file')
const pid = process.pid
dirPath += '/pid_' + pid + '_' + _getToday() + '/'
const accessLogPath = dirPath + 'access-%DATE%.log'
const combineLogPath = dirPath + 'combine-%DATE%.log'
const datePattern = rotateMap[rotateMode] || 'YYYY-MM'
accessTransport = new (winston.transports.DailyRotateFile)({
filename: accessLogPath,
datePattern: datePattern,
zippedArchive: true,
maxSize: '1g',
maxFiles: '30d'
})
combineTransport = new (winston.transports.DailyRotateFile)({
filename: combineLogPath,
datePattern: datePattern,
zippedArchive: true,
maxSize: '500m',
maxFiles: '30d'
})
}
const options = {
// 我们在这里定义日志的等级
levels: { error: 0, warning: 1, notice: 2, info: 3, debug: 4 },
format: combine(
timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' })
),
transports: rotateMode ? [
combineTransport
] : []
}
// 开发环境,我们将日志也输出到终端,并设置上颜色
if (process.env.NODE_ENV === 'development') {
options.format = combine(
timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
winston.format.colorize(),
json()
)
// 输出到终端的信息,我们调整为 simple 格式,方便看到颜色;
// 并设置打印 debug 以上级别的日志(包含 debug)
options.transports.push(new winston.transports.Console({
format: format.simple(), level: 'debug'
}))
}
winston.loggers.add('access', {
levels: { access: 0 },
level: 'access',
format: combine(
timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }),
json()
),
transports: rotateMode ? [
accessTransport
] : []
})
const logger = winston.createLogger(options)
return {
logger: logger,
accessLogger: winston.loggers.get('access')
}
}
复制代码
In app/server.js
the introduction lib/logger.js
also need to be adjusted as follows:
const { logger, accessLogger } = require('./lib/logger.js')('./', 'hourly')
复制代码
In a development environment to start the service, we will find that in addition to the output terminal of the log, we log file into a structure as follows:
./pid_48794_2019-6-6
├── access-2019-06-06-18.log
└── combine-2019-06-06-18.log
复制代码
Eventually, the plug-in vue-cli-plugin-my_ssr_plugin_demo
full directory structure is as follows:
├── app
│ ├── middlewares
│ │ ├── dev.ssr.js
│ │ ├── dev.static.js
│ │ └── prod.ssr.js
│ ├── lib
│ │ └── logger.js
│ └── server.js
├── generator
│ ├── index.js
│ └── template
│ ├── src
│ │ ├── App.vue
│ │ ├── assets
│ │ │ └── logo.png
│ │ ├── components
│ │ │ └── HelloWorld.vue
│ │ ├── entry-client.js
│ │ ├── entry-server.js
│ │ ├── main.js
│ │ ├── router
│ │ │ └── index.js
│ │ ├── store
│ │ │ ├── index.js
│ │ │ └── modules
│ │ │ └── book.js
│ │ └── views
│ │ ├── About.vue
│ │ └── Home.vue
│ └── vue.config.js
├── index.js
└── package.json
复制代码
So far, we have completed the logging system. The next article, we talk about how to vue-cli-plugin-my_ssr_plugin_demo
design and integrated monitoring system.
Drop front-end team to recruit partners, welcome to send your resume to the mailbox: [email protected]
Reproduced in: https: //juejin.im/post/5d030cc4f265da1bd04edc64