Skip to content

Commit d131a04

Browse files
authored
feat(crud): telemetry for bulk operations COMPASS-7388 (#5178)
* telemetry for bulk operations * minus the .only * add isUpdateQuery to recent and favourite query events * skip the clipboard test where it won't work
1 parent 026e903 commit d131a04

File tree

7 files changed

+125
-17
lines changed

7 files changed

+125
-17
lines changed

packages/compass-crud/src/components/bulk-delete-modal.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const documentContainerStyles = css({
3737
});
3838

3939
const modalBodySpacingStyles = css({
40-
marginTop: spacing[3],
40+
marginTop: spacing[3] - spacing[1], // see queryBarStyles below
4141
paddingLeft: spacing[5],
4242
display: 'flex',
4343
flexDirection: 'column',
@@ -49,6 +49,7 @@ const queryBarStyles = css({
4949
flexDirection: 'row',
5050
alignItems: 'center',
5151
gap: spacing[3],
52+
marginTop: spacing[1], // don't cut off the focus/hover ring on the Export button
5253
});
5354

5455
const exportToLanguageButtonStyles = css({

packages/compass-crud/src/stores/crud-store.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,10 @@ class CrudStoreImpl
11021102
}
11031103

11041104
async openBulkUpdateDialog() {
1105+
track('Bulk Update Opened', {
1106+
isUpdatePreviewSupported: this.state.isUpdatePreviewSupported,
1107+
});
1108+
11051109
await this.updateBulkUpdatePreview('{ $set: { } }');
11061110
this.setState({
11071111
bulkUpdate: {
@@ -1224,6 +1228,10 @@ class CrudStoreImpl
12241228
}
12251229

12261230
async runBulkUpdate() {
1231+
track('Bulk Update Executed', {
1232+
isUpdatePreviewSupported: this.state.isUpdatePreviewSupported,
1233+
});
1234+
12271235
this.closeBulkUpdateDialog();
12281236

12291237
// keep the filter count around for the duration of the toast
@@ -1826,6 +1834,8 @@ class CrudStoreImpl
18261834
}
18271835

18281836
openBulkDeleteDialog() {
1837+
track('Bulk Delete Opened');
1838+
18291839
const PREVIEW_DOCS = 5;
18301840

18311841
this.setState({
@@ -1880,6 +1890,8 @@ class CrudStoreImpl
18801890
}
18811891

18821892
async runBulkDelete() {
1893+
track('Bulk Delete Executed');
1894+
18831895
const { affected } = this.state.bulkDelete;
18841896
this.closeBulkDeleteDialog();
18851897

@@ -1919,6 +1931,10 @@ class CrudStoreImpl
19191931
}
19201932

19211933
async saveUpdateQuery(name: string): Promise<void> {
1934+
track('Bulk Update Favorited', {
1935+
isUpdatePreviewSupported: this.state.isUpdatePreviewSupported,
1936+
});
1937+
19221938
const { filter } = this.state.query;
19231939
let update;
19241940
try {

packages/compass-e2e-tests/tests/collection-bulk-delete.test.ts

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ describe('Bulk Delete', () => {
3636
});
3737

3838
it('deletes documents matching a filter', async function () {
39-
//const telemetryEntry = await browser.listenForTelemetryEvents(telemetry);
39+
const telemetryEntry = await browser.listenForTelemetryEvents(telemetry);
4040

4141
// Set a query that we'll use.
4242
await browser.runFindOperation('Documents', '{ i: 5 }');
@@ -45,6 +45,10 @@ describe('Bulk Delete', () => {
4545
await browser.clickVisible(Selectors.OpenBulkDeleteButton);
4646
await browser.$(Selectors.BulkDeleteModal).waitForDisplayed();
4747

48+
// Check the telemetry
49+
const openedEvent = await telemetryEntry('Bulk Delete Opened');
50+
expect(openedEvent).to.deep.equal({});
51+
4852
// Make sure the query is shown in the modal.
4953
expect(
5054
await browser.$(Selectors.BulkDeleteModalReadonlyFilter).getText()
@@ -71,6 +75,10 @@ describe('Bulk Delete', () => {
7175
await browser.clickVisible(Selectors.ConfirmationModalConfirmButton());
7276
await browser.runFindOperation('Documents', '{ i: 5 }');
7377

78+
// Check the telemetry
79+
const executedEvent = await telemetryEntry('Bulk Delete Executed');
80+
expect(executedEvent).to.deep.equal({});
81+
7482
// The success toast is displayed
7583
await browser.$(Selectors.BulkDeleteSuccessToast).waitForDisplayed();
7684

@@ -93,8 +101,6 @@ describe('Bulk Delete', () => {
93101
});
94102

95103
it('does not delete documents when cancelled', async function () {
96-
//const telemetryEntry = await browser.listenForTelemetryEvents(telemetry);
97-
98104
// Set a query that we'll use.
99105
await browser.runFindOperation('Documents', '{ i: 5 }');
100106

@@ -129,4 +135,52 @@ describe('Bulk Delete', () => {
129135
await browser.$(Selectors.DocumentListActionBarMessage).getText()
130136
).to.equal('1 – 1 of 1');
131137
});
138+
139+
it('can export a delete query', async function () {
140+
if (process.env.COMPASS_E2E_DISABLE_CLIPBOARD_USAGE === 'true') {
141+
this.skip();
142+
}
143+
144+
const telemetryEntry = await browser.listenForTelemetryEvents(telemetry);
145+
146+
// Set a query that we'll use.
147+
await browser.runFindOperation('Documents', '{ i: 5 }');
148+
149+
// Open the modal.
150+
await browser.clickVisible(Selectors.OpenBulkDeleteButton);
151+
await browser.$(Selectors.BulkDeleteModal).waitForDisplayed();
152+
153+
// Click the export button
154+
await browser.clickVisible(Selectors.BulkDeleteModalExportButton);
155+
156+
const openedEvent = await telemetryEntry('Delete Export Opened');
157+
expect(openedEvent).to.deep.equal({});
158+
159+
const text = await browser.exportToLanguage('Python', {
160+
includeImportStatements: true,
161+
includeDriverSyntax: true,
162+
useBuilders: false,
163+
});
164+
expect(text).to.equal(`from pymongo import MongoClient
165+
166+
# Requires the PyMongo package.
167+
# https://api.mongodb.com/python/current
168+
169+
client = MongoClient('mongodb://localhost:27091/test')
170+
filter={
171+
'i': 5
172+
}
173+
174+
result = client['test']['numbers'].delete_many(
175+
filter=filter
176+
)`);
177+
178+
const exportedEvent = await telemetryEntry('Delete Exported');
179+
expect(exportedEvent).to.deep.equal({
180+
language: 'python',
181+
with_builders: false,
182+
with_drivers_syntax: true,
183+
with_import_statements: true,
184+
});
185+
});
132186
});

packages/compass-e2e-tests/tests/collection-bulk-update.test.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ describe('Bulk Update', () => {
3636
});
3737

3838
it('updates documents matching a filter', async function () {
39-
//const telemetryEntry = await browser.listenForTelemetryEvents(telemetry);
39+
const telemetryEntry = await browser.listenForTelemetryEvents(telemetry);
4040

4141
// Set a query that we'll use.
4242
await browser.runFindOperation('Documents', '{ i: 5 }');
@@ -45,6 +45,12 @@ describe('Bulk Update', () => {
4545
await browser.clickVisible(Selectors.OpenBulkUpdateButton);
4646
await browser.$(Selectors.BulkUpdateModal).waitForDisplayed();
4747

48+
// Check the telemetry
49+
const openedEvent = await telemetryEntry('Bulk Update Opened');
50+
expect(openedEvent).to.deep.equal({
51+
isUpdatePreviewSupported: true,
52+
});
53+
4854
// Make sure the query is shown in the modal.
4955
expect(
5056
await browser.$(Selectors.BulkUpdateReadonlyFilter).getText()
@@ -101,7 +107,11 @@ describe('Bulk Update', () => {
101107
.$(Selectors.BulkUpdateSuccessToast)
102108
.waitForDisplayed({ reverse: true });
103109

104-
// TODO(COMPASS-7388): Check the telemetry once we add it
110+
// Check the telemetry
111+
const executedEvent = await telemetryEntry('Bulk Update Executed');
112+
expect(executedEvent).to.deep.equal({
113+
isUpdatePreviewSupported: true,
114+
});
105115

106116
await browser.runFindOperation('Documents', '{ i: 5, foo: "bar" }');
107117
const modifiedDocument = await browser.$(Selectors.DocumentListEntry);
@@ -111,6 +121,8 @@ describe('Bulk Update', () => {
111121
});
112122

113123
it('can save an update query as a favourite and return to it', async function () {
124+
const telemetryEntry = await browser.listenForTelemetryEvents(telemetry);
125+
114126
// Set a query that we'll use.
115127
await browser.runFindOperation('Documents', '{ i: { $gt: 5 } }');
116128

@@ -136,6 +148,12 @@ describe('Bulk Update', () => {
136148
await browser.$(Selectors.BulkUpdateFavouriteSaveButton).waitForEnabled();
137149
await browser.clickVisible(Selectors.BulkUpdateFavouriteSaveButton);
138150

151+
// Check the telemetry
152+
const favoritedEvent = await telemetryEntry('Bulk Update Favorited');
153+
expect(favoritedEvent).to.deep.equal({
154+
isUpdatePreviewSupported: true,
155+
});
156+
139157
// Close the modal
140158
await browser.clickVisible(Selectors.BulkUpdateCancelButton);
141159

packages/compass-export-to-language/src/components/modal.tsx

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,21 +151,36 @@ const ExportToLanguageModal: React.FunctionComponent<
151151
const [wasOpen, setWasOpen] = useState(false);
152152

153153
useEffect(() => {
154+
const trackingEvent =
155+
mode === 'Update Query'
156+
? 'Update Export Opened'
157+
: mode === 'Delete Query'
158+
? 'Delete Export Opened'
159+
: mode === 'Query'
160+
? 'Query Export Opened'
161+
: 'Aggregation Export Opened';
162+
154163
if (modalOpen && !wasOpen) {
155-
track(
156-
mode === 'Query' ? 'Query Export Opened' : 'Aggregation Export Opened',
157-
{
158-
...stageCountForTelemetry(inputExpression),
159-
}
160-
);
164+
track(trackingEvent, {
165+
...stageCountForTelemetry(inputExpression),
166+
});
161167
track('Screen', { name: 'export_to_language_modal' });
162168
}
163169

164170
setWasOpen(modalOpen);
165171
}, [modalOpen, wasOpen, mode, inputExpression]);
166172

167173
function trackCopiedOutput() {
168-
track(mode === 'Query' ? 'Query Exported' : 'Aggregation Exported', {
174+
const trackingEvent =
175+
mode === 'Update Query'
176+
? 'Update Exported'
177+
: mode === 'Delete Query'
178+
? 'Delete Exported'
179+
: mode === 'Query'
180+
? 'Query Exported'
181+
: 'Aggregation Exported';
182+
183+
track(trackingEvent, {
169184
language: outputLanguage,
170185
with_import_statements: includeImports,
171186
with_drivers_syntax: includeDrivers,

packages/compass-query-bar/src/components/query-history/favorite-list.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const FavoriteItem = ({
4646
track('Query History Favorite Used', {
4747
id: query._id,
4848
screen: 'documents',
49+
isUpdateQuery,
4950
});
5051

5152
if (isDisabled) {
@@ -70,9 +71,10 @@ const FavoriteItem = ({
7071
track('Query History Favorite Removed', {
7172
id: query._id,
7273
screen: 'documents',
74+
isUpdateQuery,
7375
});
7476
onDelete(query._id);
75-
}, [onDelete, query._id]);
77+
}, [onDelete, query._id, isUpdateQuery]);
7678

7779
return (
7880
<QueryItemCard

packages/compass-query-bar/src/components/query-history/recent-list.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ const RecentItem = ({
6161
onUpdateRecentChoosen();
6262
}
6363

64-
track('Query History Recent Used');
64+
track('Query History Recent Used', {
65+
isUpdateQuery,
66+
});
6567
onApply(attributes);
6668
}, [isDisabled, isUpdateQuery, onApply, attributes, onUpdateRecentChoosen]);
6769

@@ -79,10 +81,10 @@ const RecentItem = ({
7981

8082
const onSaveQuery = useCallback(
8183
(name: string) => {
82-
track('Query History Favorite Added');
84+
track('Query History Favorite Added', { isUpdateQuery });
8385
void onFavorite(query, name);
8486
},
85-
[query, onFavorite]
87+
[query, onFavorite, isUpdateQuery]
8688
);
8789

8890
return (

0 commit comments

Comments
 (0)