Initial Code Layering (#3788)

* working on formatting

* fixed basic lint errors; starting moving things to their appropriate location

* formatting

* update tslint to match the version of vscode we have

* remove unused code

* work in progress fixing layering

* formatting

* moved connection management service to platform

* formatting

* add missing file

* moving more servies

* formatting

* moving more services

* formatting

* wip

* moving more services

* formatting

* revert back tslint rules

* move css file

* add missing svgs
This commit is contained in:
Anthony Dresser
2019-01-25 14:52:35 -08:00
committed by GitHub
parent c8986464ec
commit ea67859de7
338 changed files with 2036 additions and 7386 deletions

View File

@@ -0,0 +1,179 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import * as sqlops from 'sqlops';
import { INewProfilerState } from 'sql/parts/profiler/editor/profilerState';
const PROFILER_SERVICE_ID = 'profilerService';
export const IProfilerService = createDecorator<IProfilerService>(PROFILER_SERVICE_ID);
export type ProfilerSessionID = string;
export const PROFILER_VIEW_TEMPLATE_SETTINGS = 'profiler.viewTemplates';
export const PROFILER_SESSION_TEMPLATE_SETTINGS = 'profiler.sessionTemplates';
export const PROFILER_SETTINGS = 'profiler';
/**
* A front end provider for a profiler session
*/
export interface IProfilerSession {
/**
* Called by the service when more rows are available to render
*/
onMoreRows(events: sqlops.ProfilerSessionEvents);
/**
* Called by the service when the session is closed unexpectedly
*/
onSessionStopped(events: sqlops.ProfilerSessionStoppedParams);
/**
* Called by the service when a new profiler session is created by the dialog
*/
onProfilerSessionCreated(events: sqlops.ProfilerSessionCreatedParams);
/**
* Called by the service when the session state is changed
*/
onSessionStateChanged(newState: INewProfilerState);
}
/**
* A Profiler Service that handles session communication between the backends and frontends
*/
export interface IProfilerService {
_serviceBrand: any;
/**
* Registers a backend provider for profiler session. ex: mssql
*/
registerProvider(providerId: string, provider: sqlops.ProfilerProvider): void;
/**
* Registers a session with the service that acts as the UI for a profiler session
* @returns An unique id that should be used to make subsequent calls to this service
*/
registerSession(uri: string, connectionProfile: IConnectionProfile, session: IProfilerSession): Promise<ProfilerSessionID>;
/**
* Connects the session specified by the id
*/
connectSession(sessionId: ProfilerSessionID): Thenable<boolean>;
/**
* Disconnected the session specified by the id
*/
disconnectSession(sessionId: ProfilerSessionID): Thenable<boolean>;
/**
* Creates a new session using the given create statement and session name
*/
createSession(id: string, createStatement: string, template: sqlops.ProfilerSessionTemplate): Thenable<boolean>;
/**
* Starts the session specified by the id
*/
startSession(sessionId: ProfilerSessionID, sessionName: string): Thenable<boolean>;
/**
* Pauses the session specified by the id
*/
pauseSession(sessionId: ProfilerSessionID): Thenable<boolean>;
/**
* Stops the session specified by the id
*/
stopSession(sessionId: ProfilerSessionID): Thenable<boolean>;
/**
* Gets a list of running XEvent sessions on the Profiler Session's target
*/
getXEventSessions(sessionId: ProfilerSessionID): Thenable<string[]>;
/**
* The method called by the service provider for when more rows are available to render
*/
onMoreRows(params: sqlops.ProfilerSessionEvents): void;
/**
* The method called by the service provider for when more rows are available to render
*/
onSessionStopped(params: sqlops.ProfilerSessionStoppedParams): void;
/**
* Called by the service when a new profiler session is created by the dialog
*/
onProfilerSessionCreated(events: sqlops.ProfilerSessionCreatedParams);
/**
* Gets a list of the view templates that are specified in the settings
* @param provider An optional string to limit the view templates to a specific provider
* @returns An array of view templates that match the provider passed, if passed, and generic ones (no provider specified),
* otherwise returns all view templates
*/
getViewTemplates(providerId?: string): Array<IProfilerViewTemplate>;
/**
* Gets a list of the session templates that are specified in the settings
* @param provider An optional string to limit the session template to a specific
* @returns An array of session templates that match the provider passed, if passed, and generic ones (no provider specified),
* otherwise returns all session templates
*/
getSessionTemplates(providerId?: string): Array<IProfilerSessionTemplate>;
/**
* Gets the session view state
* @param sessionId The session ID to get the view state for
* @returns Sessions view state
*/
getSessionViewState(sessionId: string): any;
/**
* Launches the dialog for editing the view columns of a profiler session template for the given input
* @param input input object that contains the necessary information which will be modified based on used input
*/
launchColumnEditor(input: ProfilerInput): Thenable<void>;
/**
* Launches the dialog for creating a new XEvent session from a template
* @param input input object that contains the necessary information which will be modified based on used input
*/
launchCreateSessionDialog(input: ProfilerInput): Thenable<void>;
/**
* Launches the dialog for collecting the filter object
* @param input input object
*/
launchFilterSessionDialog(input: ProfilerInput): void;
}
export interface IProfilerSettings {
viewTemplates: Array<IProfilerViewTemplate>;
sessionTemplates: Array<IProfilerSessionTemplate>;
}
export interface IColumnViewTemplate {
name: string;
eventsMapped: Array<string>;
}
export interface IProfilerViewTemplate {
name: string;
columns: Array<IColumnViewTemplate>;
}
export interface IProfilerSessionTemplate {
name: string;
defaultView: string;
createStatement: string;
}
export interface ProfilerFilter {
clauses: ProfilerFilterClause[];
}
export interface ProfilerFilterClause {
field: string;
operator: ProfilerFilterClauseOperator;
value: string;
}
export enum ProfilerFilterClauseOperator {
Equals,
NotEquals,
LessThan,
LessThanOrEquals,
GreaterThan,
GreaterThanOrEquals,
IsNull,
IsNotNull,
Contains,
NotContains,
StartsWith,
NotStartsWith
}

View File

@@ -0,0 +1,242 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IConnectionManagementService, IConnectionCompletionOptions, ConnectionType, RunQueryOnConnectionMode } from 'sql/platform/connection/common/connectionManagement';
import {
ProfilerSessionID, IProfilerSession, IProfilerService, IProfilerViewTemplate, IProfilerSessionTemplate,
PROFILER_SETTINGS, IProfilerSettings
} from './interfaces';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
import { ProfilerColumnEditorDialog } from 'sql/parts/profiler/dialog/profilerColumnEditorDialog';
import * as sqlops from 'sqlops';
import { TPromise } from 'vs/base/common/winjs.base';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { Scope as MementoScope, Memento } from 'vs/workbench/common/memento';
import { ProfilerFilterDialog } from 'sql/parts/profiler/dialog/profilerFilterDialog';
class TwoWayMap<T, K> {
private forwardMap: Map<T, K>;
private reverseMap: Map<K, T>;
constructor() {
this.forwardMap = new Map<T, K>();
this.reverseMap = new Map<K, T>();
}
get(input: T): K {
return this.forwardMap.get(input);
}
reverseGet(input: K): T {
return this.reverseMap.get(input);
}
set(input: T, input2: K): TwoWayMap<T, K> {
this.forwardMap.set(input, input2);
this.reverseMap.set(input2, input);
return this;
}
}
export class ProfilerService implements IProfilerService {
private static readonly PROFILER_SERVICE_UI_STATE_STORAGE_KEY = 'profileservice.uiState';
public _serviceBrand: any;
private _providers = new Map<string, sqlops.ProfilerProvider>();
private _idMap = new TwoWayMap<ProfilerSessionID, string>();
private _sessionMap = new Map<ProfilerSessionID, IProfilerSession>();
private _connectionMap = new Map<ProfilerSessionID, IConnectionProfile>();
private _editColumnDialog: ProfilerColumnEditorDialog;
private _memento: any;
private _context: Memento;
constructor(
@IConnectionManagementService private _connectionService: IConnectionManagementService,
@IConfigurationService public _configurationService: IConfigurationService,
@IInstantiationService private _instantiationService: IInstantiationService,
@INotificationService private _notificationService: INotificationService,
@ICommandService private _commandService: ICommandService,
@IStorageService private _storageService: IStorageService
) {
this._context = new Memento('ProfilerEditor');
this._memento = this._context.getMemento(this._storageService, MementoScope.GLOBAL);
}
public registerProvider(providerId: string, provider: sqlops.ProfilerProvider): void {
this._providers.set(providerId, provider);
}
public async registerSession(uri: string, connectionProfile: IConnectionProfile, session: IProfilerSession): Promise<ProfilerSessionID> {
let options: IConnectionCompletionOptions = {
params: { connectionType: ConnectionType.default, runQueryOnCompletion: RunQueryOnConnectionMode.none, input: undefined },
saveTheConnection: false,
showDashboard: false,
showConnectionDialogOnError: false,
showFirewallRuleOnError: true
};
try {
await this._connectionService.connect(connectionProfile, uri, options);
} catch (connectionError) {
}
this._sessionMap.set(uri, session);
this._connectionMap.set(uri, connectionProfile);
this._idMap.set(uri, uri);
return TPromise.wrap(uri);
}
public onMoreRows(params: sqlops.ProfilerSessionEvents): void {
this._sessionMap.get(this._idMap.reverseGet(params.sessionId)).onMoreRows(params);
}
public onSessionStopped(params: sqlops.ProfilerSessionStoppedParams): void {
this._sessionMap.get(this._idMap.reverseGet(params.ownerUri)).onSessionStopped(params);
}
public onProfilerSessionCreated(params: sqlops.ProfilerSessionCreatedParams): void {
this._sessionMap.get(this._idMap.reverseGet(params.ownerUri)).onProfilerSessionCreated(params);
this.updateMemento(params.ownerUri, { previousSessionName: params.sessionName });
}
public connectSession(id: ProfilerSessionID): Thenable<boolean> {
return this._runAction(id, provider => provider.connectSession(this._idMap.get(id)));
}
public disconnectSession(id: ProfilerSessionID): Thenable<boolean> {
return this._runAction(id, provider => provider.disconnectSession(this._idMap.get(id)));
}
public createSession(id: string, createStatement: string, template: sqlops.ProfilerSessionTemplate): Thenable<boolean> {
return this._runAction(id, provider => provider.createSession(this._idMap.get(id), createStatement, template)).then(() => {
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isRunning: true, isStopped: false, isPaused: false });
return true;
}, (reason) => {
this._notificationService.error(reason.message);
});
}
public startSession(id: ProfilerSessionID, sessionName: string): Thenable<boolean> {
this.updateMemento(id, { previousSessionName: sessionName });
return this._runAction(id, provider => provider.startSession(this._idMap.get(id), sessionName)).then(() => {
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isRunning: true, isStopped: false, isPaused: false });
return true;
}, (reason) => {
this._notificationService.error(reason.message);
});
}
public pauseSession(id: ProfilerSessionID): Thenable<boolean> {
return this._runAction(id, provider => provider.pauseSession(this._idMap.get(id)));
}
public stopSession(id: ProfilerSessionID): Thenable<boolean> {
return this._runAction(id, provider => provider.stopSession(this._idMap.get(id))).then(() => {
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isStopped: true, isPaused: false, isRunning: false });
return true;
}, (reason) => {
// The error won't be actionable to the user, so only log it to console.
// In case of error, the state of the UI is not usable, makes more sense to
// set it to stopped so that user can restart it or pick a different session
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isStopped: true, isPaused: false, isRunning: false });
});
}
public getXEventSessions(id: ProfilerSessionID): Thenable<string[]> {
return this._runAction(id, provider => provider.getXEventSessions(this._idMap.get(id))).then((r) => {
return r;
}, (reason) => {
this._notificationService.error(reason.message);
});
}
private _runAction<T>(id: ProfilerSessionID, action: (handler: sqlops.ProfilerProvider) => Thenable<T>): Thenable<T> {
// let providerId = this._connectionService.getProviderIdFromUri(this._idMap.get(id));
let providerId = 'MSSQL';
if (!providerId) {
return TPromise.wrapError(new Error('Connection is required in order to interact with queries'));
}
let handler = this._providers.get(providerId);
if (handler) {
return action(handler);
} else {
return TPromise.wrapError(new Error('No Handler Registered'));
}
}
public getViewTemplates(provider?: string): Array<IProfilerViewTemplate> {
let config = <IProfilerSettings>this._configurationService.getValue(PROFILER_SETTINGS);
if (provider) {
return config.viewTemplates;
} else {
return config.viewTemplates;
}
}
public getSessionTemplates(provider?: string): Array<IProfilerSessionTemplate> {
let config = <IProfilerSettings>this._configurationService.getValue(PROFILER_SETTINGS);
if (provider) {
return config.sessionTemplates;
} else {
return config.sessionTemplates;
}
}
public getSessionViewState(ownerUri: string): any {
let mementoKey = this.getMementoKey(ownerUri);
let uiStateMap = this._memento[ProfilerService.PROFILER_SERVICE_UI_STATE_STORAGE_KEY];
if (uiStateMap && mementoKey) {
return uiStateMap[mementoKey];
}
return undefined;
}
private getMementoKey(ownerUri: string): string {
let mementoKey = undefined;
let connectionProfile: IConnectionProfile = this._connectionMap.get(ownerUri);
if (connectionProfile) {
mementoKey = connectionProfile.serverName;
}
return mementoKey;
}
private updateMemento(ownerUri: string, uiState: any) {
// update persisted session state
let mementoKey = this.getMementoKey(ownerUri);
let uiStateMap = this._memento[ProfilerService.PROFILER_SERVICE_UI_STATE_STORAGE_KEY];
if (uiStateMap && mementoKey) {
uiStateMap[mementoKey] = uiState;
this._memento[ProfilerService.PROFILER_SERVICE_UI_STATE_STORAGE_KEY] = uiStateMap;
this._context.saveMemento();
}
}
public launchColumnEditor(input?: ProfilerInput): Thenable<void> {
if (!this._editColumnDialog) {
this._editColumnDialog = this._instantiationService.createInstance(ProfilerColumnEditorDialog);
this._editColumnDialog.render();
}
this._editColumnDialog.open(input);
return TPromise.as(null);
}
public launchCreateSessionDialog(input?: ProfilerInput): Thenable<void> {
return this._commandService.executeCommand('profiler.openCreateSessionDialog', input.id, input.providerType, this.getSessionTemplates());
}
public launchFilterSessionDialog(input: ProfilerInput): void {
let dialog = this._instantiationService.createInstance(ProfilerFilterDialog);
dialog.open(input);
}
}