123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- 'use strict';
- const fs = require('fs');
- const path = require('path');
- const assert = require('assert');
- const mkdirp = require('mkdirp');
- const utility = require('utility');
- const depd = require('depd')('egg-logger');
- const Transport = require('./transport');
- const utils = require('../utils');
- /**
- * output log into file {@link Transport}。
- */
- class FileTransport extends Transport {
- /**
- * @class
- * @param {Object} options
- * - {String} file - file path
- * - {String} [level = INFO] - log level
- */
- constructor(options) {
- super(options);
- assert(this.options.file, 'should pass options.file');
- this._stream = null;
- this.reload();
- }
- get defaults() {
- return utils.assign(super.defaults, {
- file: null,
- level: 'INFO',
- });
- }
- /**
- * reload file stream
- */
- reload() {
- this._closeStream();
- this._stream = this._createStream();
- }
- /**
- * output log, see {@link Transport#log}
- * @param {String} level - log level
- * @param {Array} args - all arguments
- * @param {Object} meta - meta information
- */
- log(level, args, meta) {
- if (!this.writable) {
- const err = new Error(`${this.options.file} log stream had been closed`);
- console.error(err.stack);
- return;
- }
- const buf = super.log(level, args, meta);
- if (buf.length) {
- this._write(buf);
- }
- }
- /**
- * close stream
- */
- close() {
- this._closeStream();
- }
- /**
- * @deprecated
- */
- end() {
- depd('transport.end() is deprecated, use transport.close()');
- this.close();
- }
- /**
- * write stream directly
- * @param {Buffer|String} buf - log content
- * @private
- */
- _write(buf) {
- this._stream.write(buf);
- }
- /**
- * transport is writable
- * @return {Boolean} writable
- */
- get writable() {
- return this._stream && !this._stream.closed && this._stream.writable && !this._stream.destroyed;
- }
- /**
- * create stream
- * @return {Stream} return writeStream
- * @private
- */
- _createStream() {
- mkdirp.sync(path.dirname(this.options.file));
- const stream = fs.createWriteStream(this.options.file, { flags: 'a' });
- const onError = err => {
- console.error('%s ERROR %s [egg-logger] [%s] %s',
- utility.logDate(','), process.pid, this.options.file, err.stack);
- this.reload();
- console.warn('%s WARN %s [egg-logger] [%s] reloaded', utility.logDate(','), process.pid, this.options.file);
- };
- // only listen error once because stream will reload after error
- stream.once('error', onError);
- stream._onError = onError;
- return stream;
- }
- /**
- * close stream
- * @private
- */
- _closeStream() {
- if (this._stream) {
- this._stream.end();
- this._stream.removeListener('error', this._stream._onError);
- this._stream = null;
- }
- }
- }
- module.exports = FileTransport;
|