diff --git a/README.md b/README.md
index e51a619..cddb44f 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,10 @@ This can be disabled either by setting `OTEL_SERVICE_NAME` or by setting `DASH0_
Additional debug logs can be enabled by setting `DASH0_DEBUG=true`.
+### DASH0_DISABLE
+
+Disables the Dash0 Node.js distribution entirely.
+
### DASH0_ENABLE_FS_INSTRUMENTATION
By default, the instrumentation plug-in `@opentelemetry/instrumentation-fs` is disabled. Set `DASH0_ENABLE_FS_INSTRUMENTATION=true` to enable spans for file system access.
diff --git a/src/index.ts b/src/index.ts
index 4ca8c09..878f98c 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -36,7 +36,11 @@ function init() {
}
}
-init();
+if (process.env.DASH0_DISABLE == null || process.env.DASH0_DISABLE.toLowerCase() !== 'true') {
+ init();
+} else {
+ logProhibitiveError(`The distribution has been disabled by setting DASH0_DISABLE=${process.env.DASH0_DISABLE}.`);
+}
function logProhibitiveError(message: string) {
console.error(`[${prefix}] ${message} OpenTelemetry data will not be sent to Dash0.`);
diff --git a/test/collector/CollectorChildProcessWrapper.ts b/test/collector/CollectorChildProcessWrapper.ts
index 744c7b9..d2dca3a 100644
--- a/test/collector/CollectorChildProcessWrapper.ts
+++ b/test/collector/CollectorChildProcessWrapper.ts
@@ -27,4 +27,8 @@ export default class CollectorChildProcessWrapper extends ChildProcessWrapper {
async fetchTelemetry() {
return await collector().sendRequest({ command: 'telemetry' });
}
+
+ async clear() {
+ await collector().sendRequest({ command: 'clear' });
+ }
}
diff --git a/test/collector/Sink.ts b/test/collector/Sink.ts
index 3b52db7..f7976fe 100644
--- a/test/collector/Sink.ts
+++ b/test/collector/Sink.ts
@@ -64,6 +64,14 @@ export default class Sink {
return this.telemetry;
}
+ clear() {
+ this.telemetry = {
+ traces: [],
+ metrics: [],
+ logs: [],
+ };
+ }
+
printStats() {
console.log(JSON.stringify(this.stats(), null, 2));
}
diff --git a/test/collector/index.ts b/test/collector/index.ts
index dc4baac..2a6445b 100644
--- a/test/collector/index.ts
+++ b/test/collector/index.ts
@@ -34,6 +34,9 @@ function registerIpcMessageListener() {
case 'telemetry':
sendToParentProcess({ id, ...sink.getTelemetry() });
break;
+ case 'clear':
+ sink.clear();
+ break;
default:
console.error(`Unknown message: ${inspect(message)}`);
}
diff --git a/test/integration/rootHooks.ts b/test/integration/rootHooks.ts
index da7dfcc..181ecda 100644
--- a/test/integration/rootHooks.ts
+++ b/test/integration/rootHooks.ts
@@ -21,6 +21,10 @@ export const mochaHooks = {
console.debug('[rootHooks] global mock collector started');
},
+ async beforeEach() {
+ collectorInstance.clear();
+ },
+
async afterAll() {
console.debug('[rootHooks] stopping global mock collector');
await collectorInstance.stop();
diff --git a/test/integration/test.ts b/test/integration/test.ts
index bef1c99..c2828bd 100644
--- a/test/integration/test.ts
+++ b/test/integration/test.ts
@@ -12,9 +12,12 @@ import runCommand from '../util/runCommand';
import waitUntil from '../util/waitUntil';
import ChildProcessWrapper, { defaultAppConfiguration } from './ChildProcessWrapper';
import { collector } from './rootHooks';
+import delay from '../util/delay';
const skipWhenNodeJsVersionIsSmallerThan = '18.0.0';
+const { fail } = expect;
+
const appPort = 1302;
let expectedDistroVersion: number;
@@ -104,7 +107,7 @@ describe('attach', () => {
await appUnderTest.stop();
});
- it('should attach via --require and derive a service name from the package.json file ', async () => {
+ it('should attach via --require and derive a service name from the package.json file', async () => {
await waitUntil(async () => {
const telemetry = await waitForTelemetry();
expectMatchingSpan(
@@ -122,6 +125,37 @@ describe('attach', () => {
});
});
+ describe('disable via DASH0_DISABLE', () => {
+ let appUnderTest: ChildProcessWrapper;
+
+ before(async () => {
+ const appConfiguration = defaultAppConfiguration(appPort);
+ if (!appConfiguration.env) {
+ appConfiguration.env = {};
+ }
+ appConfiguration.env.DASH0_DISABLE = 'true';
+ appUnderTest = new ChildProcessWrapper(appConfiguration);
+ await appUnderTest.start();
+ });
+
+ after(async () => {
+ await appUnderTest.stop();
+ });
+
+ it('should do nothing if disabled', async () => {
+ await delay(1000);
+ const response = await fetch(`http://localhost:${appPort}/ohai`);
+ await delay(2000);
+ expect(response.status).to.equal(200);
+ const responsePayload = await response.json();
+ expect(responsePayload).to.deep.equal({ message: 'We make Observability easy for every developer.' });
+
+ if (await collector().hasTelemetry()) {
+ fail('The collector received telemetry data although it should not have received anything.');
+ }
+ });
+ });
+
async function waitForTelemetry() {
const response = await fetch(`http://localhost:${appPort}/ohai`);
expect(response.status).to.equal(200);