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

Commit 7b5554b

Browse files
authored
Merge branch 'main' into rm-backward
2 parents 9545632 + 35224c7 commit 7b5554b

File tree

9 files changed

+129
-88
lines changed

9 files changed

+129
-88
lines changed

.github/workflows/test.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
strategy:
1111
fail-fast: false
1212
matrix:
13-
container: ["node:8", "node:10", "node:12", "node:14"]
13+
container: ["node:8", "node:10", "node:12", "node:14", "node:16"]
1414
runs-on: ubuntu-latest
1515
container:
1616
image: ${{ matrix.container }}
@@ -29,7 +29,7 @@ jobs:
2929

3030
- name: Report Coverage
3131
run: npm run codecov
32-
if: ${{ matrix.container }} == 'node:12'
32+
if: ${{ matrix.container }} == 'node:14'
3333

3434
browser-tests:
3535
runs-on: ubuntu-latest

src/api/diag.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,18 @@ export class DiagAPI implements DiagLogger {
8585
return false;
8686
}
8787

88-
return registerGlobal(
89-
'diag',
90-
createLogLevelDiagLogger(logLevel, logger),
91-
true
92-
);
88+
const oldLogger = getGlobal('diag');
89+
const newLogger = createLogLevelDiagLogger(logLevel, logger);
90+
// There already is an logger registered. We'll let it know before overwriting it.
91+
if (oldLogger) {
92+
const stack = new Error().stack ?? '<failed to generate stacktrace>';
93+
oldLogger.warn(`Current logger will be overwritten from ${stack}`);
94+
newLogger.warn(
95+
`Current logger will overwrite one already registered from ${stack}`
96+
);
97+
}
98+
99+
return registerGlobal('diag', newLogger, true);
93100
};
94101

