Skip to content

Commit

Permalink
feat: Add log base dir extras options
Browse files Browse the repository at this point in the history
Makes it easier to parse user logging options with a different, default, base dir for log files
  • Loading branch information
FoxxMD committed Mar 20, 2024
1 parent eede5c8 commit 0c615da
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 51 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@foxxmd/logging",
"type": "module",
"version": "0.1.7",
"version": "0.1.8",
"repository": "https://github.com/foxxmd/logging",
"description": "A typed, opinionated, batteries-included, Pino-based logging solution for backend TS/JS projects",
"scripts": {
Expand Down
8 changes: 5 additions & 3 deletions src/loggers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,10 @@ export const loggerApp = (config: LogOptions | object = {}, extras?: LoggerAppEx
pretty = {},
destinations = [],
pino,
logBaseDir
} = extras || {};

const options = parseLogOptions(config);
const options = parseLogOptions(config, logBaseDir);
const streams: LogLevelStreamEntry[] = [
buildDestinationStdout(options.console, pretty),
...destinations
Expand Down Expand Up @@ -133,10 +134,11 @@ export const loggerAppRolling = async (config: LogOptions | object = {}, extras?
const {
pretty = {},
destinations = [],
pino
pino,
logBaseDir
} = extras || {};

const options = parseLogOptions(config);
const options = parseLogOptions(config, logBaseDir);
const streams: LogLevelStreamEntry[] = [
buildDestinationStdout(options.console, pretty),
...destinations
Expand Down
14 changes: 12 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,10 @@ export interface FileOptions extends PinoRollOptions, RollOptions {
*
* May also be specified using env LOG_PATH or a function that returns a string.
*
* If path is relative the absolute path will be derived from the current working directory.
* If path is relative the absolute path will be derived from `logBaseDir` (in `LoggerAppExtras`) which defaults to CWD
*
* @default 'CWD/logs/app.log'
* @default './logs/app.log'
* @see LoggerAppExtras
* */
path?: string | (() => string)
}
Expand Down Expand Up @@ -170,6 +171,15 @@ export interface LoggerAppExtras {
* Additional [Pino Log options](https://getpino.io/#/docs/api?id=options) that are passed to `pino()` on logger creation
* */
pino?: PinoLoggerOptions

/**
* The base path to use when parsing file logging options.
*
* @see FileOptions
*
* @default 'CWD'
* */
logBaseDir?: string
}

/**
Expand Down
102 changes: 59 additions & 43 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ const testConsoleLogger = (config?: object): [Logger, Transform, Transform] => {
return [logger, testStream, rawStream];
}

const testFileRollingLogger = async (config?: object) => {
const opts = parseLogOptions(config, process.cwd());
const testFileRollingLogger = async (config?: object, logBaseDir = process.cwd()) => {
const opts = parseLogOptions(config, logBaseDir);
const {
file: {
level,
Expand All @@ -68,8 +68,8 @@ const testFileRollingLogger = async (config?: object) => {
]);
};

const testFileLogger = async (config?: object) => {
const opts = parseLogOptions(config, process.cwd());
const testFileLogger = async (config?: object, logBaseDir = process.cwd()) => {
const opts = parseLogOptions(config, logBaseDir);
const {
file: {
path: logPath,
Expand All @@ -91,7 +91,8 @@ const testFileLogger = async (config?: object) => {
};

const testRollingAppLogger = async (config: LogOptions | object = {}, extras: LoggerAppExtras = {}): Promise<[Logger, Transform, Transform]> => {
const opts = parseLogOptions(config, process.cwd());
const {destinations = [], pretty, logBaseDir = process.cwd(), ...restExtras} = extras;
const opts = parseLogOptions(config, logBaseDir);
const testStream = new PassThrough();
const rawStream = new PassThrough();
const streams: LogLevelStreamEntry[] = [
Expand All @@ -108,16 +109,17 @@ const testRollingAppLogger = async (config: LogOptions | object = {}, extras: Lo
stream: rawStream
}
];
const {destinations = [], pretty, ...restExtras} = extras;
const logger = await loggerAppRolling({...opts, console: 'silent'}, {destinations: [...destinations, ...streams], pretty, ...restExtras});
const logger = await loggerAppRolling({...config, console: 'silent'}, {destinations: [...destinations, ...streams], pretty, logBaseDir, ...restExtras});
return [logger, testStream, rawStream];
}

const testAppLogger = (config: LogOptions | object = {}, extras: LoggerAppExtras = {}): [Logger, Transform, Transform] => {
const opts = parseLogOptions(config, process.cwd());
const {destinations = [], pretty = {}, logBaseDir = process.cwd(), ...restExtras} = extras;

const opts = parseLogOptions(config, logBaseDir);
const testStream = new PassThrough();
const rawStream = new PassThrough();
const {destinations = [], pretty = {}, ...restExtras} = extras;


const streams = [
buildDestinationStream(
Expand All @@ -134,8 +136,7 @@ const testAppLogger = (config: LogOptions | object = {}, extras: LoggerAppExtras
stream: rawStream
},
];

const logger = loggerApp({...opts, console: 'silent'}, {destinations: [...destinations, ...streams], pretty, ...restExtras});
const logger = loggerApp({...config, console: 'silent'}, {destinations: [...destinations, ...streams], pretty, logBaseDir, ...restExtras});
return [logger, testStream, rawStream];
}

Expand Down Expand Up @@ -219,6 +220,38 @@ describe('Transports', function () {
});
});

describe('File', async function () {

it('Does NOT write to file when file is false', async function () {
await withLocalTmpDir(async () => {
const logger = await testFileLogger({file: false});
logger.debug('Test');
await sleep(20);
expect(readdirSync('.').length).eq(0);
}, {unsafeCleanup: false});
});

it('Writes to file when file level is valid', async function () {
await withLocalTmpDir(async () => {
const logger = await testFileLogger({file: 'debug'});
logger.debug('Test');
await sleep(20);
expect(readdirSync('./logs').length).eq(1);
}, {unsafeCleanup: true});
});

it('Writes to specified file path', async function () {
await withLocalTmpDir(async () => {
const logger = await testFileLogger({file: { path: './myLogs.log' }});
logger.debug('Test');
await sleep(20);
const files = readdirSync('.');
expect(files.length).eq(1);
expect(files[0]).eq('myLogs.log')
}, {unsafeCleanup: true});
});
});

describe('Rolling File', async function () {

it('Does NOT write to file when file is false', async function () {
Expand Down Expand Up @@ -324,38 +357,6 @@ describe('Transports', function () {
});
});

describe('File', async function () {

it('Does NOT write to file when file is false', async function () {
await withLocalTmpDir(async () => {
const logger = await testFileLogger({file: false});
logger.debug('Test');
await sleep(20);
expect(readdirSync('.').length).eq(0);
}, {unsafeCleanup: false});
});

it('Writes to file when file level is valid', async function () {
await withLocalTmpDir(async () => {
const logger = await testFileLogger({file: 'debug'});
logger.debug('Test');
await sleep(20);
expect(readdirSync('./logs').length).eq(1);
}, {unsafeCleanup: true});
});

it('Writes to specified file path', async function () {
await withLocalTmpDir(async () => {
const logger = await testFileLogger({file: { path: './myLogs.log' }});
logger.debug('Test');
await sleep(20);
const files = readdirSync('.');
expect(files.length).eq(1);
expect(files[0]).eq('myLogs.log')
}, {unsafeCleanup: true});
});
});

describe('Combined', function() {
it('It writes to rolling file and console', async function () {
await withLocalTmpDir(async () => {
Expand Down Expand Up @@ -394,6 +395,21 @@ describe('Transports', function () {
expect(fileContents.match(/DEBUG\s*:\s*Test/)).is.not.null;
}, {unsafeCleanup: true});
});

it('It writes to file with a different base dir', async function () {
await withLocalTmpDir(async () => {
const [logger, testStream, rawStream] = testAppLogger({file: 'debug'}, {logBaseDir: path.resolve(process.cwd(), './config/logs')});
const race = Promise.race([
pEvent(testStream, 'data'),
sleep(10)
]) as Promise<Buffer>;
logger.debug('Test');
await sleep(20);
const res = await race;
const paths = readdirSync('./config/logs');
expect(paths.length).eq(1);
}, {unsafeCleanup: true});
});
});
});

Expand Down

0 comments on commit 0c615da

Please sign in to comment.