Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 22 additions & 86 deletions src/connectionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,11 @@ import { EventEmitter } from 'events';
import { StorageController, StorageVariables } from './storage';
import { SavedConnection, StorageScope } from './storage/storageController';
import { getNodeModule } from './utils/getNodeModule';
import TelemetryController, {
TelemetryEventTypes
} from './telemetry/telemetryController';
import { getCloudInfo } from 'mongodb-cloud-info';
import TelemetryController from './telemetry/telemetryController';

const { name, version } = require('../package.json');
const log = createLogger('connection controller');
const MAX_CONNECTION_NAME_LENGTH = 512;
const ATLAS_REGEX = /mongodb.net[:/]/i;
const LOCALHOST_REGEX = /(localhost|127\.0\.0\.1)/i;

type KeyTar = typeof keytarType;

Expand Down Expand Up @@ -245,6 +240,17 @@ export default class ConnectionController {
});
};

public sendTelemetry(
newDataService: DataServiceType,
connectionType: ConnectionTypes
) {
// Send metrics to Segment
this._telemetryController.trackNewConnection(
newDataService,
connectionType
);
}

public parseNewConnectionAndConnect = (
newConnectionModel: ConnectionModelType
): Promise<boolean> => {
Expand Down Expand Up @@ -309,82 +315,13 @@ export default class ConnectionController {
return resolve(false);
}

resolve(true);
return resolve(true);
},
reject
);
});
};

public async getCloudInfoFromDataService(firstServerHostname: string) {
const cloudInfo = await getCloudInfo(firstServerHostname);
let isPublicCloud = false;
let publicCloudName: string | null = null;

if (cloudInfo.isAws) {
isPublicCloud = true;
publicCloudName = 'aws';
} else if (cloudInfo.isGcp) {
isPublicCloud = true;
publicCloudName = 'gcp';
} else if (cloudInfo.isAzure) {
isPublicCloud = true;
publicCloudName = 'azure';
}

return { isPublicCloud, publicCloudName };
}

private async sendTelemetry(
dataService: DataServiceType,
connectionType: ConnectionTypes
): Promise<void> {
dataService.instance({}, async (error: any, data: any) => {
if (error) {
log.error('TELEMETRY data service error', error);
}

if (data) {
try {
const firstServerHostname = dataService.client.model.hosts[0].host;
const cloudInfo = await this.getCloudInfoFromDataService(
firstServerHostname
);
const nonGenuineServerName = data.genuineMongoDB.isGenuine
? null
: data.genuineMongoDB.dbType;
const telemetryData = {
is_atlas: !!data.client.s.url.match(ATLAS_REGEX),
is_localhost: !!data.client.s.url.match(LOCALHOST_REGEX),
is_data_lake: data.dataLake.isDataLake,
is_enterprise: data.build.enterprise_module,
is_public_cloud: cloudInfo.isPublicCloud,
public_cloud_name: cloudInfo.publicCloudName,
is_genuine: data.genuineMongoDB.isGenuine,
non_genuine_server_name: nonGenuineServerName,
server_version: data.build.version,
server_arch: data.build.raw.buildEnvironment.target_arch,
server_os: data.build.raw.buildEnvironment.target_os,
is_used_connect_screen:
connectionType === ConnectionTypes.CONNECTION_FORM,
is_used_command_palette:
connectionType === ConnectionTypes.CONNECTION_STRING,
is_used_saved_connection:
connectionType === ConnectionTypes.CONNECTION_ID
};

// Send metrics to Segment
this._telemetryController.track(
TelemetryEventTypes.NEW_CONNECTION,
telemetryData
);
} catch (error) {
log.error('TELEMETRY cloud info error', error);
}
}
});
}

public connect = async (
connectionId: string,
connectionModel: ConnectionModelType,
Expand Down Expand Up @@ -449,9 +386,8 @@ export default class ConnectionController {
this.eventEmitter.emit(DataServiceEventTypes.CONNECTIONS_DID_CHANGE);
this.eventEmitter.emit(DataServiceEventTypes.ACTIVE_CONNECTION_CHANGED);

if (this._telemetryController.needTelemetry()) {
this.sendTelemetry(newDataService, connectionType);
}
// Send metrics to Segment
this.sendTelemetry(newDataService, connectionType);

return resolve(true);
});
Expand Down Expand Up @@ -659,13 +595,13 @@ export default class ConnectionController {
const connectionNameToRemove:
| string
| undefined = await vscode.window.showQuickPick(
connectionIds.map(
(id, index) => `${index + 1}: ${this._connections[id].name}`
),
{
placeHolder: 'Choose a connection to remove...'
}
);
connectionIds.map(
(id, index) => `${index + 1}: ${this._connections[id].name}`
),
{
placeHolder: 'Choose a connection to remove...'
}
);