95102
self.disable = () => {

src/internal/global-utils.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,12 @@ export function registerGlobal<Type extends keyof OTelGlobalAPI>(
3535
instance: OTelGlobalAPI[Type],
3636
allowOverride = false
3737
): boolean {
38-
_global[GLOBAL_OPENTELEMETRY_API_KEY] = _global[
38+
const api = (_global[GLOBAL_OPENTELEMETRY_API_KEY] = _global[
3939
GLOBAL_OPENTELEMETRY_API_KEY
4040
] ?? {
4141
version: VERSION,
42-
};
42+
});
4343

44-
const api = _global[GLOBAL_OPENTELEMETRY_API_KEY]!;
4544
if (!allowOverride && api[type]) {
4645
// already registered an API of this type
4746
const err = new Error(
@@ -61,6 +60,10 @@ export function registerGlobal<Type extends keyof OTelGlobalAPI>(
6160
}
6261

6362
api[type] = instance;
63+
diag.debug(
64+
`@opentelemetry/api: Registered a global for ${type} v${VERSION}.`
65+
);
66+
6467
return true;
6568
}
6669

@@ -75,6 +78,9 @@ export function getGlobal<Type extends keyof OTelGlobalAPI>(
7578
}
7679

7780
export function unregisterGlobal(type: keyof OTelGlobalAPI) {
81+
diag.debug(
82+
`@opentelemetry/api: Unregistering a global for ${type} v${VERSION}.`
83+
);
7884
const api = _global[GLOBAL_OPENTELEMETRY_API_KEY];
7985

8086
if (api) {

src/trace/NoopTracer.ts

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -49,41 +49,47 @@ export class NoopTracer implements Tracer {
4949

5050
startActiveSpan<F extends (span: Span) => ReturnType<F>>(
5151
name: string,
52-
arg2: F | SpanOptions,
52+
fn: F
53+
): ReturnType<F>;
54+
startActiveSpan<F extends (span: Span) => ReturnType<F>>(
55+
name: string,
56+
opts: SpanOptions | undefined,
57+
fn: F
58+
): ReturnType<F>;
59+
startActiveSpan<F extends (span: Span) => ReturnType<F>>(
60+
name: string,
61+
opts: SpanOptions | undefined,
62+
ctx: Context | undefined,
63+
fn: F
64+
): ReturnType<F>;
65+
startActiveSpan<F extends (span: Span) => ReturnType<F>>(
66+
name: string,
67+
arg2?: F | SpanOptions,
5368
arg3?: F | Context,
5469
arg4?: F
5570
): ReturnType<F> | undefined {
56-
let fn: F | undefined,
57-
options: SpanOptions | undefined,
58-
activeContext: Context | undefined;
59-
if (arguments.length === 2 && typeof arg2 === 'function') {
60-
fn = arg2;
61-
} else if (
62-
arguments.length === 3 &&
63-
typeof arg2 === 'object' &&
64-
typeof arg3 === 'function'
65-
) {
66-
options = arg2;
67-
fn = arg3;
68-
} else if (
69-
arguments.length === 4 &&
70-
typeof arg2 === 'object' &&
71-
typeof arg3 === 'object' &&
72-
typeof arg4 === 'function'
73-
) {
74-
options = arg2;
75-
activeContext = arg3;
76-
fn = arg4;
71+
let opts: SpanOptions | undefined;
72+
let ctx: Context | undefined;
73+
let fn: F;
74+
75+
if (arguments.length < 2) {
76+
return;
77+
} else if (arguments.length === 2) {
78+
fn = arg2 as F;
79+
} else if (arguments.length === 3) {
80+
opts = arg2 as SpanOptions | undefined;
81+
fn = arg3 as F;
82+
} else {
83+
opts = arg2 as SpanOptions | undefined;
84+
ctx = arg3 as Context | undefined;
85+
fn = arg4 as F;
7786
}
7887

79-
const parentContext = activeContext ?? context.active();
80-
const span = this.startSpan(name, options, parentContext);
88+
const parentContext = ctx ?? context.active();
89+
const span = this.startSpan(name, opts, parentContext);
8190
const contextWithSpanSet = setSpan(parentContext, span);
8291

83-
if (fn) {
84-
return context.with(contextWithSpanSet, fn, undefined, span);
85-
}
86-
return;
92+
return context.with(contextWithSpanSet, fn, undefined, span);
8793
}
8894
}
8995

test/diag/ComponentLogger.test.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,9 @@ import { diag, DiagLogger, DiagLogLevel } from '../../src';
2020

2121
class SpyLogger implements DiagLogger {
2222
debug() {}
23-
2423
error() {}
25-
2624
info() {}
27-
2825
warn() {}
29-
3026
verbose() {}
3127
}
3228

@@ -41,6 +37,8 @@ describe('ComponentLogger', () => {
4137
logger = new SpyLogger();
4238
sandbox.spy(logger);
4339
diag.setLogger(logger, DiagLogLevel.ALL);
40+
// clean any messages up that might be there from the registration
41+
sandbox.reset();
4442
});
4543

4644
afterEach(() => {

test/diag/logLevel.test.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ describe('LogLevelFilter DiagLogger', () => {
4545
/** Simulated Legacy logger */
4646
let incompleteLogger: DiagLogger;
4747

48+
const restoreCallHistory = () => {
49+
diagLoggerFunctions.forEach(fName => {
50+
calledArgs[fName] = null;
51+
});
52+
};
53+
4854
beforeEach(() => {
4955
// Set no logger so that sinon doesn't complain about TypeError: Attempted to wrap xxxx which is already wrapped
5056
diag.disable();
@@ -66,10 +72,7 @@ describe('LogLevelFilter DiagLogger', () => {
6672
});
6773

6874
afterEach(() => {
69-
// restore
70-
diagLoggerFunctions.forEach(fName => {
71-
calledArgs[fName] = null;
72-
});
75+
restoreCallHistory();
7376
});
7477

7578
const levelMap: Array<{
@@ -170,6 +173,7 @@ describe('LogLevelFilter DiagLogger', () => {
170173
map.level,
171174
dummyLogger
172175
);
176+
restoreCallHistory();
173177
testLogger[fName](`${fName} called %s`, 'param1');
174178
diagLoggerFunctions.forEach(lName => {
175179
if (
@@ -190,6 +194,7 @@ describe('LogLevelFilter DiagLogger', () => {
190194

191195
it('diag.setLogger level and logger should log', () => {
192196
diag.setLogger(dummyLogger, map.level);
197+
restoreCallHistory();
193198
diag[fName](`${fName} called %s`, 'param1');
194199
diagLoggerFunctions.forEach(lName => {
195200
if (fName === lName && map.ignoreFuncs.indexOf(lName) === -1) {
@@ -217,6 +222,7 @@ describe('LogLevelFilter DiagLogger', () => {
217222
map.level,
218223
invalidLogger as any
219224
);
225+
restoreCallHistory();
220226

221227
testLogger[fName](`${fName} called %s`, 'param1');
222228
diagLoggerFunctions.forEach(lName => {

test/diag/logger.test.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ describe('DiagLogger functions', () => {
3838

3939
let dummyLogger: DiagLogger;
4040

41+
const restoreCallHistory = () => {
42+
diagLoggerFunctions.forEach(fName => {
43+
calledArgs[fName] = null;
44+
});
45+
};
46+
4147
beforeEach(() => {
4248
// mock
4349
dummyLogger = {} as DiagLogger;
@@ -49,10 +55,7 @@ describe('DiagLogger functions', () => {
4955
});
5056

5157
afterEach(() => {
52-
// restore
53-
diagLoggerFunctions.forEach(fName => {
54-
calledArgs[fName] = null;
55-
});
58+
restoreCallHistory();
5659
diag.disable();
5760
});
5861

@@ -75,6 +78,7 @@ describe('DiagLogger functions', () => {
7578

7679
it(`diag should log with ${fName} message`, () => {
7780
diag.setLogger(dummyLogger, DiagLogLevel.ALL);
81+
restoreCallHistory();
7882
diag[fName](`${fName} called %s`, 'param1');
7983
diagLoggerFunctions.forEach(lName => {
8084
if (fName === lName) {

test/internal/global.test.ts

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import * as assert from 'assert';
1818
import { getGlobal } from '../../src/internal/global-utils';
1919
import { _globalThis } from '../../src/platform';
2020
import { NoopContextManager } from '../../src/context/NoopContextManager';
21+
import { DiagLogLevel } from '../../src/diag/types';
2122
import sinon = require('sinon');
2223

2324
const api1 = require('../../src') as typeof import('../../src');
@@ -32,6 +33,14 @@ const api2 = require('../../src') as typeof import('../../src');
3233
// It is intentionally not autogenerated to ensure the author of the change is aware of what they are doing.
3334
const GLOBAL_API_SYMBOL_KEY = 'io.opentelemetry.js.api.0';
3435

36+
const getMockLogger = () => ({
37+
verbose: sinon.spy(),
38+
debug: sinon.spy(),
39+
info: sinon.spy(),
40+
warn: sinon.spy(),
41+
error: sinon.spy(),
42+
});
43+
3544
describe('Global Utils', () => {
3645
// prove they are separate instances
3746
assert.notEqual(api1, api2);
@@ -94,48 +103,53 @@ describe('Global Utils', () => {
94103
);
95104
});
96105

106+
it('should debug log registrations', () => {
107+
const logger = getMockLogger();
108+
api1.diag.setLogger(logger, DiagLogLevel.DEBUG);
109+
110+
const newContextManager = new NoopContextManager();
111+
api1.context.setGlobalContextManager(newContextManager);
112+
113+
sinon.assert.calledWith(logger.debug, sinon.match(/global for context/));
114+
sinon.assert.calledWith(logger.debug, sinon.match(/global for diag/));
115+
sinon.assert.calledTwice(logger.debug);
116+
});
117+
97118
it('should log an error if there is a duplicate registration', () => {
98-
const error = sinon.stub();
99-
api1.diag.setLogger({
100-
verbose: () => {},
101-
debug: () => {},
102-
info: () => {},
103-
warn: () => {},
104-
error,
105-
});
119+
const logger = getMockLogger();
120+
api1.diag.setLogger(logger);
106121

107122
api1.context.setGlobalContextManager(new NoopContextManager());
108123
api1.context.setGlobalContextManager(new NoopContextManager());
109124

110-
sinon.assert.calledOnce(error);
111-
assert.strictEqual(error.firstCall.args.length, 1);
125+
sinon.assert.calledOnce(logger.error);
126+
assert.strictEqual(logger.error.firstCall.args.length, 1);
112127
assert.ok(
113-
error.firstCall.args[0].startsWith(
128+
logger.error.firstCall.args[0].startsWith(
114129
'Error: @opentelemetry/api: Attempted duplicate registration of API: context'
115130
)
116131
);
117132
});
118133

119134
it('should allow duplicate registration of the diag logger', () => {
120-
const error1 = sinon.stub();
121-
const error2 = sinon.stub();
122-
api1.diag.setLogger({
123-
verbose: () => {},
124-
debug: () => {},
125-
info: () => {},
126-
warn: () => {},
127-
error: error1,
128-
});
129-
130-
api1.diag.setLogger({
131-
verbose: () => {},
132-
debug: () => {},
133-
info: () => {},
134-
warn: () => {},
135-
error: error2,
136-
});
137-
138-
sinon.assert.notCalled(error1);
139-
sinon.assert.notCalled(error2);
135+
const logger1 = getMockLogger();
136+
const logger2 = getMockLogger();
137+
138+
api1.diag.setLogger(logger1);
139+
api1.diag.setLogger(logger2);
140+
141+
const MSG = '__log message__';
142+
api1.diag.info(MSG);
143+
144+
sinon.assert.notCalled(logger1.error);
145+
sinon.assert.notCalled(logger1.info);
146+
sinon.assert.calledOnce(logger1.warn);
147+
sinon.assert.calledWith(logger1.warn, sinon.match(/will be overwritten/i));
148+
149+
sinon.assert.notCalled(logger2.error);
150+
sinon.assert.calledOnce(logger2.warn);
151+
sinon.assert.calledWith(logger2.warn, sinon.match(/will overwrite/i));
152+
sinon.assert.calledOnce(logger2.info);
153+
sinon.assert.calledWith(logger2.info, MSG);
140154
});
141155
});

test/noop-implementations/noop-tracer.test.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,16 @@ describe('NoopTracer', () => {
6969
}
7070
};
7171
const opts = { attributes: { foo: 'bar' } };
72-
const ctx = context.active();
7372

74-
const a = tracer.startActiveSpan(name, fn);
75-
assert.strictEqual(a, 1);
73+
assert.strictEqual((tracer as any).startActiveSpan(name), undefined);
7674

77-
const b = tracer.startActiveSpan(name, opts, fn);
75+
assert.strictEqual(tracer.startActiveSpan(name, fn), 1);
7876

79-
assert.strictEqual(b, 1);
77+
assert.strictEqual(tracer.startActiveSpan(name, opts, fn), 1);
8078

81-
const c = tracer.startActiveSpan(name, opts, ctx, fn);
82-
assert.strictEqual(c, 1);
79+
assert.strictEqual(
80+
tracer.startActiveSpan(name, opts, context.active(), fn),
81+
1
82+
);
8383
});
8484
});

0 commit comments

Comments
 (0)