[READ-ONLY] Mirror of https://github.com/FoxxMD/logging. A typed, opinionated, batteries-included, Pino-based logging solution for backend TS/JS projects foxxmd.github.io/logging
child-logger logging logging-library nodejs pinojs typescript-library
0

Configure Feed

Select the types of activity you want to include in your feed.

tests: Add tests for sync/async file logging separately and combined with stream

FoxxMD (Mar 1, 2024, 3:33 PM EST) aa8d87f6 341357c0

+153 -13
+2 -1
.mocharc.json
··· 1 1 { 2 2 "reporter": "dot", 3 3 "extension": "ts", 4 - "import": "tsx/esm" 4 + "import": "tsx/esm", 5 + "exit": true 5 6 }
+151 -12
tests/index.test.ts
··· 7 7 import {LogData, LOG_LEVELS} from "../src/types.js"; 8 8 import withLocalTmpDir from 'with-local-tmp-dir'; 9 9 import {readdirSync,} from 'node:fs'; 10 - import {buildDestinationStream, buildDestinationRollingFile} from "../src/destinations.js"; 10 + import {buildDestinationStream, buildDestinationRollingFile, buildDestinationFile} from "../src/destinations.js"; 11 11 import {buildLogger} from "../src/loggers.js"; 12 + import {readFileSync} from "fs"; 13 + import path from "path"; 12 14 13 15 14 16 const testConsoleLogger = (config?: object): [Logger, Transform, Transform] => { ··· 32 34 return [logger, testStream, rawStream]; 33 35 } 34 36 35 - const testFileLogger = async (config?: object) => { 37 + const testFileRollingLogger = async (config?: object, logPath: string = '.') => { 36 38 const opts = parseLogOptions(config); 37 39 const streamEntry = await buildDestinationRollingFile( 38 40 opts.file, 39 41 { 40 - path: '.', 42 + path: logPath, 43 + ...opts 44 + } 45 + ); 46 + return buildLogger('debug', [ 47 + streamEntry 48 + ]); 49 + }; 50 + 51 + const testFileLogger = async (config?: object, logPath: string = './app.log') => { 52 + const opts = parseLogOptions(config); 53 + const streamEntry = buildDestinationFile( 54 + opts.file, 55 + { 56 + path: logPath, 41 57 ...opts 42 58 } 43 59 ); ··· 45 61 streamEntry 46 62 ]); 47 63 }; 64 + 65 + const testRollingAppLogger = async (config?: object, logPath: string = '.'): Promise<[Logger, Transform, Transform]> => { 66 + const opts = parseLogOptions(config); 67 + const testStream = new PassThrough(); 68 + const rawStream = new PassThrough(); 69 + const streamEntry = await buildDestinationRollingFile( 70 + opts.file, 71 + { 72 + path: logPath, 73 + ...opts 74 + } 75 + ); 76 + const logger = buildLogger('debug', [ 77 + buildDestinationStream( 78 + opts.console, 79 + { 80 + destination: testStream, 81 + colorize: false, 82 + ...opts 83 + } 84 + ), 85 + { 86 + level: opts.console, 87 + stream: rawStream 88 + }, 89 + buildDestinationStream(opts.console, { destination: 1, colorize: false }), 90 + streamEntry 91 + ]); 92 + return [logger, testStream, rawStream]; 93 + } 94 + 95 + const testAppLogger = (config?: object, logPath: string = '.'): [Logger, Transform, Transform] => { 96 + const opts = parseLogOptions(config); 97 + const testStream = new PassThrough(); 98 + const rawStream = new PassThrough(); 99 + const streamEntry = buildDestinationFile( 100 + opts.file, 101 + { 102 + path: logPath, 103 + ...opts 104 + } 105 + ); 106 + const logger = buildLogger('debug', [ 107 + buildDestinationStream( 108 + opts.console, 109 + { 110 + destination: testStream, 111 + colorize: false, 112 + ...opts 113 + } 114 + ), 115 + { 116 + level: opts.console, 117 + stream: rawStream 118 + }, 119 + buildDestinationStream(opts.console, { destination: 1, colorize: false }), 120 + streamEntry 121 + ]); 122 + return [logger, testStream, rawStream]; 123 + } 48 124 49 125 describe('Config Parsing', function () { 50 126 ··· 126 202 }); 127 203 }); 128 204 205 + describe('Rolling File', async function () { 206 + 207 + it('Does NOT write to file when file is false', async function () { 208 + await withLocalTmpDir(async () => { 209 + const logger = await testFileRollingLogger({file: false}); 210 + logger.debug('Test'); 211 + await sleep(20); 212 + expect(readdirSync('.').length).eq(0); 213 + }, {unsafeCleanup: false}); 214 + }); 215 + 216 + it('Writes to file when file level is valid', async function () { 217 + await withLocalTmpDir(async () => { 218 + const logger = await testFileRollingLogger({file: 'debug'}); 219 + logger.debug('Test'); 220 + await sleep(20); 221 + expect(readdirSync('.').length).eq(1); 222 + }, {unsafeCleanup: true}); 223 + }); 224 + }); 225 + 129 226 describe('File', async function () { 130 227 131 228 it('Does NOT write to file when file is false', async function () { 132 229 await withLocalTmpDir(async () => { 133 - const logger = await testFileLogger({file: false}); 230 + const logger = await testFileLogger({file: false}); 134 231 logger.debug('Test'); 135 232 await sleep(20); 136 233 expect(readdirSync('.').length).eq(0); 137 234 }, {unsafeCleanup: false}); 138 235 }); 139 236 140 - // it('Writes to file when file level is valid', async function () { 141 - // await withLocalTmpDir(async () => { 142 - // const logger = await testFileLogger({file: 'debug'}); 143 - // logger.debug('Test'); 144 - // await sleep(20); 145 - // expect(readdirSync('.').length).eq(1); 146 - // }, {unsafeCleanup: true}); 147 - // }); 237 + it('Writes to file when file level is valid', async function () { 238 + await withLocalTmpDir(async () => { 239 + const logger = await testFileLogger({file: 'debug'}); 240 + logger.debug('Test'); 241 + await sleep(20); 242 + expect(readdirSync('.').length).eq(1); 243 + }, {unsafeCleanup: true}); 244 + }); 245 + }); 246 + 247 + describe('Combined', function() { 248 + it('It writes to rolling file and console', async function () { 249 + await withLocalTmpDir(async () => { 250 + const logPath = './logs'; 251 + const [logger, testStream, rawStream] = await testRollingAppLogger({file: 'debug'}, logPath); 252 + const race = Promise.race([ 253 + pEvent(testStream, 'data'), 254 + sleep(10) 255 + ]) as Promise<Buffer>; 256 + logger.debug('Test'); 257 + await sleep(20); 258 + const res = await race; 259 + expect(res).to.not.be.undefined; 260 + expect(res.toString()).to.include('DEBUG: Test'); 261 + const paths = readdirSync(logPath); 262 + expect(paths.length).eq(1); 263 + const fileContents = readFileSync(path.resolve(logPath, paths[0])).toString(); 264 + expect(fileContents).includes('DEBUG: Test'); 265 + }, {unsafeCleanup: true}); 266 + }); 267 + 268 + it('It writes to file and console', async function () { 269 + await withLocalTmpDir(async () => { 270 + const logPath = './logs/app.log'; 271 + const [logger, testStream, rawStream] = testAppLogger({file: 'debug'}, logPath); 272 + const race = Promise.race([ 273 + pEvent(testStream, 'data'), 274 + sleep(10) 275 + ]) as Promise<Buffer>; 276 + logger.debug('Test'); 277 + await sleep(20); 278 + const res = await race; 279 + expect(res).to.not.be.undefined; 280 + expect(res.toString()).to.include('DEBUG: Test'); 281 + const paths = readdirSync('./logs'); 282 + expect(paths.length).eq(1); 283 + const fileContents = readFileSync(path.resolve('./logs', paths[0])).toString(); 284 + expect(fileContents).includes('DEBUG: Test'); 285 + }, {unsafeCleanup: true}); 286 + }); 148 287 }); 149 288 }); 150 289