@apolitical/logger 1.0.2 → 2.0.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/README.md +5 -4
- package/package.json +21 -21
- package/src/config.js +1 -1
- package/src/container.js +0 -6
- package/src/index.js +11 -0
- package/src/services/logger.service.js +22 -10
- package/.gitlab-ci.yml +0 -22
- package/.husky/pre-commit +0 -6
- package/index.js +0 -5
- package/test/unit/logger/__snapshots__/logger.spec.js.snap +0 -27
- package/test/unit/logger/container.js +0 -25
- package/test/unit/logger/logger.helper.js +0 -43
- package/test/unit/logger/logger.spec.js +0 -122
- package/test/unit/logger/stubs/winston.google.stub.js +0 -5
- package/test/unit/logger/stubs/winston.stub.js +0 -14
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
|
|
9
|
+
## [2.0.0] - 2022-01-18
|
|
10
|
+
### Changed
|
|
11
|
+
- Dependencies
|
|
12
|
+
- Node version
|
|
13
|
+
- Labels definition instead of metadata
|
|
14
|
+
### Added
|
|
15
|
+
- Logger middleware
|
|
16
|
+
|
|
8
17
|
## [1.0.2] - 2021-07-08
|
|
9
18
|
### Updated
|
|
10
19
|
- Dependencies
|
package/README.md
CHANGED
|
@@ -41,14 +41,15 @@ const childLogger = logger.where(__filename, 'debugging');
|
|
|
41
41
|
childLogger.debug('Accessed:', { count: 0 });
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
### The
|
|
44
|
+
### The _labels_ object
|
|
45
45
|
|
|
46
|
-
And also, the
|
|
46
|
+
And also, the labels allow you to keep extra info along the logger journey:
|
|
47
47
|
|
|
48
48
|
```
|
|
49
49
|
const opts = {
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
labels: {
|
|
51
|
+
name: 'apolitical-service',
|
|
52
|
+
version: 'v1.0.0'
|
|
52
53
|
}
|
|
53
54
|
};
|
|
54
55
|
const logger = apoliticalLogger(opts);
|
package/package.json
CHANGED
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@apolitical/logger",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-beta.3",
|
|
4
4
|
"description": "Node.js module to expose Apolitical's logger service",
|
|
5
5
|
"author": "Apolitical Group Limited <engineering@apolitical.co>",
|
|
6
|
-
"contributors": [
|
|
7
|
-
"Anouska Hopkins <anouska.hopkins@apolitical.co>",
|
|
8
|
-
"Antonio Cordasco <antonio.cordasco@apolitical.co>",
|
|
9
|
-
"Dorothy Yau <dorothy.yau@apolitical.co>",
|
|
10
|
-
"Laura Hanna-White <laura.hanna-white@apolitical.co>",
|
|
11
|
-
"Fatimat Gbajabiamila <fatimat.gbajabiamila@apolitical.co>",
|
|
12
|
-
"Renzo Rozza <renzo.rozza@apolitical.co>",
|
|
13
|
-
"Rihards Jukna <rihards.jukna@apolitical.co>"
|
|
14
|
-
],
|
|
15
6
|
"license": "MIT",
|
|
16
|
-
"main": "index.js",
|
|
7
|
+
"main": "src/index.js",
|
|
8
|
+
"files": [
|
|
9
|
+
"src"
|
|
10
|
+
],
|
|
17
11
|
"scripts": {
|
|
18
12
|
"test": "jest --bail --runInBand",
|
|
19
13
|
"integration-test": "jest --bail --runInBand",
|
|
@@ -30,19 +24,20 @@
|
|
|
30
24
|
"Node Modules"
|
|
31
25
|
],
|
|
32
26
|
"dependencies": {
|
|
33
|
-
"@google-cloud/logging-winston": "4.1.
|
|
34
|
-
"awilix": "
|
|
35
|
-
"winston": "3.
|
|
27
|
+
"@google-cloud/logging-winston": "4.1.1",
|
|
28
|
+
"awilix": "6.0.0",
|
|
29
|
+
"winston": "3.4.0"
|
|
36
30
|
},
|
|
37
31
|
"devDependencies": {
|
|
38
|
-
"@apolitical/eslint-config": "0.0.
|
|
39
|
-
"audit-ci": "
|
|
40
|
-
"husky": "7.0.
|
|
41
|
-
"jest": "27.
|
|
42
|
-
"
|
|
32
|
+
"@apolitical/eslint-config": "1.0.0-beta.0",
|
|
33
|
+
"audit-ci": "5.1.2",
|
|
34
|
+
"husky": "7.0.4",
|
|
35
|
+
"jest": "27.4.7",
|
|
36
|
+
"jest-junit": "13.0.0",
|
|
37
|
+
"lint-staged": "12.1.7"
|
|
43
38
|
},
|
|
44
39
|
"engines": {
|
|
45
|
-
"node": ">=
|
|
40
|
+
"node": ">=16.13.2"
|
|
46
41
|
},
|
|
47
42
|
"eslintConfig": {
|
|
48
43
|
"extends": "@apolitical/eslint-config/base.config"
|
|
@@ -67,7 +62,12 @@
|
|
|
67
62
|
"testEnvironment": "node",
|
|
68
63
|
"testTimeout": 60000,
|
|
69
64
|
"maxConcurrency": 1,
|
|
70
|
-
"maxWorkers": 1
|
|
65
|
+
"maxWorkers": 1,
|
|
66
|
+
"reporters": [
|
|
67
|
+
"default",
|
|
68
|
+
"jest-junit"
|
|
69
|
+
],
|
|
70
|
+
"testResultsProcessor": "jest-junit"
|
|
71
71
|
},
|
|
72
72
|
"lint-staged": {
|
|
73
73
|
"*.js": "eslint --cache --fix --ignore-path .gitignore",
|
package/src/config.js
CHANGED
package/src/container.js
CHANGED
|
@@ -2,28 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
// External Modules
|
|
4
4
|
const { createContainer, asValue, asFunction } = require('awilix');
|
|
5
|
-
|
|
6
5
|
const path = require('path');
|
|
7
6
|
const winston = require('winston');
|
|
8
7
|
const winstonGoogle = require('@google-cloud/logging-winston');
|
|
9
|
-
|
|
10
8
|
// Configuration
|
|
11
9
|
const config = require('./config');
|
|
12
|
-
|
|
13
10
|
// Services
|
|
14
11
|
const loggerService = require('./services/logger.service');
|
|
15
12
|
|
|
16
13
|
const container = createContainer();
|
|
17
14
|
container.register({
|
|
18
15
|
// External Modules
|
|
19
|
-
|
|
20
16
|
path: asValue(path),
|
|
21
17
|
winston: asValue(winston),
|
|
22
18
|
winstonGoogle: asValue(winstonGoogle),
|
|
23
|
-
|
|
24
19
|
// Configuration
|
|
25
20
|
config: asValue(config),
|
|
26
|
-
|
|
27
21
|
// Services
|
|
28
22
|
loggerService: asFunction(loggerService).singleton(),
|
|
29
23
|
});
|
package/src/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { resolve } = require('./container');
|
|
4
|
+
|
|
5
|
+
const winstonGoogle = resolve('winstonGoogle');
|
|
6
|
+
const loggerService = resolve('loggerService');
|
|
7
|
+
|
|
8
|
+
module.exports = {
|
|
9
|
+
createLogger: loggerService,
|
|
10
|
+
loggerMiddleware: winstonGoogle.express.makeMiddleware,
|
|
11
|
+
};
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module.exports =
|
|
4
4
|
({ path, winston, winstonGoogle, config }) =>
|
|
5
|
-
({ logLevel = 'info',
|
|
6
|
-
const { LOGGING_LEVELS,
|
|
5
|
+
({ logLevel = 'info', labels = {} }) => {
|
|
6
|
+
const { LOGGING_LEVELS, ALLOWED_LABELS } = config.LOGGER;
|
|
7
7
|
const { ERROR_OPTIONS, COMBINED_OPTIONS } = config.LOGGER.TRANSPORTS.FILE;
|
|
8
8
|
const { CLOUD_FUNCTION, CREDENTIALS } = config.GOOGLE;
|
|
9
9
|
|
|
10
|
-
function
|
|
11
|
-
return
|
|
12
|
-
if (
|
|
13
|
-
acc[cv] =
|
|
10
|
+
function allowedLabels() {
|
|
11
|
+
return ALLOWED_LABELS.reduce((acc, cv) => {
|
|
12
|
+
if (labels[cv]) {
|
|
13
|
+
acc[cv] = labels[cv];
|
|
14
14
|
}
|
|
15
15
|
return acc;
|
|
16
16
|
}, {});
|
|
@@ -27,7 +27,15 @@ module.exports =
|
|
|
27
27
|
const transports = [];
|
|
28
28
|
if (config.NODE_ENV === 'production') {
|
|
29
29
|
if (CLOUD_FUNCTION || CREDENTIALS) {
|
|
30
|
-
transports.push(
|
|
30
|
+
transports.push(
|
|
31
|
+
new winstonGoogle.LoggingWinston({
|
|
32
|
+
labels,
|
|
33
|
+
serviceContext: {
|
|
34
|
+
service: labels.name,
|
|
35
|
+
version: labels.version,
|
|
36
|
+
},
|
|
37
|
+
}),
|
|
38
|
+
);
|
|
31
39
|
} else {
|
|
32
40
|
transports.push(new winston.transports.Console());
|
|
33
41
|
}
|
|
@@ -52,14 +60,18 @@ module.exports =
|
|
|
52
60
|
};
|
|
53
61
|
return acc;
|
|
54
62
|
},
|
|
55
|
-
{
|
|
63
|
+
{
|
|
64
|
+
add: logger.add,
|
|
65
|
+
labels: logger.labels,
|
|
66
|
+
transports: logger.transports,
|
|
67
|
+
},
|
|
56
68
|
);
|
|
57
69
|
}
|
|
58
70
|
|
|
59
71
|
function createWrapper(logger) {
|
|
60
72
|
function where(filePath, method) {
|
|
61
73
|
const file = path.basename(filePath);
|
|
62
|
-
const childLogger = logger.child({
|
|
74
|
+
const childLogger = logger.child({ labels: { file, method } });
|
|
63
75
|
return createWrapper(childLogger);
|
|
64
76
|
}
|
|
65
77
|
function write(message) {
|
|
@@ -70,10 +82,10 @@ module.exports =
|
|
|
70
82
|
}
|
|
71
83
|
|
|
72
84
|
const loggerInstance = winston.createLogger({
|
|
85
|
+
labels: allowedLabels(),
|
|
73
86
|
level: logLevel,
|
|
74
87
|
levels: loggingLevels(),
|
|
75
88
|
format: loggerFormat(),
|
|
76
|
-
defaultMeta: allowedMetadata(),
|
|
77
89
|
transports: loggerTransports(),
|
|
78
90
|
});
|
|
79
91
|
|
package/.gitlab-ci.yml
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# External jobs
|
|
2
|
-
include:
|
|
3
|
-
- project: 'apolitical/templates/gitlab-pipelines'
|
|
4
|
-
ref: master
|
|
5
|
-
file: 'Node-Testing.gitlab-ci.yml'
|
|
6
|
-
|
|
7
|
-
stages:
|
|
8
|
-
- cache
|
|
9
|
-
- test
|
|
10
|
-
- publish
|
|
11
|
-
|
|
12
|
-
publish-module:
|
|
13
|
-
stage: publish
|
|
14
|
-
image: node:12.20.1-alpine3.11
|
|
15
|
-
extends:
|
|
16
|
-
- .use-cache
|
|
17
|
-
only:
|
|
18
|
-
- tags
|
|
19
|
-
- /^v\d+\.\d+\.\d+$/
|
|
20
|
-
script:
|
|
21
|
-
- echo '//registry.npmjs.org/:_authToken=${NPM_TOKEN}' > ~/.npmrc
|
|
22
|
-
- yarn publish --access=public
|
package/.husky/pre-commit
DELETED
package/index.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`Logger Service Child should create child logger with where method 1`] = `
|
|
4
|
-
Object {
|
|
5
|
-
"debug": [Function],
|
|
6
|
-
"error": [Function],
|
|
7
|
-
"info": [Function],
|
|
8
|
-
"metadata": Object {
|
|
9
|
-
"requestId": "some-request-id",
|
|
10
|
-
"serviceName": "some-service-name",
|
|
11
|
-
},
|
|
12
|
-
"stream": Object {
|
|
13
|
-
"write": [Function],
|
|
14
|
-
},
|
|
15
|
-
"warn": [Function],
|
|
16
|
-
"where": [Function],
|
|
17
|
-
}
|
|
18
|
-
`;
|
|
19
|
-
|
|
20
|
-
exports[`Logger Service Child should create child using child method 1`] = `
|
|
21
|
-
Object {
|
|
22
|
-
"location": Object {
|
|
23
|
-
"file": "logger.spec.js",
|
|
24
|
-
"method": "test",
|
|
25
|
-
},
|
|
26
|
-
}
|
|
27
|
-
`;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { createContainer, asValue, asFunction } = require('awilix');
|
|
4
|
-
|
|
5
|
-
// External Modules
|
|
6
|
-
const path = require('path');
|
|
7
|
-
|
|
8
|
-
// Local Modules
|
|
9
|
-
const config = require('../../../src/config');
|
|
10
|
-
const loggerService = require('../../../src/services/logger.service');
|
|
11
|
-
|
|
12
|
-
// Stubs
|
|
13
|
-
const winston = require('./stubs/winston.stub');
|
|
14
|
-
const winstonGoogle = require('./stubs/winston.google.stub');
|
|
15
|
-
|
|
16
|
-
const testContainer = createContainer();
|
|
17
|
-
testContainer.register({
|
|
18
|
-
path: asValue(path),
|
|
19
|
-
winston: asValue(winston),
|
|
20
|
-
winstonGoogle: asValue(winstonGoogle),
|
|
21
|
-
config: asValue(config),
|
|
22
|
-
loggerService: asFunction(loggerService).singleton(),
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
module.exports = testContainer;
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const container = require('./container');
|
|
4
|
-
|
|
5
|
-
const winston = container.resolve('winston');
|
|
6
|
-
const config = container.resolve('config');
|
|
7
|
-
|
|
8
|
-
const loggerOpts = {
|
|
9
|
-
logLevel: 'info',
|
|
10
|
-
metadata: {
|
|
11
|
-
serviceName: 'some-service-name',
|
|
12
|
-
requestId: 'some-request-id',
|
|
13
|
-
},
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const loggerStub = {
|
|
17
|
-
defaultMeta: {
|
|
18
|
-
serviceName: loggerOpts.metadata.serviceName,
|
|
19
|
-
requestId: loggerOpts.metadata.requestId,
|
|
20
|
-
},
|
|
21
|
-
child: jest.fn(),
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
config.LOGGER.LOGGING_LEVELS.forEach((level) => {
|
|
25
|
-
loggerStub[level] = jest.fn();
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
module.exports = {
|
|
29
|
-
setUp() {
|
|
30
|
-
loggerStub.child.mockReturnValue(loggerStub);
|
|
31
|
-
winston.format.combine.mockReturnValue('colorize and simple');
|
|
32
|
-
winston.format.colorize.mockReturnValue('colorize');
|
|
33
|
-
winston.format.simple.mockReturnValue('simple');
|
|
34
|
-
winston.createLogger.mockReturnValue(loggerStub);
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
logger: {
|
|
38
|
-
opts: loggerOpts,
|
|
39
|
-
stub: loggerStub,
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
},
|
|
43
|
-
};
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const container = require('./container');
|
|
4
|
-
|
|
5
|
-
const config = container.resolve('config');
|
|
6
|
-
const winston = container.resolve('winston');
|
|
7
|
-
const winstonGoogle = container.resolve('winstonGoogle');
|
|
8
|
-
const loggerService = container.resolve('loggerService');
|
|
9
|
-
|
|
10
|
-
const loggerHelper = require('./logger.helper');
|
|
11
|
-
|
|
12
|
-
describe('Logger Service', () => {
|
|
13
|
-
const { LOGGING_LEVELS } = config.LOGGER;
|
|
14
|
-
let logger = null;
|
|
15
|
-
|
|
16
|
-
beforeEach(() => {
|
|
17
|
-
({ logger } = loggerHelper.setUp());
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
describe('General', () => {
|
|
21
|
-
test('should be exposed as function', () => {
|
|
22
|
-
expect(typeof loggerService).toBe('function');
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
test('should provide logger levels', () => {
|
|
26
|
-
const instance = loggerService(logger.opts);
|
|
27
|
-
LOGGING_LEVELS.forEach((level) => {
|
|
28
|
-
expect(typeof instance[level]).toBe('function');
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test('should invoke logger methods with message', () => {
|
|
33
|
-
const instance = loggerService(logger.opts);
|
|
34
|
-
LOGGING_LEVELS.forEach((level) => {
|
|
35
|
-
instance[level]('some-message');
|
|
36
|
-
expect(logger.stub[level]).toHaveBeenCalledTimes(1);
|
|
37
|
-
expect(logger.stub[level]).toHaveBeenLastCalledWith('some-message');
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('should invoke logger methods with extras', () => {
|
|
42
|
-
const instance = loggerService(logger.opts);
|
|
43
|
-
LOGGING_LEVELS.forEach((level) => {
|
|
44
|
-
instance[level]('some-message', { bar: 'foo' });
|
|
45
|
-
expect(logger.stub[level]).toHaveBeenCalledTimes(1);
|
|
46
|
-
expect(logger.stub[level]).toHaveBeenLastCalledWith('some-message', {
|
|
47
|
-
bar: 'foo',
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
describe('Transport', () => {
|
|
54
|
-
test('should use console and files in non-prod envs', () => {
|
|
55
|
-
loggerService(logger.opts);
|
|
56
|
-
const params = winston.createLogger.mock.calls[0][0];
|
|
57
|
-
expect(params.transports.length).toEqual(3);
|
|
58
|
-
expect(winston.transports.Console).toHaveBeenCalledTimes(1);
|
|
59
|
-
expect(winston.transports.File).toHaveBeenCalledTimes(2);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test('should use console in prod env (without credentials)', () => {
|
|
63
|
-
config.NODE_ENV = 'production';
|
|
64
|
-
loggerService(logger.opts);
|
|
65
|
-
const params = winston.createLogger.mock.calls[0][0];
|
|
66
|
-
expect(params.transports.length).toEqual(1);
|
|
67
|
-
expect(winston.transports.Console).toHaveBeenCalledTimes(1);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test('should use google winston in prod env (with credentials)', () => {
|
|
71
|
-
config.NODE_ENV = 'production';
|
|
72
|
-
config.GOOGLE.CREDENTIALS = 'some-credentials';
|
|
73
|
-
loggerService(logger.opts);
|
|
74
|
-
const params = winston.createLogger.mock.calls[0][0];
|
|
75
|
-
expect(params.transports.length).toEqual(1);
|
|
76
|
-
expect(winstonGoogle.LoggingWinston).toHaveBeenCalledTimes(1);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test('should use google winston in prod env (with cloud function)', () => {
|
|
80
|
-
config.NODE_ENV = 'production';
|
|
81
|
-
config.GOOGLE.GOOGLE_CLOUD_FUNCTION = 'true';
|
|
82
|
-
loggerService(logger.opts);
|
|
83
|
-
const params = winston.createLogger.mock.calls[0][0];
|
|
84
|
-
expect(params.transports.length).toEqual(1);
|
|
85
|
-
expect(winstonGoogle.LoggingWinston).toHaveBeenCalledTimes(1);
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
describe('Metadata', () => {
|
|
90
|
-
test('should not use default metadata', () => {
|
|
91
|
-
loggerService({});
|
|
92
|
-
const params = winston.createLogger.mock.calls[0][0];
|
|
93
|
-
expect(params.defaultMeta).toEqual({});
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test('should use default metadata', () => {
|
|
97
|
-
loggerService(logger.opts);
|
|
98
|
-
const params = winston.createLogger.mock.calls[0][0];
|
|
99
|
-
expect(params.defaultMeta).toEqual({
|
|
100
|
-
requestId: 'some-request-id',
|
|
101
|
-
serviceName: 'some-service-name',
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
describe('Child', () => {
|
|
107
|
-
test('should create child logger with where method', () => {
|
|
108
|
-
const instance = loggerService(logger.opts);
|
|
109
|
-
const childLogger = instance.where(__filename, 'test');
|
|
110
|
-
expect(logger.stub.child).toHaveBeenCalledTimes(1);
|
|
111
|
-
expect(childLogger).toMatchSnapshot();
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
test('should create child using child method', () => {
|
|
115
|
-
const instance = loggerService(logger.opts);
|
|
116
|
-
instance.where(__filename, 'test');
|
|
117
|
-
expect(logger.stub.child).toHaveBeenCalledTimes(1);
|
|
118
|
-
const params = logger.stub.child.mock.calls[0][0];
|
|
119
|
-
expect(params).toMatchSnapshot();
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
});
|