@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 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 _metadata_ object
44
+ ### The _labels_ object
45
45
 
46
- And also, the metadata object allows you to keep extra info along the logger journey:
46
+ And also, the labels allow you to keep extra info along the logger journey:
47
47
 
48
48
  ```
49
49
  const opts = {
50
- metadata: {
51
- serviceName: 'apolitical-service'
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": "1.0.2",
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.0",
34
- "awilix": "4.3.4",
35
- "winston": "3.3.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.1",
39
- "audit-ci": "4.1.0",
40
- "husky": "7.0.1",
41
- "jest": "27.0.6",
42
- "lint-staged": "11.0.0"
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": ">=12.20.1"
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
@@ -9,7 +9,7 @@ module.exports = {
9
9
  },
10
10
  LOGGER: {
11
11
  LOGGING_LEVELS: ['error', 'warn', 'info', 'debug'],
12
- ALLOWED_METADATA: ['serviceName', 'requestId'],
12
+ ALLOWED_LABELS: ['name', 'version'],
13
13
  TRANSPORTS: {
14
14
  FILE: {
15
15
  ERROR_OPTIONS: {
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', metadata = {} }) => {
6
- const { LOGGING_LEVELS, ALLOWED_METADATA } = config.LOGGER;
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 allowedMetadata() {
11
- return ALLOWED_METADATA.reduce((acc, cv) => {
12
- if (metadata[cv]) {
13
- acc[cv] = metadata[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(new winstonGoogle.LoggingWinston());
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
- { metadata: logger.defaultMeta },
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({ location: { file, method } });
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
@@ -1,6 +0,0 @@
1
- #!/bin/sh
2
- . "$(dirname "$0")/_/husky.sh"
3
-
4
- yarn lint-format
5
-
6
- yarn test
package/index.js DELETED
@@ -1,5 +0,0 @@
1
- 'use strict';
2
-
3
- const container = require('./src/container');
4
-
5
- module.exports = container.resolve('loggerService');
@@ -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
- });
@@ -1,5 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = {
4
- LoggingWinston: jest.fn(),
5
- };
@@ -1,14 +0,0 @@
1
- 'use strict';
2
-
3
- module.exports = {
4
- format: {
5
- combine: jest.fn(),
6
- colorize: jest.fn(),
7
- simple: jest.fn(),
8
- },
9
- transports: {
10
- Console: jest.fn(),
11
- File: jest.fn(),
12
- },
13
- createLogger: jest.fn(),
14
- };