winstonjs / winston

A logger for just about everything.
http://github.com/winstonjs/winston
MIT License
22.81k stars 1.81k forks source link

Moving logs which are above the maxsize limits to a custom directory, rather than keeping them in the current one #972

Open Sossenbinder opened 7 years ago

Sossenbinder commented 7 years ago

I think this would be a handy addition.

Currently, I'm storing a few logs in a certain folder. However, some of them log so much data, I am kind of forced to archive them from time to time in order to create a new one.

I like the possibility to let winston do this, by setting maxsize, however, I would really love to be able to move these old logs to a certain folder, instead of dumping everything in the current directory.

It just gets super messy, and I would prefer to just have the currently used logs in my log directory instead of having to search for them.

ne00346536 commented 7 years ago

@Sossenbinder can you please let me know if you find any solution on this.

Thanks, Naresh

Sossenbinder commented 7 years ago

I did find a solution. In the file.js file of the winston library, I added the following options below this.tailable:

this.autoStoreFolder = options.autoStoreFolder || false;

my file.prototype._checkMaxFilesTailable function was changed to this:

File.prototype._checkMaxFilesTailable = function (ext, basename, callback) {
  var tasks = [],
      self = this;

  var logPath = path.join(self.dirname, basename + ext);

  if(self.autoStoreFolder){
      try{
          fs.mkdirSync(self.autoStoreFolder);
      }
      catch(mkDirErr){
          if(mkDirErr.code != 'EEXIST'){
              self.autoStoreFolder = false;
          }
      }
  }

  if (!this.maxFiles)
    return;

  for (var x = this.maxFiles - 1; x > 0; x--) {
    tasks.push(function (i) {
      return function (cb) {

        var tmppath = path.join((self.autoStoreFolder ? self.autoStoreFolder : self.dirName), basename + (i - 1) + ext +
          (self.zippedArchive ? '.gz' : ''));

        if(self.autoStoreFolder && i == 1){
            tmppath = logPath;
        }
        fs.exists(tmppath, function (exists) {
          if (!exists) {
            return cb(null);
          }

          var newPath = path.join((self.autoStoreFolder ? self.autoStoreFolder : self.dirName), basename + i + ext + (self.zippedArchive ? '.gz' : ''));

          fs.rename(logPath, newPath, cb);
        });
      };
    }(x));
  }

  if (self.zippedArchive) {
    self._archive = path.join(self.dirname, basename + 1 + ext);
  }
  async.series(tasks, function (err) {
    fs.rename(
      path.join(self.dirname, basename + ext),
      path.join(self.dirname, basename + 1 + ext),
      callback
    );
  });
};

Afterwards, when creating a new (winston.transports.File), just add this option to the other ones:

autoStoreFolder: <path>

Now all files will be pasted to the path instead. I'm not really sure if this was the exact behaviour, as I didn't work with that code for months now, but I can recall it did work very well. It might also be possible that the given function here was already changed, I was using a code base from early January.

Hope it helps, though. Feel free to ask if you need clarification, I might be able to help. But as I said, I didn't touch that code in months.