Skip to content

Commit

Permalink
set version to 1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
edeustace committed Mar 27, 2017
2 parents fe4b2dd + 2d5b613 commit a4b8796
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 91 deletions.
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,53 @@ let logger = buildLogger();

```

The logger will be named after the module that called `buildLogger`. So if your file was called `utils/index.js` the logger category will be `[utils]`.

### Configuration

By default logging targets the console with a `level` of `info`. You can change this by calling `init`.

```javascript

import {init} from 'log-factory';

/**
* Will only affect loggers created after the call to init.
* It is advisable to call this at the start of your app
* before any log instances have been created.
*/
init({
console: false,
file: 'my-log.log',
log: 'INFO'
});
```

The options for `init` are:

* console - true/false, default: `true`
* file - direct logs to a file, default: `undefined`
* log - string|json-string|path-to-json-file, default: `'info'`
* string - error|warn|info|debug|verbose|silly
* json-string - a string that can be parsed as json
* path-to-json - a path to a json file


> If you want to disable logging you can pass in: `{console: false, file: undefined}`
If using json you can define levels for different categories. For example:

```json
{
"app": "info",
"item" : "debug"
}
```

`default` is a special category that will be applied if the category can't be found.

To see the available categories, first run the log with level `silly`, the name in the square brackets is the category.

# test

`npm test`
Expand Down
6 changes: 5 additions & 1 deletion lib/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/// <reference types="winston" />
import * as winston from 'winston';
export declare const setDefaultLevel: (l: any) => void;
export declare const init: (log: any) => void;
export declare const init: (opts: {
console: boolean;
file?: string;
log?: any;
}) => void;
export declare const getLogger: (id: string) => winston.LoggerInstance;
export declare const fileLogger: (filename: any) => winston.LoggerInstance;
export declare function buildLogger(): winston.LoggerInstance;
56 changes: 37 additions & 19 deletions lib/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "log-factory",
"version": "0.0.1",
"version": "1.0.0",
"author": "",
"main": "lib/index.js",
"types": "lib/index.d.ts",
Expand Down
71 changes: 52 additions & 19 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,58 @@ import * as winston from 'winston';

//levels: error > warn > info > verbose > debug > silly

type LogFactoryOpts = {
console: boolean,
file?: string,
log?: any
};

const moduleOpts = {
console: true,
file: null,
log: 'info'
};

let config = {
'default': 'info'
};

const timestamp = () => {
var now = new Date();
return dateFormat(now, 'HH:MM:ss.l');
};

const consoleTransport = (label: string): winston.TransportInstance => {
return new (winston.transports.Console)({
colorize: true,
label: label,
timestamp
});
};

const fileTransport = (label: string): winston.TransportInstance => {
return new winston.transports.File({
colorize: false,
json: false,
filename: moduleOpts.file,
label,
timestamp
});
};

const mkLogConfig = (label: string, level: string) => {
return {
level: level,
transports: [
new (winston.transports.Console)({
colorize: true,
label: label,
timestamp: () => {
var now = new Date();
return dateFormat(now, 'HH:MM:ss.l');
}
})
]
};

const addConsole = !moduleOpts.file && moduleOpts.console;

const transports: winston.TransportInstance[] = [
addConsole ? consoleTransport(label) : null,
moduleOpts.file ? fileTransport(label) : null
].filter(t => t !== null);


return { level, transports };
};

const logger = addLogger('LOG_FACTORY');

const setConfig = (cfg) => {
config = _.merge({}, config, cfg);
Expand All @@ -40,17 +71,20 @@ const isLogLevel = (l): Boolean => _.includes(['error', 'warn', 'info', 'verbose

export const setDefaultLevel = (l) => {
config = _.merge(config, { 'default': l });
logger.debug('default level now: ', config['default']);
_.forEach(winston.loggers.loggers, (value, key) => {
let logger = winston.loggers.get(key);
let cfg = mkLogConfig(key, config['default']);
logger.configure(cfg);
});
};

export const init = (log): void => {
export const init = (opts: LogFactoryOpts): void => {

moduleOpts.console = opts.console;
moduleOpts.file = opts.file;
moduleOpts.log = opts.log || moduleOpts.log;

logger.debug('init: ', log);
const { log } = moduleOpts;

if (!log) {
return;
Expand All @@ -63,7 +97,6 @@ export const init = (log): void => {
} else {
try {
let config = JSON.parse(log);
logger.debug('parsed log: ', log);
setConfig(config);
} catch (e) {
if (fs.existsSync(log)) {
Expand All @@ -76,8 +109,8 @@ export const init = (log): void => {
}
};


function addLogger(label, level?: string): winston.LoggerInstance {

level = level ? level : config['default'] || 'info';
let cfg = mkLogConfig(label, level);
let logger;
Expand Down
165 changes: 114 additions & 51 deletions test/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ describe('log-factory', () => {
deps = {
'winston': {
transports: {
Console: stub().returns(instance)
Console: stub().returns(instance),
File: stub().returns(instance)
},
loggers: {
get: stub().returns(instance),
Expand All @@ -32,84 +33,146 @@ describe('log-factory', () => {
},
'stack-trace': {}
}

logFactory = proxyquire('../lib', deps);
});

describe('init', () => {

beforeEach(() => {
logFactory.setDefaultLevel = stub();
});

it('inits via a level', () => {
logFactory.init('silly');
assert.calledWith(logFactory.setDefaultLevel, 'silly');
});
describe('disabled', () => {
beforeEach(() => {
logFactory.init({ console: false, file: undefined });
logFactory.fileLogger('test');
});

let prepLoggers = (has) => {
deps.winston.loggers.has.withArgs('app').returns(has);
deps.winston.loggers.get.withArgs('app').returns(instance);
deps.winston.loggers.add.withArgs('app').returns(instance);
logFactory.init({ app: 'silly' });
}
it('does not create a Console transport', () => {
assert.notCalled(deps.winston.transports.Console);
});

it('does not create a File transport', () => {
assert.notCalled(deps.winston.transports.File)
});
});

let assertSetConfig = (run) => {
describe('console', () => {

it('calls logger.has', () => {
run();
assert.calledWith(deps.winston.loggers.has, 'app');
beforeEach(() => {
logFactory.init({ console: true, file: undefined });
logFactory.fileLogger('test');
});

it('calls logger.configure', () => {
run();
assert.calledWith(instance.configure, {
level: 'silly',
transports: match.array
it('creates a new Console transport', () => {
assert.calledWith(deps.winston.transports.Console, {
colorize: true,
label: 'test',
timestamp: match.func
});
});

it('does not create a File transport', () => {
assert.notCalled(deps.winston.transports.File)
});
});

describe('file', () => {

it('calls logger.add if there is no logger', () => {
run(false);
assert.calledWith(deps.winston.loggers.add, 'app', {});
beforeEach(() => {
logFactory.init({ console: false, file: 'my-file.log' });
logFactory.fileLogger('test');
});

it('calls logger.get if there is a logger', () => {
run(true);
assert.calledWith(deps.winston.loggers.get, 'app');
it('does not create a new Console transport', () => {
assert.notCalled(deps.winston.transports.Console)
});

}
it('creates a new File transport', () =>

assert.calledWith(deps.winston.transports.File, {
filename: 'my-file.log',
colorize: false,
json: false,
label: 'test',
timestamp: match.func
}));
});


describe('with object', () => {
describe('log', () => {

let run = (has) => {
prepLoggers(has);
beforeEach(() => {
logFactory.setDefaultLevel = stub();
});

it('inits via a level', () => {
logFactory.init({
log: 'silly'
});
assert.calledWith(logFactory.setDefaultLevel, 'silly');
});

let prepLoggers = (has) => {
deps.winston.loggers.has.withArgs('app').returns(has);
deps.winston.loggers.get.withArgs('app').returns(instance);
deps.winston.loggers.add.withArgs('app').returns(instance);
logFactory.init({ app: 'silly' });
}
assertSetConfig(run);
});

describe('with json string', () => {

let run = (has) => {
prepLoggers(has);
logFactory.init(JSON.stringify({ app: 'silly' }));
}
assertSetConfig(run);
});
let assertSetConfig = (run) => {

it('calls logger.has', () => {
run();
assert.calledWith(deps.winston.loggers.has, 'app');
});

it('calls logger.configure', () => {
run();
assert.calledWith(instance.configure, {
level: 'silly',
transports: match.array
});
});


it('calls logger.add if there is no logger', () => {
run(false);
assert.calledWith(deps.winston.loggers.add, 'app', {});
});

it('calls logger.get if there is a logger', () => {
run(true);
assert.calledWith(deps.winston.loggers.get, 'app');
});

describe('with path to file', () => {
let run = (has) => {
prepLoggers(has);
deps.fs.existsSync.returns(true);
deps.fs.readFileSync.returns(JSON.stringify({ app: 'silly' }));
logFactory.init('path/to/file');
}

assertSetConfig(run);
describe('with object', () => {

let run = (has) => {
prepLoggers(has);
logFactory.init({ log: { app: 'silly' } });
}
assertSetConfig(run);
});

describe('with json string', () => {

let run = (has) => {
prepLoggers(has);
logFactory.init({ log: JSON.stringify({ app: 'silly' }) });
}
assertSetConfig(run);
});

describe('with path to file', () => {
let run = (has) => {
prepLoggers(has);
deps.fs.existsSync.returns(true);
deps.fs.readFileSync.returns(JSON.stringify({ app: 'silly' }));
logFactory.init({ log: 'path/to/file' });
}

assertSetConfig(run);
});
});
});
});

0 comments on commit a4b8796

Please sign in to comment.