Skip to content

Commit 3d0d04a

Browse files
nataliadelmarndelmar_cisco
andauthored
feat(metrics/telemetryOptOut): add automatic and manual switches (#5085)
Co-authored-by: ndelmar_cisco <ndelmar@cisco.com>
1 parent 7e274bf commit 3d0d04a

6 files changed

Lines changed: 214 additions & 102 deletions

File tree

packages/@webex/internal-plugin-metrics/src/call-diagnostic/call-diagnostic-metrics-batcher.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,17 +90,7 @@ const CallDiagnosticEventsBatcher = Batcher.extend({
9090
}
9191

9292
if (statusCode === 200) {
93-
if (
94-
this.webex.internal.newMetrics?.callDiagnosticMetrics?.getTelemetryOptOut() === undefined
95-
) {
96-
// If telemetry opt-out is not set, we can set it to 'automatic' on a 200 response. 'manual' opt out takes precedence over 'automatic' opt out.
97-
this.webex.internal.newMetrics?.callDiagnosticMetrics?.setTelemetryOptOut('automatic');
98-
}
99-
} else if (
100-
this.webex.internal.newMetrics?.callDiagnosticMetrics?.getTelemetryOptOut() === 'automatic'
101-
) {
102-
// If we had set the telemetry opt-out to 'automatic' and the request now responds with something other than 200, we should revert it back to undefined.
103-
this.webex.internal.newMetrics?.callDiagnosticMetrics?.setTelemetryOptOut(undefined);
93+
this.webex.internal.newMetrics?.callDiagnosticMetrics?.setIsTelemetryOptOutAutomatic(true);
10494
}
10595
},
10696
});

packages/@webex/internal-plugin-metrics/src/call-diagnostic/call-diagnostic-metrics.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
108108
private isMercuryConnected = false;
109109
private eventLimitTracker: Map<string, number> = new Map();
110110
private eventLimitWarningsLogged: Set<string> = new Set();
111-
private telemetryOptOut: NonNullable<ClientEventPayload>['telemetryOptOut'] = undefined;
111+
private isTelemetryOptOutManual = false;
112+
private isTelemetryOptOutAutomatic = false;
112113

