Skip to content
This repository was archived by the owner on Nov 10, 2022. It is now read-only.

Commit 20f3bfc

Browse files
authored
chore: adding component logger (#62)
1 parent 28fabc4 commit 20f3bfc

File tree

4 files changed

+157
-1
lines changed

4 files changed

+157
-1
lines changed

src/api/diag.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,14 @@
1414
* limitations under the License.
1515
*/
1616

17+
import { DiagComponentLogger } from '../diag/ComponentLogger';
1718
import { createLogLevelDiagLogger } from '../diag/internal/logLevelLogger';
18-
import { DiagLogFunction, DiagLogger, DiagLogLevel } from '../diag/types';
19+
import {
20+
ComponentLoggerOptions,
21+
DiagLogFunction,
22+
DiagLogger,
23+
DiagLogLevel,
24+
} from '../diag/types';
1925
import {
2026
getGlobal,
2127
registerGlobal,
@@ -90,6 +96,10 @@ export class DiagAPI implements DiagLogger {
9096
unregisterGlobal(API_NAME);
9197
};
9298

99+
self.createComponentLogger = (options: ComponentLoggerOptions) => {
100+
return new DiagComponentLogger(options);
101+
};
102+
93103
self.verbose = _logProxy('verbose');
94104
self.debug = _logProxy('debug');
95105
self.info = _logProxy('info');
@@ -106,6 +116,12 @@ export class DiagAPI implements DiagLogger {
106116
* @returns true if the logger was successfully registered, else false
107117
*/
108118
public setLogger!: (logger: DiagLogger, logLevel?: DiagLogLevel) => boolean;
119+
/**
120+
*
121+
*/
122+
public createComponentLogger!: (
123+
options: ComponentLoggerOptions
124+
) => DiagLogger;
109125

110126
// DiagLogger implementation
111127
public verbose!: DiagLogFunction;

src/diag/ComponentLogger.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { getGlobal } from '../internal/global-utils';
18+
import { ComponentLoggerOptions, DiagLogger } from './types';
19+
20+
/**
21+
* Component Logger which is meant to be used as part of any component which
22+
* will add automatically additional namespace in front of the log message.
23+
* It will then forward all message to global diag logger
24+
* @example
25+
* const cLogger = diag.createComponentLogger({ namespace: '@opentelemetry/instrumentation-http' });
26+
* cLogger.debug('test');
27+
* // @opentelemetry/instrumentation-http test
28+
*/
29+
export class DiagComponentLogger implements DiagLogger {
30+
private _namespace: string;
31+
32+
constructor(props: ComponentLoggerOptions) {
33+
this._namespace = props.namespace || 'DiagComponentLogger';
34+
}
35+
36+
public debug(...args: any[]): void {
37+
return logProxy('debug', this._namespace, args);
38+
}
39+
40+
public error(...args: any[]): void {
41+
return logProxy('error', this._namespace, args);
42+
}
43+
44+
public info(...args: any[]): void {
45+
return logProxy('info', this._namespace, args);
46+
}
47+
48+
public warn(...args: any[]): void {
49+
return logProxy('warn', this._namespace, args);
50+
}
51+
52+
public verbose(...args: any[]): void {
53+
return logProxy('verbose', this._namespace, args);
54+
}
55+
}
56+
57+
function logProxy(
58+
funcName: keyof DiagLogger,
59+
namespace: string,
60+
args: any
61+
): void {
62+
const logger = getGlobal('diag');
63+
// shortcut if logger not set
64+
if (!logger) {
65+
return;
66+
}
67+
68+
args.unshift(namespace);
69+
return logger[funcName].apply(logger, args);
70+
}

src/diag/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,10 @@ export enum DiagLogLevel {
8989
/** Used to set the logging level to include all logging */
9090
ALL = 9999,
9191
}
92+
93+
/**
94+
* Defines options for ComponentLogger
95+
*/
96+
export interface ComponentLoggerOptions {
97+
namespace: string;
98+
}

test/diag/ComponentLogger.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import * as assert from 'assert';
18+
import * as sinon from 'sinon';
19+
import { diag, DiagLogger, DiagLogLevel } from '../../src';
20+
21+
class SpyLogger implements DiagLogger {
22+
debug() {}
23+
24+
error() {}
25+
26+
info() {}
27+
28+
warn() {}
29+
30+
verbose() {}
31+
}
32+
33+
const loggerFunctions = ['verbose', 'debug', 'info', 'warn', 'error'];
34+
35+
describe('ComponentLogger', () => {
36+
let logger: DiagLogger;
37+
38+
const sandbox = sinon.createSandbox();
39+
40+
beforeEach(() => {
41+
logger = new SpyLogger();
42+
sandbox.spy(logger);
43+
diag.setLogger(logger, DiagLogLevel.ALL);
44+
});
45+
46+
afterEach(() => {
47+
sandbox.restore();
48+
});
49+
50+
loggerFunctions.forEach(name => {
51+
const fName = name as keyof SpyLogger;
52+
it(`should call global logger function "${name}" with namespace as first param`, () => {
53+
const componentLogger = diag.createComponentLogger({ namespace: 'foo' });
54+
componentLogger[fName]('test');
55+
56+
assert.strictEqual((logger[fName] as sinon.SinonSpy).callCount, 1);
57+
assert.deepStrictEqual((logger[fName] as sinon.SinonSpy).args[0], [
58+
'foo',
59+
'test',
60+
]);
61+
});
62+
});
63+
});

0 commit comments

Comments
 (0)