Skip to content

Commit 210df1d

Browse files
committed
feat(bif-common): adds new pkg with logger
It is a universal package by design meaning that it works in the browser and also in NodeJS which allows both the API server and the cockpit to use the logger from the common package. Signed-off-by: Peter Somogyvari <[email protected]>
1 parent b4b0f83 commit 210df1d

File tree

17 files changed

+225
-2
lines changed

17 files changed

+225
-2
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"private": true,
44
"scripts": {
55
"configure": "lerna clean --yes && lerna bootstrap && npm run build && node ./tools/generate-api-server-config.js",
6+
"start": "node ./packages/bif-cmd-api-server/dist/lib/main/typescript/cmd/bif-api.js --config-file=.config.json",
67
"tsc": "lerna exec --stream --ignore '*/*cockpit' -- tsc --project ./tsconfig.json",
78
"clean": "lerna exec --stream --ignore '*/*cockpit' -- del-cli dist/**",
89
"build": "npm-run-all --parallel build:frontend build:backend",

packages/bif-cmd-api-server/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"homepage": "https://github.com/hyperledger-labs/blockchain-integration-framework#readme",
4747
"dependencies": {
4848
"@hyperledger-labs/bif-cockpit": "0.2.0",
49+
"@hyperledger-labs/bif-common": "0.2.0",
4950
"@hyperledger-labs/bif-core-api": "0.2.0",
5051
"@hyperledger-labs/bif-plugin-keychain-memory": "0.2.0",
5152
"@hyperledger-labs/bif-plugin-kv-storage-memory": "0.2.0",

packages/bif-cmd-api-server/src/main/typescript/api-server.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,24 @@ import { IPluginKVStorage, PluginFactory } from '@hyperledger-labs/bif-core-api'
88
import { CreateConsortiumEndpointV1 } from './consortium/routes/create-consortium-endpoint-v1';
99
import { IBifApiServerOptions, ConfigService } from './config/config-service';
1010
import { BIF_OPEN_API_JSON } from './openapi-spec';
11+
import { Logger, LoggerProvider } from '@hyperledger-labs/bif-common';
1112

1213
export interface IApiServerConstructorOptions {
1314
config: Config<IBifApiServerOptions>;
1415
}
1516

1617
export class ApiServer {
1718

19+
private readonly log: Logger;
20+
1821
constructor(public readonly options: IApiServerConstructorOptions) {
1922
if (!options) {
2023
throw new Error(`ApiServer#ctor options was falsy`);
2124
}
2225
if (!options.config) {
2326
throw new Error(`ApiServer#ctor options.config was falsy`);
2427
}
28+
this.log = LoggerProvider.getOrCreate({ label: 'api-server', level: options.config.get('logLevel') });
2529
}
2630

2731
async start(): Promise<void> {
@@ -34,7 +38,10 @@ export class ApiServer {
3438
const app: Express = express();
3539

3640
const cockpitWwwRoot = this.options.config.get('cockpitWwwRoot');
37-
app.use(express.static(cockpitWwwRoot));
41+
this.log.info(`cockpitWwwRoot: ${cockpitWwwRoot}`);
42+
const resolvedWwwRoot = path.resolve(process.cwd(), cockpitWwwRoot);
43+
this.log.info(`resolvedWwwRoot: ${resolvedWwwRoot}`);
44+
app.use(express.static(resolvedWwwRoot));
3845

3946
const cockpitPort: number = this.options.config.get('cockpitPort');
4047
const cockpitHost: string = this.options.config.get('cockpitHost');

packages/bif-cmd-api-server/src/main/typescript/config/config-service.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ import { randomBytes } from 'crypto';
22
import convict, { Schema, Config, SchemaObj } from 'convict';
33
import secp256k1 from 'secp256k1';
44
import { v4 as uuidV4 } from 'uuid';
5+
import { LoggerProvider, Logger } from '@hyperledger-labs/bif-common';
56

67
export interface IBifApiServerOptions {
78
configFile: string;
89
bifNodeId: string;
10+
logLevel: string;
911
cockpitHost: string;
1012
cockpitPort: number;
1113
cockpitWwwRoot: string;
@@ -64,6 +66,14 @@ export class ConfigService {
6466
env: 'BIF_NODE_ID',
6567
arg: 'bif-node-id',
6668
},
69+
logLevel: {
70+
doc: 'The level at which loggers should be configured. Supported values include the following: ' +
71+
'error, warn, info, debug, trace',
72+
format: ConfigService.formatNonBlankString,
73+
default: 'warn',
74+
env: 'LOG_LEVEL',
75+
arg: 'log-level',
76+
},
6777
cockpitHost: {
6878
doc: 'The host to bind the Cockpit webserver to. Secure default is: 127.0.0.1. Use 0.0.0.0 to bind for any host.',
6979
format: 'ipaddress',
@@ -83,7 +93,7 @@ export class ConfigService {
8393
format: '*',
8494
env: 'COCKPIT_WWW_ROOT',
8595
arg: 'cockpit-www-root',
86-
default: 'node_modules/@hyperledger-labs/bif-cockpit/www/',
96+
default: 'packages/bif-cmd-api-server/node_modules/@hyperledger-labs/bif-cockpit/www/',
8797
},
8898
apiHost: {
8999
doc: 'The host to bind the API to. Secure default is: 127.0.0.1. Use 0.0.0.0 to bind for any host.',
@@ -200,6 +210,7 @@ export class ConfigService {
200210
return {
201211
configFile: '.config.json',
202212
bifNodeId: uuidV4(),
213+
logLevel: 'debug',
203214
publicKey,
204215
privateKey,
205216
apiCorsDomainCsv: (schema.apiCorsDomainCsv as SchemaObj).default,
@@ -227,6 +238,9 @@ export class ConfigService {
227238
}
228239
ConfigService.config.validate();
229240
this.validateKeyPairMatch();
241+
const level = ConfigService.config.get('logLevel');
242+
const logger: Logger = LoggerProvider.getOrCreate({ label: 'config-service', level });
243+
logger.info('Configuration validation OK.');
230244
}
231245
return ConfigService.config;
232246
}

packages/bif-cockpit/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"@angular/platform-browser-dynamic": "8.2.14",
2323
"@angular/router": "8.2.14",
2424
"@capacitor/core": "1.5.1",
25+
"@hyperledger-labs/bif-common": "0.2.0",
2526
"@ionic-native/core": "5.0.0",
2627
"@ionic-native/splash-screen": "5.0.0",
2728
"@ionic-native/status-bar": "5.0.0",

packages/bif-cockpit/src/app/app.component.ts

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { Platform } from '@ionic/angular';
44
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
55
import { StatusBar } from '@ionic-native/status-bar/ngx';
66

7+
import { LoggerProvider, Logger } from '@hyperledger-labs/bif-common';
8+
79
@Component({
810
selector: 'app-root',
911
templateUrl: 'app.component.html',
@@ -45,18 +47,23 @@ export class AppComponent implements OnInit {
4547
];
4648
public labels = ['Family', 'Friends', 'Notes', 'Work', 'Travel', 'Reminders'];
4749

50+
private readonly logger: Logger;
51+
4852
constructor(
4953
private platform: Platform,
5054
private splashScreen: SplashScreen,
5155
private statusBar: StatusBar
5256
) {
57+
this.logger = LoggerProvider.getOrCreate({ label: 'app-component', level: 'debug' });
58+
this.logger.info('Initializing app...');
5359
this.initializeApp();
5460
}
5561

5662
initializeApp() {
5763
this.platform.ready().then(() => {
5864
this.statusBar.styleDefault();
5965
this.splashScreen.hide();
66+
this.logger.info('App initialized OK. Splashscreen was hidden.');
6067
});
6168
}
6269

packages/bif-common/README.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# `@hyperledger-labs/bif-common`
2+
3+
> TODO: description
4+
5+
## Usage
6+
7+
```
8+
// TODO: DEMONSTRATE API
9+
```

packages/bif-common/package-lock.json

+18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/bif-common/package.json

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"name": "@hyperledger-labs/bif-common",
3+
"version": "0.2.0",
4+
"description": "Universal library used by both front end and back end components of BIF. Aims to be a developer swiss army knife.",
5+
"main": "dist/bif-common.node.umd.js",
6+
"mainMinified": "dist/bif-common.node.umd.min.js",
7+
"browser": "dist/bif-common.web.umd.js",
8+
"browserMinified": "dist/bif-common.web.umd.min.js",
9+
"module": "dist/lib/main/typescript/index.js",
10+
"types": "dist/types/main/typescript/index.d.ts",
11+
"files": [
12+
"dist/*"
13+
],
14+
"publishConfig": {
15+
"access": "public"
16+
},
17+
"engines": {
18+
"node": ">=10",
19+
"npm": ">=6"
20+
},
21+
"repository": {
22+
"type": "git",
23+
"url": "git+https://github.com/hyperledger-labs/blockchain-integration-framework.git"
24+
},
25+
"keywords": [
26+
"Hyperledger",
27+
"Blockchain",
28+
"Interoperability",
29+
"Integration"
30+
],
31+
"author": {
32+
"name": "Peter Somogyvari",
33+
"email": "[email protected]",
34+
"url": "https://accenture.com"
35+
},
36+
"contributors": [
37+
{
38+
"name": "Please add yourself to the list of contributors",
39+
"email": "[email protected]",
40+
"url": "https://example.com"
41+
}
42+
],
43+
"license": "Apache-2.0",
44+
"bugs": {
45+
"url": "https://github.com/hyperledger-labs/blockchain-integration-framework/issues"
46+
},
47+
"homepage": "https://github.com/hyperledger-labs/blockchain-integration-framework#readme",
48+
"dependencies": {
49+
"loglevel": "1.6.7",
50+
"loglevel-plugin-prefix": "0.8.4"
51+
}
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './public-api';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Logger, ILoggerOptions } from './logger';
2+
3+
export class LoggerProvider {
4+
5+
private static loggers: Map<string, Logger> = new Map();
6+
7+
public static getOrCreate(loggerOptions: ILoggerOptions) {
8+
let logger: Logger | undefined = LoggerProvider.loggers.get(loggerOptions.label);
9+
if (!logger) {
10+
logger = new Logger(loggerOptions);
11+
LoggerProvider.loggers.set(loggerOptions.label, logger);
12+
}
13+
return logger;
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import libLogLevel, { Logger as LogLevelLogger, levels } from 'loglevel';
2+
import prefix from 'loglevel-plugin-prefix';
3+
4+
prefix.reg(libLogLevel);
5+
6+
prefix.apply(libLogLevel, {
7+
template: '[%t] %l (%n):',
8+
levelFormatter(level) {
9+
return level.toUpperCase();
10+
},
11+
nameFormatter(name) {
12+
return name || 'global';
13+
},
14+
timestampFormatter(date) {
15+
return date.toISOString();
16+
},
17+
});
18+
19+
export interface ILoggerOptions {
20+
label: string;
21+
level?: string;
22+
}
23+
24+
/**
25+
* Levels:
26+
* - error: 0,
27+
* - warn: 1,
28+
* - info: 2,
29+
* - debug: 3,
30+
* - trace: 4
31+
*/
32+
export class Logger {
33+
34+
private readonly backend: LogLevelLogger;
35+
36+
constructor(public readonly options: ILoggerOptions) {
37+
const level: string = options.level || 'warn';
38+
this.backend = libLogLevel.getLogger(options.label);
39+
this.backend.setLevel(level.toUpperCase() as any);
40+
}
41+
42+
public async shutdown(gracePeriodMillis: number = 60000): Promise<void> {
43+
this.backend.info('Shut down logger OK.');
44+
}
45+
46+
public error(...msg: any[]): void {
47+
this.backend.error(...msg);
48+
}
49+
50+
public warn(...msg: any[]): void {
51+
this.backend.warn(...msg);
52+
}
53+
public info(...msg: any[]): void {
54+
this.backend.info(...msg);
55+
}
56+
public debug(...msg: any[]): void {
57+
this.backend.debug(...msg);
58+
}
59+
public trace(...msg: any[]): void {
60+
this.backend.trace(...msg);
61+
}
62+
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { LoggerProvider } from './logging/logger-provider';
2+
export { Logger, ILoggerOptions } from './logging/logger';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// tslint:disable-next-line: no-var-requires
2+
const tap = require('tap');
3+
import { Logger, LoggerProvider } from '../../../main/typescript/public-api';
4+
5+
tap.pass('Test file can be executed');
6+
7+
tap.test('Library can be loaded', (assert: any) => {
8+
assert.plan(2);
9+
assert.ok(Logger);
10+
assert.ok(LoggerProvider);
11+
});

packages/bif-common/src/test/typescript/integration/tap-parallel-not-ok

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// tslint:disable-next-line: no-var-requires
2+
const tap = require('tap');
3+
import { Logger, LoggerProvider } from '../../../main/typescript/public-api';
4+
5+
tap.pass('Test file can be executed');
6+
7+
tap.test('Library can be loaded', (assert: any) => {
8+
assert.plan(2);
9+
assert.ok(Logger);
10+
assert.ok(LoggerProvider);
11+
});

packages/bif-common/tsconfig.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"compilerOptions": {
4+
"outDir": "./dist/lib/", /* Redirect output structure to the directory. */
5+
"declarationDir": "dist/types",
6+
},
7+
"include": [
8+
"./src"
9+
]
10+
}

0 commit comments

Comments
 (0)