core: add "log_path" option

This commit is contained in:
Micooz 2017-08-15 23:05:32 +08:00
parent 5643ae60e9
commit 4109e5f6ba
7 changed files with 86 additions and 56 deletions

@ -14,6 +14,7 @@ function makeConfs(presets) {
"dns": [],
"dns_expire": 3600,
"timeout": 600,
"log_path": "/dev/null",
"log_level": "error"
};
const server = {

@ -58,6 +58,7 @@ module.exports = function init() {
'dns_expire': 3600,
'timeout': timeout,
'workers': 0,
'log_path': 'bs-client.log',
'log_level': 'info'
};
@ -83,6 +84,7 @@ module.exports = function init() {
'redirect': '',
'timeout': timeout,
'workers': 0,
'log_path': 'bs-server.log',
'log_level': 'info'
};

@ -59,6 +59,8 @@ $ blinksocks init
"timeout": 600,
// how many sub processes to create, default is 0(disable cluster mode)
"workers": 0,
// where to store log file
"log_path": "bs-client.log",
// log at the level, "error", "warn", "info", "verbose", "debug" or "silly"
"log_level": "info"
}
@ -107,6 +109,8 @@ $ blinksocks init
"timeout": 600,
// how many sub processes to create, default is 0(disable cluster mode)
"workers": 0,
// where to store log file
"log_path": "bs-server.log",
// log at the level, "error", "warn", "info", "verbose", "debug" or "silly"
"log_level": "info"
}
@ -145,6 +149,10 @@ Blinksocks will detect which server is the fastest in intervals using [balancer.
For more information about presets, please check out [presets](../presets).
* Log Path
Specify a relative or absolute path to store log file, if no `log_path` provided, log file named `bs-[type].log` will be stored in the working directory.
* Log Levels
The logging library [winston](https://github.com/winstonjs/winston) use

@ -1,5 +1,11 @@
const fs = jest.genMockFromModule('fs');
fs.statSync = function () {
return {
isFile: () => true
};
};
fs.lstatSync = function () {
const err = new Error();
err.code = 'ENOENT';

@ -1,30 +1,12 @@
import dns from 'dns';
import fs from 'fs';
import path from 'path';
import os from 'os';
import net from 'net';
import {isValidPort} from '../utils';
import {BLINKSOCKS_DIR, LOG_DIR, DEFAULT_LOG_LEVEL} from './constants';
import {DNS_DEFAULT_EXPIRE} from './dns-cache';
/**
* make directory if not exist
* @param dir
*/
function mkdir(dir) {
try {
fs.lstatSync(dir);
} catch (err) {
if (err.code === 'ENOENT') {
fs.mkdirSync(dir);
}
}
}
// create ~/.blinksocks directory
mkdir(BLINKSOCKS_DIR);
// create ~/.blinksocks/logs directory
mkdir(LOG_DIR);
const DEFAULT_LOG_LEVEL = 'info';
export class Config {
@ -74,24 +56,42 @@ export class Config {
}
// redirect
if (typeof json.redirect === 'string' && json.redirect !== '') {
if (typeof json.redirect !== 'undefined') {
if (typeof json.redirect !== 'string') {
throw Error('\'redirect\' is must be a string');
}
const address = json.redirect.split(':');
if (address.length !== 2 || !isValidPort(+address[1])) {
throw Error('\'redirect\' is an invalid address');
throw Error('\'redirect\' must be formed as [host:port]');
}
}
// timeout
if (typeof json.timeout !== 'number') {
throw Error('\'timeout\' must be a number');
if (typeof json.timeout !== 'undefined') {
if (typeof json.timeout !== 'number') {
throw Error('\'timeout\' must be a number');
}
if (json.timeout < 1) {
throw Error('\'timeout\' must be greater than 0');
}
if (json.timeout < 60) {
console.warn(`==> [config] 'timeout' is too short, is ${json.timeout}s expected?`);
}
}
if (json.timeout < 1) {
throw Error('\'timeout\' must be greater than 0');
// log_path
if (typeof json.log_path !== 'undefined') {
if (typeof json.log_path !== 'string') {
throw Error('\'log_path\' must be a string');
}
}
if (json.timeout < 60) {
console.warn(`==> [config] 'timeout' is too short, is ${json.timeout}s expected?`);
// log_level
if (typeof json.log_level !== 'undefined') {
const levels = ['error', 'warn', 'info', 'verbose', 'debug', 'silly'];
if (!levels.includes(json.log_level)) {
throw Error(`'log_level' must be one of [${levels.toString()}]`);
}
}
// workers
@ -123,12 +123,13 @@ export class Config {
static validateServer(server) {
// transport
if (typeof server.transport !== 'string') {
throw Error('\'server.transport\' must be a string');
}
if (!['tcp', 'udp'].includes(server.transport.toLowerCase())) {
throw Error('\'server.transport\' must be one of "tcp" or "udp"');
if (typeof server.transport !== 'undefined') {
if (typeof server.transport !== 'string') {
throw Error('\'server.transport\' must be a string');
}
if (!['tcp', 'udp'].includes(server.transport.toLowerCase())) {
throw Error('\'server.transport\' must be one of "tcp" or "udp"');
}
}
// host
@ -200,10 +201,14 @@ export class Config {
}
global.__IS_SERVER__ = !global.__IS_CLIENT__;
global.__REDIRECT__ = json.redirect;
global.__TIMEOUT__ = json.timeout * 1e3;
global.__REDIRECT__ = (json.redirect !== undefined) ? json.redirect : '';
global.__TIMEOUT__ = (json.timeout !== undefined) ? json.timeout * 1e3 : 600 * 1e3;
global.__WORKERS__ = (json.workers !== undefined) ? json.workers : 0;
global.__LOG_LEVEL__ = json.log_level || DEFAULT_LOG_LEVEL;
const absolutePath = path.resolve(process.cwd(), json.log_path || '.');
const isFile = fs.statSync(absolutePath).isFile();
global.__LOG_PATH__ = isFile ? absolutePath : path.join(absolutePath, `bs-${__IS_CLIENT__ ? 'client' : 'server'}.log`);
global.__LOG_LEVEL__ = (json.log_level !== undefined) ? json.log_level : DEFAULT_LOG_LEVEL;
global.__DNS_EXPIRE__ = (json.dns_expire !== undefined) ? json.dns_expire * 1e3 : DNS_DEFAULT_EXPIRE;
global.__ALL_CONFIG__ = json;
@ -216,7 +221,7 @@ export class Config {
static initServer(server) {
this.validateServer(server);
global.__TRANSPORT__ = server.transport;
global.__TRANSPORT__ = (server.transport !== undefined) ? server.transport : 'tcp';
global.__SERVER_HOST__ = server.host;
global.__SERVER_PORT__ = server.port;
global.__KEY__ = server.key;

@ -1,11 +1,13 @@
import cluster from 'cluster';
import EventEmitter from 'events';
import net from 'net';
import logger from './logger';
import {initLogger} from './logger';
import {Config} from './config';
import {Socket} from './socket';
import {Balancer} from './balancer';
let logger = null;
const nextId = (function () {
let i = 0;
return () => {
@ -40,7 +42,7 @@ export class Hub extends EventEmitter {
if (typeof config !== 'undefined') {
Config.init(config);
}
logger.level = __LOG_LEVEL__;
logger = initLogger({file: __LOG_PATH__, level: __LOG_LEVEL__});
this._hub = net.createServer();
this._hub.on('close', this.onClose.bind(this));
this._hub.on('connection', this.onConnect.bind(this));

@ -1,19 +1,25 @@
import winston from 'winston';
import {LOG_FILE_PATH, LOG_FILE_MAX_SIZE} from './constants';
const instance = new (winston.Logger)({
transports: [
new (winston.transports.Console)({
colorize: true,
prettyPrint: true
}),
new (winston.transports.File)({
filename: LOG_FILE_PATH,
maxsize: LOG_FILE_MAX_SIZE,
silent: ['test', 'debug'].includes(process.env.NODE_ENV)
})
]
});
const LOG_FILE_MAX_SIZE = 2 * 1024 * 1024; // 2MB
export const logger = instance;
export default instance;
let instance = null;
export function initLogger({file, level}) {
instance = new (winston.Logger)({
transports: [
new (winston.transports.Console)({
colorize: true,
prettyPrint: true
}),
new (winston.transports.File)({
filename: file,
maxsize: LOG_FILE_MAX_SIZE,
silent: ['test', 'debug'].includes(process.env.NODE_ENV)
})
]
});
instance.level = level;
return instance;
}
export default initLogger({file: 'tmp.log', level: 'error'});