113114
// the default validator before piping an event to the batcher
114115
// this function can be overridden by the user
@@ -151,15 +152,30 @@ export default class CallDiagnosticMetrics extends StatelessWebexPlugin {
151152
* @returns one of 'manual', 'automatic', undefined
152153
*/
153154
public getTelemetryOptOut() {
154-
return this.telemetryOptOut;
155+
if (this.isTelemetryOptOutManual) {
156+
return 'manual';
157+
}
158+
if (this.isTelemetryOptOutAutomatic) {
159+
return 'automatic';
160+
}
161+
162+
return undefined;
163+
}
164+
165+
/**
166+
* Sets the manual telemetry opt-out status for the current user
167+
* @param value - boolean value indicating manual telemetry opt-out status
168+
*/
169+
public setIsTelemetryOptOutManual(value: boolean) {
170+
this.isTelemetryOptOutManual = value;
155171
}
156172

157173
/**
158-
* Sets the telemetryOptOut value of the current user
159-
* @param value - one of 'manual', 'automatic', undefined
174+
* Sets the automatic telemetry opt-out status for the current user
175+
* @param value - boolean value indicating automatic telemetry opt-out status
160176
*/
161-
public setTelemetryOptOut(value: NonNullable<ClientEventPayload>['telemetryOptOut']) {
162-
this.telemetryOptOut = value;
177+
public setIsTelemetryOptOutAutomatic(value: boolean) {
178+
this.isTelemetryOptOutAutomatic = value;
163179
}
164180

165181
/**

packages/@webex/internal-plugin-metrics/src/prelogin-metrics-batcher.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -113,17 +113,7 @@ const PreLoginMetricsBatcher = Batcher.extend({
113113
}
114114

115115
if (statusCode === 200) {
116-
if (
117-
this.webex.internal.newMetrics?.callDiagnosticMetrics?.getTelemetryOptOut() === undefined
118-
) {
119-
// If telemetry opt-out is not set, we can set it to 'automatic' on a 200 response. 'manual' opt out takes precedence over 'automatic' opt out.
120-
this.webex.internal.newMetrics?.callDiagnosticMetrics?.setTelemetryOptOut('automatic');
121-
}
122-
} else if (
123-
this.webex.internal.newMetrics?.callDiagnosticMetrics?.getTelemetryOptOut() === 'automatic'
124-
) {
125-
// If we had set the telemetry opt-out to 'automatic' and the request now responds with something other than 200, we should revert it back to undefined.
126-
this.webex.internal.newMetrics?.callDiagnosticMetrics?.setTelemetryOptOut(undefined);
116+
this.webex.internal.newMetrics?.callDiagnosticMetrics?.setIsTelemetryOptOutAutomatic(true);
127117
}
128118
},
129119
});

packages/@webex/internal-plugin-metrics/test/unit/spec/call-diagnostic/call-diagnostic-metrics-batcher.ts

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -593,45 +593,64 @@ describe('plugin-metrics', () => {
593593
});
594594

595595
describe('#handleHttpResponseStatus', () => {
596-
[
597-
{shouldMark: true, statusCode: 200, currentTelemetryOptOut: 'automatic', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
598-
{shouldMark: true, statusCode: 200, currentTelemetryOptOut: 'manual', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
599-
{shouldMark: true, statusCode: 200, currentTelemetryOptOut: undefined, shouldCallSetTelemetryOptOut: true, expectedSetTelemetryOptOutArg: 'automatic'},
600-
601-
{shouldMark: true, statusCode: 201, currentTelemetryOptOut: 'automatic', shouldCallSetTelemetryOptOut: true, expectedSetTelemetryOptOutArg: undefined},
602-
{shouldMark: true, statusCode: 202, currentTelemetryOptOut: 'manual', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
603-
{shouldMark: true, statusCode: 203, currentTelemetryOptOut: undefined, shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
604-
605-
{shouldMark: false, statusCode: 200, currentTelemetryOptOut: 'automatic', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
606-
{shouldMark: false, statusCode: 200, currentTelemetryOptOut: 'manual', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
607-
{shouldMark: false, statusCode: 200, currentTelemetryOptOut: undefined, shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
608-
609-
{shouldMark: false, statusCode: 201, currentTelemetryOptOut: 'automatic', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
610-
{shouldMark: false, statusCode: 202, currentTelemetryOptOut: 'manual', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
611-
{shouldMark: false, statusCode: 203, currentTelemetryOptOut: undefined, shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
612-
].forEach(({shouldMark, statusCode, currentTelemetryOptOut, shouldCallSetTelemetryOptOut, expectedSetTelemetryOptOutArg}) => {
613-
it(`should call setTelemetryOptOut ${shouldCallSetTelemetryOptOut ? 'with ' + expectedSetTelemetryOptOutArg : 'not at all'} when shouldMark is ${shouldMark}, statusCode is ${statusCode} and currentTelemetryOptOut is ${currentTelemetryOptOut}`, () => {
614-
webex.internal.newMetrics.callDiagnosticMetrics.setTelemetryOptOut = sinon.stub();
615-
webex.internal.newMetrics.callDiagnosticMetrics.getTelemetryOptOut = sinon
616-
.stub()
617-
.returns(currentTelemetryOptOut);
596+
let setIsTelemetryOptOutAutomaticStub;
597+
598+
beforeEach(() => {
599+
setIsTelemetryOptOutAutomaticStub = sinon.stub(
600+
webex.internal.newMetrics.callDiagnosticMetrics,
601+
'setIsTelemetryOptOutAutomatic'
602+
);
603+
});
604+
605+
[201, 400, 503, undefined].forEach((statusCode) => {
606+
it(`does not call setIsTelemetryOptOutAutomatic() when statusCode is ${statusCode} and markTelemetryOptOutOnResponse is true`, () => {
607+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.handleHttpResponseStatus(
608+
statusCode,
609+
[{markTelemetryOptOutOnResponse: true}]
610+
);
611+
612+
assert.notCalled(setIsTelemetryOptOutAutomaticStub);
613+
});
614+
});
615+
616+
it('calls setIsTelemetryOptOutAutomatic(true) when statusCode is 200 and markTelemetryOptOutOnResponse is true', () => {
617+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.handleHttpResponseStatus(
618+
200,
619+
[{markTelemetryOptOutOnResponse: true}]
620+
);
621+
622+
assert.calledOnce(setIsTelemetryOptOutAutomaticStub);
623+
assert.calledWithExactly(setIsTelemetryOptOutAutomaticStub, true);
624+
});
618625

626+
[200, 201, 400, 503, undefined].forEach((statusCode) => {
627+
it(`does not call setIsTelemetryOptOutAutomatic when shouldMark is false (statusCode: ${statusCode})`, () => {
619628
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.handleHttpResponseStatus(
620629
statusCode,
621-
shouldMark ? [{markTelemetryOptOutOnResponse: true}] : [{markTelemetryOptOutOnResponse: false}]
630+
[{markTelemetryOptOutOnResponse: false}]
622631
);
623632

624-
if (shouldCallSetTelemetryOptOut) {
625-
assert.calledOnce(webex.internal.newMetrics.callDiagnosticMetrics.setTelemetryOptOut);
626-
assert.deepEqual(
627-
webex.internal.newMetrics.callDiagnosticMetrics.setTelemetryOptOut.getCalls()[0].args[0],
628-
expectedSetTelemetryOptOutArg
629-
);
630-
} else {
631-
assert.notCalled(webex.internal.newMetrics.callDiagnosticMetrics.setTelemetryOptOut);
632-
}
633+
assert.notCalled(setIsTelemetryOptOutAutomaticStub);
633634
});
634-
})
635+
});
636+
637+
it('does not call setIsTelemetryOptOutAutomatic when payload is empty', () => {
638+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.handleHttpResponseStatus(
639+
200,
640+
[]
641+
);
642+
643+
assert.notCalled(setIsTelemetryOptOutAutomaticStub);
644+
});
645+
646+
it('does not call setIsTelemetryOptOutAutomatic when payload is not an array', () => {
647+
webex.internal.newMetrics.callDiagnosticMetrics.callDiagnosticEventsBatcher.handleHttpResponseStatus(
648+
200,
649+
null
650+
);
651+
652+
assert.notCalled(setIsTelemetryOptOutAutomaticStub);
653+
});
635654
});
636655
});
637656
});

packages/@webex/internal-plugin-metrics/test/unit/spec/call-diagnostic/call-diagnostic-metrics.ts

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4035,15 +4035,93 @@ describe('internal-plugin-metrics', () => {
40354035
});
40364036

40374037
describe('#getTelemetryOptOut', () => {
4038-
['manual', 'automatic', undefined].forEach((telemetryOptOut) => {
4039-
it(`returns ${telemetryOptOut} if telemetryOptOut is ${telemetryOptOut}`, () => {
4040-
cd.setTelemetryOptOut(telemetryOptOut);
4041-
assert.deepEqual(cd.getTelemetryOptOut(), telemetryOptOut);
4042-
});
4038+
it('returns "manual" when manual telemetry opt-out is enabled', () => {
4039+
cd.setIsTelemetryOptOutManual(true);
4040+
assert.equal(cd.getTelemetryOptOut(), 'manual');
4041+
});
40434042

4044-
it('returns undefined if telemetryOptOut is not set', () => {
4045-
assert.deepEqual(cd.getTelemetryOptOut(), undefined);
4046-
});
4043+
it('returns "automatic" when automatic telemetry opt-out is enabled', () => {
4044+
cd.setIsTelemetryOptOutAutomatic(true);
4045+
assert.equal(cd.getTelemetryOptOut(), 'automatic');
4046+
});
4047+
4048+
it('returns "manual" when manual opt-out takes precedence over automatic', () => {
4049+
cd.setIsTelemetryOptOutManual(true);
4050+
cd.setIsTelemetryOptOutAutomatic(true);
4051+
assert.equal(cd.getTelemetryOptOut(), 'manual');
4052+
});
4053+
4054+
it('returns undefined when neither manual nor automatic opt-out is set', () => {
4055+
assert.isUndefined(cd.getTelemetryOptOut());
4056+
});
4057+
4058+
it('returns undefined after disabling manual opt-out', () => {
4059+
cd.setIsTelemetryOptOutManual(true);
4060+
cd.setIsTelemetryOptOutManual(false);
4061+
assert.isUndefined(cd.getTelemetryOptOut());
4062+
});
4063+
});
4064+
4065+
describe('#setIsTelemetryOptOutManual', () => {
4066+
it('sets manual telemetry opt-out to true', () => {
4067+
cd.setIsTelemetryOptOutManual(true);
4068+
assert.equal(cd.getTelemetryOptOut(), 'manual');
4069+
});
4070+
4071+
it('sets manual telemetry opt-out to false', () => {
4072+
cd.setIsTelemetryOptOutManual(true);
4073+
cd.setIsTelemetryOptOutManual(false);
4074+
assert.isUndefined(cd.getTelemetryOptOut());
4075+
});
4076+
4077+
it('can toggle manual telemetry opt-out multiple times', () => {
4078+
cd.setIsTelemetryOptOutManual(true);
4079+
assert.equal(cd.getTelemetryOptOut(), 'manual');
4080+
4081+
cd.setIsTelemetryOptOutManual(false);
4082+
assert.isUndefined(cd.getTelemetryOptOut());
4083+
4084+
cd.setIsTelemetryOptOutManual(true);
4085+
assert.equal(cd.getTelemetryOptOut(), 'manual');
4086+
});
4087+
4088+
it('manual opt-out takes precedence when automatic is also set', () => {
4089+
cd.setIsTelemetryOptOutAutomatic(true);
4090+
cd.setIsTelemetryOptOutManual(true);
4091+
assert.equal(cd.getTelemetryOptOut(), 'manual');
4092+
});
4093+
});
4094+
4095+
describe('#setIsTelemetryOptOutAutomatic', () => {
4096+
it('sets automatic telemetry opt-out to true', () => {
4097+
cd.setIsTelemetryOptOutAutomatic(true);
4098+
assert.equal(cd.getTelemetryOptOut(), 'automatic');
4099+
});
4100+
4101+
it('sets automatic telemetry opt-out to false', () => {
4102+
cd.setIsTelemetryOptOutAutomatic(true);
4103+
cd.setIsTelemetryOptOutAutomatic(false);
4104+
assert.isUndefined(cd.getTelemetryOptOut());
4105+
});
4106+
4107+
it('can toggle automatic telemetry opt-out multiple times', () => {
4108+
cd.setIsTelemetryOptOutAutomatic(true);
4109+
assert.equal(cd.getTelemetryOptOut(), 'automatic');
4110+
4111+
cd.setIsTelemetryOptOutAutomatic(false);
4112+
assert.isUndefined(cd.getTelemetryOptOut());
4113+
4114+
cd.setIsTelemetryOptOutAutomatic(true);
4115+
assert.equal(cd.getTelemetryOptOut(), 'automatic');
4116+
});
4117+
4118+
it('does not override manual opt-out', () => {
4119+
cd.setIsTelemetryOptOutManual(true);
4120+
cd.setIsTelemetryOptOutAutomatic(true);
4121+
assert.equal(cd.getTelemetryOptOut(), 'manual');
4122+
4123+
cd.setIsTelemetryOptOutAutomatic(false);
4124+
assert.equal(cd.getTelemetryOptOut(), 'manual');
40474125
});
40484126
});
40494127

packages/@webex/internal-plugin-metrics/test/unit/spec/prelogin-metrics-batcher.ts

Lines changed: 52 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -415,45 +415,64 @@ describe('internal-plugin-metrics', () => {
415415
})
416416

417417
describe('#handleHttpResponseStatus', () => {
418-
[
419-
{shouldMark: true, statusCode: 200, currentTelemetryOptOut: 'automatic', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
420-
{shouldMark: true, statusCode: 200, currentTelemetryOptOut: 'manual', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
421-
{shouldMark: true, statusCode: 200, currentTelemetryOptOut: undefined, shouldCallSetTelemetryOptOut: true, expectedSetTelemetryOptOutArg: 'automatic'},
422-
423-
{shouldMark: true, statusCode: 201, currentTelemetryOptOut: 'automatic', shouldCallSetTelemetryOptOut: true, expectedSetTelemetryOptOutArg: undefined},
424-
{shouldMark: true, statusCode: 202, currentTelemetryOptOut: 'manual', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
425-
{shouldMark: true, statusCode: 203, currentTelemetryOptOut: undefined, shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
426-
427-
{shouldMark: false, statusCode: 200, currentTelemetryOptOut: 'automatic', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
428-
{shouldMark: false, statusCode: 200, currentTelemetryOptOut: 'manual', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
429-
{shouldMark: false, statusCode: 200, currentTelemetryOptOut: undefined, shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
430-
431-
{shouldMark: false, statusCode: 201, currentTelemetryOptOut: 'automatic', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
432-
{shouldMark: false, statusCode: 202, currentTelemetryOptOut: 'manual', shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
433-
{shouldMark: false, statusCode: 203, currentTelemetryOptOut: undefined, shouldCallSetTelemetryOptOut: false, expectedSetTelemetryOptOutArg: 'N/A'},
434-
].forEach(({shouldMark, statusCode, currentTelemetryOptOut, shouldCallSetTelemetryOptOut, expectedSetTelemetryOptOutArg}) => {
435-
it(`should call setTelemetryOptOut ${shouldCallSetTelemetryOptOut ? 'with ' + expectedSetTelemetryOptOutArg : 'not at all'} when shouldMark is ${shouldMark}, statusCode is ${statusCode} and currentTelemetryOptOut is ${currentTelemetryOptOut}`, () => {
436-
webex.internal.newMetrics.callDiagnosticMetrics.setTelemetryOptOut = sinon.stub();
437-
webex.internal.newMetrics.callDiagnosticMetrics.getTelemetryOptOut = sinon
438-
.stub()
439-
.returns(currentTelemetryOptOut);
418+
let setIsTelemetryOptOutAutomaticStub;
440419

420+
beforeEach(() => {
421+
setIsTelemetryOptOutAutomaticStub = sinon.stub(
422+
webex.internal.newMetrics.callDiagnosticMetrics,
423+
'setIsTelemetryOptOutAutomatic'
424+
);
425+
});
426+
427+
[201, 400, 503, undefined].forEach((statusCode) => {
428+
it(`does not call setIsTelemetryOptOutAutomatic when shouldMark is true and statusCode is ${statusCode}`, () => {
441429
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.handleHttpResponseStatus(
442430
statusCode,
443-
shouldMark ? [{markTelemetryOptOutOnResponse: true}] : [{markTelemetryOptOutOnResponse: false}]
431+
[{markTelemetryOptOutOnResponse: true}]
444432
);
445433

446-
if (shouldCallSetTelemetryOptOut) {
447-
assert.calledOnce(webex.internal.newMetrics.callDiagnosticMetrics.setTelemetryOptOut);
448-
assert.deepEqual(
449-
webex.internal.newMetrics.callDiagnosticMetrics.setTelemetryOptOut.getCalls()[0].args[0],
450-
expectedSetTelemetryOptOutArg
451-
);
452-
} else {
453-
assert.notCalled(webex.internal.newMetrics.callDiagnosticMetrics.setTelemetryOptOut);
454-
}
434+
assert.notCalled(setIsTelemetryOptOutAutomaticStub);
455435
});
456-
})
436+
});
437+
438+
it('calls setIsTelemetryOptOutAutomatic(true) when statusCode is 200 and markTelemetryOptOutOnResponse is true', () => {
439+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.handleHttpResponseStatus(
440+
200,
441+
[{markTelemetryOptOutOnResponse: true}]
442+
);
443+
444+
assert.calledOnce(setIsTelemetryOptOutAutomaticStub);
445+
assert.calledWithExactly(setIsTelemetryOptOutAutomaticStub, true);
446+
});
447+
448+
[200, 201, 400, 503, undefined].forEach((statusCode) => {
449+
it(`does not call setIsTelemetryOptOutAutomatic when shouldMark is false (statusCode: ${statusCode})`, () => {
450+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.handleHttpResponseStatus(
451+
statusCode,
452+
[{markTelemetryOptOutOnResponse: false}]
453+
);
454+
455+
assert.notCalled(setIsTelemetryOptOutAutomaticStub);
456+
});
457+
});
458+
459+
it('does not call setIsTelemetryOptOutAutomatic when payload is empty', () => {
460+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.handleHttpResponseStatus(
461+
200,
462+
[]
463+
);
464+
465+
assert.notCalled(setIsTelemetryOptOutAutomaticStub);
466+
});
467+
468+
it('does not call setIsTelemetryOptOutAutomatic when payload is not an array', () => {
469+
webex.internal.newMetrics.callDiagnosticMetrics.preLoginMetricsBatcher.handleHttpResponseStatus(
470+
200,
471+
null
472+
);
473+
474+
assert.notCalled(setIsTelemetryOptOutAutomaticStub);
475+
});
457476
});
458477
});
459478
});

0 commit comments

Comments
 (0)