if (!connectionNameToRemove) {
return Promise.resolve(false);
Expand Down
46 changes: 7 additions & 39 deletions src/editors/playgroundController.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import * as vscode from 'vscode';

import ConnectionController, {
DataServiceEventTypes
} from '../connectionController';
import { LanguageServerController } from '../language';
import TelemetryController, {
TelemetryEventTypes,
TelemetryEventProperties
} from '../telemetry/telemetryController';
import TelemetryController from '../telemetry/telemetryController';
import ActiveConnectionCodeLensProvider from './activeConnectionCodeLensProvider';
import { OutputChannel, ProgressLocation, TextEditor } from 'vscode';
import playgroundTemplate from '../templates/playgroundTemplate';
Expand Down Expand Up @@ -137,43 +133,15 @@ export default class PlaygroundController {
});
}

public prepareTelemetry(res: any): TelemetryEventProperties {
let type = 'other';

if (!res.shellApiType) {
return { type };
}

const shellApiType = res.shellApiType.toLocaleLowerCase();

// See: https://github.com/mongodb-js/mongosh/blob/master/packages/shell-api/src/shell-api.js
if (shellApiType.includes('insert')) {
type = 'insert';
} else if (shellApiType.includes('update')) {
type = 'update';
} else if (shellApiType.includes('delete')) {
type = 'delete';
} else if (shellApiType.includes('aggregation')) {
type = 'aggregation';
} else if (shellApiType.includes('cursor')) {
type = 'query';
}

return { type };
}

public async evaluate(codeToEvaluate: string): Promise<any> {
// Send a request to the language server to execute scripts from a playground
// Send a request to the language server to execute scripts from a playground.
const result = await this._languageServerController.executeAll(
codeToEvaluate
);

if (result && this._telemetryController.needTelemetry()) {
// Send metrics to Segment
this._telemetryController.track(
TelemetryEventTypes.PLAYGROUND_CODE_EXECUTED,
this.prepareTelemetry(result)
);
// Send metrics to Segment.
if (result) {
this._telemetryController.trackPlaygroundCodeExecuted(result);
}

return Promise.resolve(result);
Expand All @@ -196,7 +164,7 @@ export default class PlaygroundController {
},
async (progress, token) => {
token.onCancellationRequested(async () => {
// If a user clicked the cancel button terminate all playground scripts
// If a user clicked the cancel button terminate all playground scripts.
this._languageServerController.cancelAll();
this._outputChannel.clear();
this._outputChannel.show(true);
Expand All @@ -206,7 +174,7 @@ export default class PlaygroundController {

const codeToEvaluate =
this._activeTextEditor?.document.getText() || '';
// Run all playground scripts
// Run all playground scripts.
const result = await this.evaluate(codeToEvaluate);

return resolve(result);
Expand Down
3 changes: 2 additions & 1 deletion src/explorer/explorerController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ export default class ExplorerController {
this._treeView = vscode.window.createTreeView('mongoDB', {
treeDataProvider: this._treeController
});

this._treeController.activateTreeViewEventHandlers(this._treeView);
}
};
Expand Down Expand Up @@ -61,13 +60,15 @@ export default class ExplorerController {
if (this._treeController) {
return this._treeController.refresh();
}

return Promise.reject(new Error('No tree to refresh.'));
}

// Exposed for testing.
public getTreeView(): vscode.TreeView<vscode.TreeItem> | undefined {
return this._treeView;
}

public getTreeController(): ExplorerTreeController {
return this._treeController;
}
Expand Down
15 changes: 4 additions & 11 deletions src/mdbExtensionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import ConnectionController from './connectionController';
import { EditorsController, PlaygroundController } from './editors';
import { ExplorerController, CollectionTreeItem } from './explorer';
import { LanguageServerController } from './language';
import TelemetryController, {
TelemetryEventTypes
} from './telemetry/telemetryController';
import TelemetryController from './telemetry/telemetryController';
import { StatusView } from './views';
import { createLogger } from './logging';
import { StorageController } from './storage';
Expand Down Expand Up @@ -42,7 +40,6 @@ export default class MDBExtensionController implements vscode.Disposable {
connectionController?: ConnectionController
) {
this._context = context;

this._statusView = new StatusView(context);
this._storageController = new StorageController(context);
this._telemetryController = new TelemetryController(
Expand Down Expand Up @@ -136,13 +133,8 @@ export default class MDBExtensionController implements vscode.Disposable {
commandHandler: (...args: any[]) => Promise<boolean>
): void => {
const commandHandlerWithTelemetry = (args: any[]) => {
// Send metrics to Segment
this._telemetryController.track(
TelemetryEventTypes.EXTENSION_COMMAND_RUN,
{
command
}
);
// Send metrics to Segment.
this._telemetryController.trackCommandRun(command);

return commandHandler(args);
};
Expand Down Expand Up @@ -204,6 +196,7 @@ export default class MDBExtensionController implements vscode.Disposable {
return new Promise((resolve, reject) => {
vscode.env.clipboard.writeText(connectionString).then(() => {
vscode.window.showInformationMessage('Copied to clipboard.');

return resolve(true);
}, reject);
});
Expand Down
Loading