-
Notifications
You must be signed in to change notification settings - Fork 549
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(instr-undici): fix issue with config in constructor #2395
Changes from all commits
6dc2736
c928cdd
1fd1cc2
30cc3ef
2ed4802
e473df6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,7 +68,6 @@ | |
private _httpClientDurationHistogram!: Histogram; | ||
constructor(config: UndiciInstrumentationConfig = {}) { | ||
super(PACKAGE_NAME, PACKAGE_VERSION, config); | ||
this.setConfig(config); | ||
} | ||
|
||
// No need to instrument files/modules | ||
|
@@ -77,26 +76,32 @@ | |
} | ||
|
||
override disable(): void { | ||
if (!this.getConfig().enabled) { | ||
return; | ||
} | ||
|
||
super.disable(); | ||
this._channelSubs.forEach(sub => sub.channel.unsubscribe(sub.onMessage)); | ||
this._channelSubs.length = 0; | ||
super.disable(); | ||
this.setConfig({ ...this.getConfig(), enabled: false }); | ||
} | ||
|
||
override enable(): void { | ||
if (this.getConfig().enabled) { | ||
return; | ||
} | ||
// "enabled" handling is currently a bit messy with InstrumentationBase. | ||
// If constructed with `{enabled: false}`, this `.enable()` is still called, | ||
// and `this.getConfig().enabled !== this.isEnabled()`, creating confusion. | ||
// | ||
// For now, this class will setup for instrumenting if `.enable()` is | ||
// called, but use `this.getConfig().enabled` to determine if | ||
// instrumentation should be generated. This covers the more likely common | ||
// case of config being given a construction time, rather than later via | ||
// `instance.enable()`, `.disable()`, or `.setConfig()` calls. | ||
super.enable(); | ||
this.setConfig({ ...this.getConfig(), enabled: true }); | ||
|
||
// This method is called by the `InstrumentationAbstract` constructor before | ||
// ours is called. So we need to ensure the property is initalized | ||
// This method is called by the super-class constructor before ours is | ||
// called. So we need to ensure the property is initalized. | ||
this._channelSubs = this._channelSubs || []; | ||
|
||
// Avoid to duplicate subscriptions | ||
if (this._channelSubs.length > 0) { | ||
return; | ||
} | ||
|
||
this.subscribeToChannel( | ||
'undici:request:create', | ||
this.onRequestCreated.bind(this) | ||
|
@@ -113,16 +118,6 @@ | |
this.subscribeToChannel('undici:request:error', this.onError.bind(this)); | ||
} | ||
|
||
override setConfig(config: UndiciInstrumentationConfig = {}): void { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note for reviewer: here I was mixing |
||
super.setConfig(config); | ||
|
||
if (config?.enabled) { | ||
this.enable(); | ||
} else { | ||
this.disable(); | ||
} | ||
} | ||
|
||
protected override _updateMetricInstruments() { | ||
this._httpClientDurationHistogram = this.meter.createHistogram( | ||
'http.client.request.duration', | ||
|
@@ -162,9 +157,10 @@ | |
// - ignored by config | ||
// - method is 'CONNECT' | ||
const config = this.getConfig(); | ||
const enabled = config.enabled !== false; | ||
const shouldIgnoreReq = safeExecuteInTheMiddle( | ||
() => | ||
!config.enabled || | ||
!enabled || | ||
request.method === 'CONNECT' || | ||
config.ignoreRequestHook?.(request), | ||
e => e && this._diag.error('caught ignoreRequestHook error: ', e), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,19 +35,16 @@ import { MockPropagation } from './utils/mock-propagation'; | |
import { MockServer } from './utils/mock-server'; | ||
import { assertSpan } from './utils/assertSpan'; | ||
|
||
const instrumentation = new UndiciInstrumentation(); | ||
instrumentation.enable(); | ||
instrumentation.disable(); | ||
|
||
const protocol = 'http'; | ||
const hostname = 'localhost'; | ||
const mockServer = new MockServer(); | ||
const memoryExporter = new InMemorySpanExporter(); | ||
const provider = new NodeTracerProvider(); | ||
provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); | ||
instrumentation.setTracerProvider(provider); | ||
|
||
describe('UndiciInstrumentation `fetch` tests', function () { | ||
let instrumentation: UndiciInstrumentation; | ||
|
||
const protocol = 'http'; | ||
const hostname = 'localhost'; | ||
const mockServer = new MockServer(); | ||
const memoryExporter = new InMemorySpanExporter(); | ||
const provider = new NodeTracerProvider(); | ||
provider.addSpanProcessor(new SimpleSpanProcessor(memoryExporter)); | ||
|
||
before(function (done) { | ||
// Do not test if the `fetch` global API is not available | ||
// This applies to nodejs < v18 or nodejs < v16.15 wihtout the flag | ||
|
@@ -57,6 +54,9 @@ describe('UndiciInstrumentation `fetch` tests', function () { | |
this.skip(); | ||
} | ||
|
||
instrumentation = new UndiciInstrumentation(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note for reviewer: the test runner was loading all the test suites at once and also evaluating the 1st There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice find! |
||
instrumentation.setTracerProvider(provider); | ||
|
||
propagation.setGlobalPropagator(new MockPropagation()); | ||
context.setGlobalContextManager(new AsyncHooksContextManager().enable()); | ||
mockServer.start(done); | ||
|
@@ -105,8 +105,8 @@ describe('UndiciInstrumentation `fetch` tests', function () { | |
let spans = memoryExporter.getFinishedSpans(); | ||
assert.strictEqual(spans.length, 0); | ||
|
||
// Disable via config | ||
instrumentation.setConfig({ enabled: false }); | ||
// Disable | ||
instrumentation.disable(); | ||
|
||
const fetchUrl = `${protocol}://${hostname}:${mockServer.port}/?query=test`; | ||
const response = await fetch(fetchUrl); | ||
|
@@ -126,7 +126,8 @@ describe('UndiciInstrumentation `fetch` tests', function () { | |
}); | ||
afterEach(function () { | ||
// Empty configuration & disable | ||
instrumentation.setConfig({ enabled: false }); | ||
instrumentation.setConfig({}); | ||
instrumentation.disable(); | ||
}); | ||
|
||
it('should create valid spans even if the configuration hooks fail', async function () { | ||
|
@@ -135,7 +136,6 @@ describe('UndiciInstrumentation `fetch` tests', function () { | |
|
||
// Set the bad configuration | ||
instrumentation.setConfig({ | ||
enabled: true, | ||
ignoreRequestHook: () => { | ||
throw new Error('ignoreRequestHook error'); | ||
}, | ||
|
@@ -204,7 +204,6 @@ describe('UndiciInstrumentation `fetch` tests', function () { | |
|
||
// Set configuration | ||
instrumentation.setConfig({ | ||
enabled: true, | ||
ignoreRequestHook: req => { | ||
return req.path.indexOf('/ignore/path') !== -1; | ||
}, | ||
|
@@ -302,7 +301,6 @@ describe('UndiciInstrumentation `fetch` tests', function () { | |
assert.strictEqual(spans.length, 0); | ||
|
||
instrumentation.setConfig({ | ||
enabled: true, | ||
requireParentforSpans: true, | ||
}); | ||
|
||
|
@@ -322,7 +320,6 @@ describe('UndiciInstrumentation `fetch` tests', function () { | |
assert.strictEqual(spans.length, 0); | ||
|
||
instrumentation.setConfig({ | ||
enabled: true, | ||
requireParentforSpans: true, | ||
}); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note for reviewer: no need to call super since the parent class method deals with patching/unpatching and does not apply here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super.disable() is also setting
this._enabled = false
, so I wonder if it still should be called.Those calls to
super.
in the enable() and disable() were added in this PR: https://github.com/open-telemetry/opentelemetry-js-contrib/pull/2289/files#diff-8e6dd9963dd47a60e25c9ac92d7a5ae25ce79c40340cb4721eefd203bec81a60R86There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've restored the
super.disable()
andsuper.enable()
calls, to allow InstrumentationBase to maintain its internalthis._enabled
setting.