rotating-file-stream icon indicating copy to clipboard operation
rotating-file-stream copied to clipboard

[bug] File not rotating when using a generator function

Open JosuerBague opened this issue 1 year ago • 6 comments

Hey there, I'm trying to use you package for my pino logger like so:

import { Logger as PinoLogger } from './logger.package';
const rfsa = require('rotating-file-stream');

const pad = (num: number) => (num > 9 ? ""  : "0") + num;

const generator = () => {
    const time = new Date();

    const year = time.getFullYear();
    const month = pad(time.getMonth() + 1);
    const day = pad(time.getDate());
    const hour = pad(time.getHours());

    return `application-${year}-${month}-${day}-${hour}.log`;
}

const stream = rfsa.createStream(generator, {
    interval: '15s',
    compress: true,
    path: 'logs'
})

const logger = new PinoLogger(stream);

export { logger };
export type { ILogger } from './libs/interfaces/interfaces';

This doesn't rotate the file. But when I provide a filename directly like so, it does:

const stream = rfsa.createStrearm('sample.log', { interval: '15s', compress: true, path: 'logs' })

JosuerBague avatar Mar 07 '24 13:03 JosuerBague

Your filename generator doesn't accepts parameters...

Please refer to the documentation.

If this solves the problem, feel free to close the issue.

iccicci avatar Mar 07 '24 18:03 iccicci

I tried using the filename generator in the documentation but it still wouldn't rotate the file. Had it set to rotate at 10s.

const generator = (time: Date, index: number) => {
    if (!time) return "file.log";
  
    const month = time.getFullYear() + "" + pad(time.getMonth() + 1);
    const day = pad(time.getDate());
    const hour = pad(time.getHours());
    const minute = pad(time.getMinutes());
  
    return `${month}/${month}${day}-${hour}${minute}-${index}-file.log`;
  };



const stream = rfsa.createStream(generator, {
    interval: '10s',
    compress: true,
})

JosuerBague avatar Mar 08 '24 08:03 JosuerBague

I suggest you to follow error and warning events.

stream.on("error", console.log);
stream.on("warning", console.log);

More than this there some known problems when rfs.createStream is called twice with the same configuration; I suggest you to ensure that piece of code runs only once.

iccicci avatar Mar 08 '24 08:03 iccicci

Hey there, I'm trying to use you package for my pino logger like so:

import { Logger as PinoLogger } from './logger.package';
const rfsa = require('rotating-file-stream');

const pad = (num: number) => (num > 9 ? ""  : "0") + num;

const generator = () => {
    const time = new Date();

    const year = time.getFullYear();
    const month = pad(time.getMonth() + 1);
    const day = pad(time.getDate());
    const hour = pad(time.getHours());

    return `application-${year}-${month}-${day}-${hour}.log`;
}

const stream = rfsa.createStream(generator, {
    interval: '15s',
    compress: true,
    path: 'logs'
})

const logger = new PinoLogger(stream);

export { logger };
export type { ILogger } from './libs/interfaces/interfaces';

This doesn't rotate the file. But when I provide a filename directly like so, it does:

const stream = rfsa.createStrearm('sample.log', { interval: '15s', compress: true, path: 'logs' })

The same problem, try to remove compress option.

nodermann2 avatar Jun 16 '24 10:06 nodermann2

Hi @nodermann ,

Also your filename generator doesn't accepts parameters...

It must accept two parameters. Please refer to the documentation.

iccicci avatar Jun 16 '24 13:06 iccicci

Also compress: true probably works only on Linux, if you are using other operating systems... butter to use compress: "gzip".

iccicci avatar Jun 16 '24 13:06 iccicci

I can confirm that rotation is not working, at least on Windows platform. Using typescript, generator is defined like this: const generator = (time: number | Date, index?: number) => { ... } Both time and index are null and undefined during the call of the generator, so we can't parse time and create rotated file path name. Using everything from your example but on typescript.

Gredys avatar Oct 07 '24 22:10 Gredys

In your class RotatingFileStream generator is called without any time. So we can't rotate file during initialization.

class RotatingFileStream extends stream_1.Writable {
    constructor(generator, options) {
        const { encoding, history, maxFiles, maxSize, path } = options;
        super({ decodeStrings: true, defaultEncoding: encoding });
        this.createGzip = zlib_1.createGzip;
        this.exec = child_process_1.exec;
--->    this.filename = path + generator(null);

Don't know what u were trying to do with generator. But its logical to pass time and index (0 if no prev index) to generator always and not optionally. Otherwise its not usable at all.

Solution:

  1. Make a note in documentation that its not going to work for initial call and user must use its own time.
  2. Do what I proposed above. Pass time and index always in any way.

Gredys avatar Oct 07 '24 22:10 Gredys

Using such code as example:

const pad = (num: number) => (num > 9 ? "" : "0") + num;
const generator = (time: number | Date, index?: number) => {
    console.log(`>>> generator(${time}, ${index})`);
    if (!time || !(time instanceof Date)) time = new Date()
    if (!index) index = 0

    const year = time.getFullYear();
    const month = pad(time.getMonth() + 1);
    const day = pad(time.getDate());

    return `./logs/${year}-${month}-${day}-${index}-test.log`;
};
const stream = createStream(generator, {
    size: "10M",
    interval: "1d",
});
stream.on("error", console.log);
stream.on("warning", console.log);

If run it few times it always gonna print:

>>> generator(null, undefined)

No matter if file already exists. Its just always null for time and undefined for index.

Running system: Windows 11 (latest update) Node: 20.17.0

Ask if u need more information.

Gredys avatar Oct 07 '24 23:10 Gredys

Hi @Gredys , did you checked this part of the README?

The filename generator function must return:

  • with time === null the not rotated filename
  • with time != null the rotated filename

iccicci avatar Oct 08 '24 10:10 iccicci

Hello @iccicci ! But it never asks for the rotated filename (didn't checked dayli rolling cos I wasn't able to force it use index) What I need to do if I want log file to be rotated on initialization? I.e. on every launch of application log file would be incremented by index without using old log file from previous application run?

Gredys avatar Oct 08 '24 13:10 Gredys

Hello @Gredys ,

does initialRotation help?

iccicci avatar Oct 08 '24 15:10 iccicci

Using such code as example:

const pad = (num: number) => (num > 9 ? "" : "0") + num;
const generator = (time: number | Date, index?: number) => {
    console.log(`>>> generator(${time}, ${index})`);
    if (!time || !(time instanceof Date)) time = new Date()
    if (!index) index = 0

By the way, this is wrong, please check better the README

iccicci avatar Oct 08 '24 15:10 iccicci

Hello @iccicci I copied you the latest version of the code that I had. And no, initialRotation didn't helped.

The inial code whas 100% from readme except that I added types so Typescript won't cringe + console.log line, which is not changing anything in logic.

What I wanted, but I think its not possible in current setup, to rotate log files upon startup. For example application crashed. After startup log file will be appended and crash would move up, adding more and more information to process during inpection of the problem. It possible ofc to separate info/error log files but it still won't rotate upon startup.

Anyway, I started using another library. Thank you for your time. Have a nice day.

Gredys avatar Oct 10 '24 11:10 Gredys

None of the code snippets reported in this issue respect the specifications.

iccicci avatar Oct 11 '24 13:10 iccicci