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

Commit

Permalink
chore: adding component logger (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
obecny authored May 18, 2021
1 parent 28fabc4 commit 20f3bfc
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 1 deletion.
18 changes: 17 additions & 1 deletion src/api/diag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@
* limitations under the License.
*/

import { DiagComponentLogger } from '../diag/ComponentLogger';
import { createLogLevelDiagLogger } from '../diag/internal/logLevelLogger';
import { DiagLogFunction, DiagLogger, DiagLogLevel } from '../diag/types';
import {
ComponentLoggerOptions,
DiagLogFunction,
DiagLogger,
DiagLogLevel,
} from '../diag/types';
import {
getGlobal,
registerGlobal,
Expand Down Expand Up @@ -90,6 +96,10 @@ export class DiagAPI implements DiagLogger {
unregisterGlobal(API_NAME);
};

self.createComponentLogger = (options: ComponentLoggerOptions) => {
return new DiagComponentLogger(options);
};

self.verbose = _logProxy('verbose');
self.debug = _logProxy('debug');
self.info = _logProxy('info');
Expand All @@ -106,6 +116,12 @@ export class DiagAPI implements DiagLogger {
* @returns true if the logger was successfully registered, else false
*/
public setLogger!: (logger: DiagLogger, logLevel?: DiagLogLevel) => boolean;
/**
*
*/
public createComponentLogger!: (
options: ComponentLoggerOptions
) => DiagLogger;

// DiagLogger implementation
public verbose!: DiagLogFunction;
Expand Down
70 changes: 70 additions & 0 deletions src/diag/ComponentLogger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { getGlobal } from '../internal/global-utils';
import { ComponentLoggerOptions, DiagLogger } from './types';

/**
* Component Logger which is meant to be used as part of any component which
* will add automatically additional namespace in front of the log message.
* It will then forward all message to global diag logger
* @example
* const cLogger = diag.createComponentLogger({ namespace: '@opentelemetry/instrumentation-http' });
* cLogger.debug('test');
* // @opentelemetry/instrumentation-http test
*/
export class DiagComponentLogger implements DiagLogger {
private _namespace: string;

constructor(props: ComponentLoggerOptions) {
this._namespace = props.namespace || 'DiagComponentLogger';
}

public debug(...args: any[]): void {
return logProxy('debug', this._namespace, args);
}

public error(...args: any[]): void {
return logProxy('error', this._namespace, args);
}

public info(...args: any[]): void {
return logProxy('info', this._namespace, args);
}

public warn(...args: any[]): void {
return logProxy('warn', this._namespace, args);
}

public verbose(...args: any[]): void {
return logProxy('verbose', this._namespace, args);
}
}

function logProxy(
funcName: keyof DiagLogger,
namespace: string,
args: any
): void {
const logger = getGlobal('diag');
// shortcut if logger not set
if (!logger) {
return;
}

args.unshift(namespace);
return logger[funcName].apply(logger, args);
}
7 changes: 7 additions & 0 deletions src/diag/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,10 @@ export enum DiagLogLevel {
/** Used to set the logging level to include all logging */
ALL = 9999,
}

/**
* Defines options for ComponentLogger
*/
export interface ComponentLoggerOptions {
namespace: string;
}
63 changes: 63 additions & 0 deletions test/diag/ComponentLogger.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright The OpenTelemetry Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as assert from 'assert';
import * as sinon from 'sinon';
import { diag, DiagLogger, DiagLogLevel } from '../../src';

class SpyLogger implements DiagLogger {
debug() {}

error() {}

info() {}

warn() {}

verbose() {}
}

const loggerFunctions = ['verbose', 'debug', 'info', 'warn', 'error'];

describe('ComponentLogger', () => {
let logger: DiagLogger;

const sandbox = sinon.createSandbox();

beforeEach(() => {
logger = new SpyLogger();
sandbox.spy(logger);
diag.setLogger(logger, DiagLogLevel.ALL);
});

afterEach(() => {
sandbox.restore();
});

loggerFunctions.forEach(name => {
const fName = name as keyof SpyLogger;
it(`should call global logger function "${name}" with namespace as first param`, () => {
const componentLogger = diag.createComponentLogger({ namespace: 'foo' });
componentLogger[fName]('test');

assert.strictEqual((logger[fName] as sinon.SinonSpy).callCount, 1);
assert.deepStrictEqual((logger[fName] as sinon.SinonSpy).args[0], [
'foo',
'test',
]);
});
});
});

0 comments on commit 20f3bfc

Please sign in to comment.