mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
SQL Operations Studio Public Preview 1 (0.23) release source code
This commit is contained in:
103
src/sql/parts/profiler/service/interfaces.ts
Normal file
103
src/sql/parts/profiler/service/interfaces.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import * as data from 'data';
|
||||
|
||||
const PROFILER_SERVICE_ID = 'profilerService';
|
||||
export const IProfilerService = createDecorator<IProfilerService>(PROFILER_SERVICE_ID);
|
||||
|
||||
export type ProfilerSessionID = string;
|
||||
|
||||
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(rowCount: number, data: data.IProfilerTableRow);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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: data.IProfilerProvider): 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, session: IProfilerSession): 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>;
|
||||
/**
|
||||
* Starts the session specified by the id
|
||||
*/
|
||||
startSession(sessionId: ProfilerSessionID): 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>;
|
||||
/**
|
||||
* The method called by the service provider for when more rows are available to render
|
||||
*/
|
||||
onMoreRows(params: data.IProfilerMoreRowsNotificationParams): void;
|
||||
/**
|
||||
* 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>;
|
||||
/**
|
||||
* 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>;
|
||||
}
|
||||
|
||||
export interface IProfilerSettings {
|
||||
sessionTemplates: Array<IProfilerSessionTemplate>;
|
||||
}
|
||||
|
||||
export interface IEventTemplate {
|
||||
name: string;
|
||||
optionalColumns: Array<string>;
|
||||
}
|
||||
|
||||
export interface IEventViewTemplate {
|
||||
name: string;
|
||||
columns: Array<string>;
|
||||
}
|
||||
|
||||
export interface ISessionViewTemplate {
|
||||
events: Array<IEventViewTemplate>;
|
||||
}
|
||||
|
||||
export interface IProfilerSessionTemplate {
|
||||
name: string;
|
||||
events: Array<IEventTemplate>;
|
||||
view: ISessionViewTemplate;
|
||||
}
|
||||
125
src/sql/parts/profiler/service/profilerService.ts
Normal file
125
src/sql/parts/profiler/service/profilerService.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
|
||||
import {
|
||||
ProfilerSessionID, IProfilerSession, IProfilerService, IProfilerSessionTemplate,
|
||||
PROFILER_SETTINGS, IProfilerSettings
|
||||
} from './interfaces';
|
||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||
import { ProfilerColumnEditorDialog } from 'sql/parts/profiler/dialog/profilerColumnEditorDialog';
|
||||
|
||||
import * as data from 'data';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
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 {
|
||||
public _serviceBrand: any;
|
||||
private _providers = new Map<string, data.IProfilerProvider>();
|
||||
private _idMap = new TwoWayMap<ProfilerSessionID, string>();
|
||||
private _sessionMap = new Map<ProfilerSessionID, IProfilerSession>();
|
||||
private _dialog: ProfilerColumnEditorDialog;
|
||||
|
||||
constructor(
|
||||
@IConnectionManagementService private _connectionService: IConnectionManagementService,
|
||||
@IConfigurationService public _configurationService: IConfigurationService,
|
||||
@IInstantiationService private _instantiationService: IInstantiationService
|
||||
) { }
|
||||
|
||||
public registerProvider(providerId: string, provider: data.IProfilerProvider): void {
|
||||
this._providers.set(providerId, provider);
|
||||
}
|
||||
|
||||
public registerSession(uri: string, session: IProfilerSession): ProfilerSessionID {
|
||||
this._sessionMap.set(uri, session);
|
||||
this._idMap.set(uri, uri);
|
||||
return uri;
|
||||
}
|
||||
|
||||
public onMoreRows(params: data.IProfilerMoreRowsNotificationParams): void {
|
||||
this._sessionMap.get(this._idMap.reverseGet(params.uri)).onMoreRows(params.rowCount, params.data);
|
||||
}
|
||||
|
||||
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 startSession(id: ProfilerSessionID): Thenable<boolean> {
|
||||
return this._runAction(id, provider => provider.startSession(this._idMap.get(id)));
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
private _runAction<T>(id: ProfilerSessionID, action: (handler: data.IProfilerProvider) => Thenable<T>): Thenable<T> {
|
||||
// let providerId = this._connectionService.getProviderIdFromUri(this._idMap.get(id));
|
||||
let providerId = 'default';
|
||||
|
||||
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 getSessionTemplates(provider?: string): Array<IProfilerSessionTemplate> {
|
||||
let config = <IProfilerSettings>this._configurationService.getConfiguration(PROFILER_SETTINGS);
|
||||
|
||||
if (provider) {
|
||||
return config.sessionTemplates;
|
||||
} else {
|
||||
return config.sessionTemplates;
|
||||
}
|
||||
}
|
||||
|
||||
public launchColumnEditor(input?: ProfilerInput): Thenable<void> {
|
||||
if (!this._dialog) {
|
||||
this._dialog = this._instantiationService.createInstance(ProfilerColumnEditorDialog);
|
||||
this._dialog.render();
|
||||
}
|
||||
|
||||
this._dialog.open(input);
|
||||
return TPromise.as(null);
|
||||
}
|
||||
}
|
||||
100
src/sql/parts/profiler/service/profilerTestBackend.ts
Normal file
100
src/sql/parts/profiler/service/profilerTestBackend.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IProfilerService } from './interfaces';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import * as path from 'path';
|
||||
|
||||
import * as data from 'data';
|
||||
|
||||
declare var __dirname;
|
||||
|
||||
const columns = [
|
||||
'EventClass',
|
||||
'TextData',
|
||||
'ApplicationName',
|
||||
'NTUserName',
|
||||
'LoginName',
|
||||
'CPU',
|
||||
'Reads',
|
||||
'Writes',
|
||||
'Duration',
|
||||
'ClientProcessID',
|
||||
'SPID',
|
||||
'StartTime',
|
||||
'EndTime',
|
||||
'BinaryData'
|
||||
];
|
||||
|
||||
export class ProfilerTestBackend implements data.IProfilerProvider {
|
||||
private index = 0;
|
||||
private timeOutMap = new Map<string, number>();
|
||||
private testData: Array<Array<string>> = new Array<Array<string>>();
|
||||
|
||||
constructor(
|
||||
@IProfilerService private _profilerService: IProfilerService) { }
|
||||
|
||||
startSession(guid: string): Thenable<boolean> {
|
||||
this.timeOutMap.set(guid, this.intervalFn(guid));
|
||||
return TPromise.as(true);
|
||||
}
|
||||
|
||||
private intervalFn(guid: string): number {
|
||||
return setTimeout(() => {
|
||||
let data = this.testData[this.index++];
|
||||
let formattedData = {
|
||||
EventClass: data[0].trim()
|
||||
};
|
||||
|
||||
for (let i = 1; i < data.length; i++) {
|
||||
formattedData[columns[i]] = data[i];
|
||||
}
|
||||
|
||||
this._profilerService.onMoreRows({ uri: guid, rowCount: 1, data: formattedData });
|
||||
if (this.index >= this.testData.length) {
|
||||
this.index = 0;
|
||||
}
|
||||
this.timeOutMap.set(guid, this.intervalFn(guid));
|
||||
}, Math.floor(Math.random() * 1000) + 300);
|
||||
}
|
||||
|
||||
stopSession(guid: string): Thenable<boolean> {
|
||||
clearTimeout(this.timeOutMap.get(guid));
|
||||
this.index = 0;
|
||||
return TPromise.as(true);
|
||||
}
|
||||
|
||||
pauseSession(guid: string): Thenable<boolean> {
|
||||
clearTimeout(this.timeOutMap.get(guid));
|
||||
return TPromise.as(true);
|
||||
}
|
||||
|
||||
connectSession(): Thenable<boolean> {
|
||||
if (this.testData.length === 0) {
|
||||
return new TPromise<boolean>((resolve, reject) => {
|
||||
pfs.readFile(path.join(__dirname, 'testData.tsv')).then(result => {
|
||||
let tabsep = result.toString().split('\t');
|
||||
for (let i = 0; i < tabsep.length; i++) {
|
||||
if (i % columns.length === 0) {
|
||||
this.testData[i / columns.length] = new Array<string>();
|
||||
}
|
||||
this.testData[Math.floor(i / columns.length)][i % columns.length] = tabsep[i];
|
||||
};
|
||||
resolve(true);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return TPromise.as(true);
|
||||
}
|
||||
}
|
||||
|
||||
disconnectSession(guid: string): Thenable<boolean> {
|
||||
clearTimeout(this.timeOutMap.get(guid));
|
||||
this.index = 0;
|
||||
return TPromise.as(true);
|
||||
}
|
||||
}
|
||||
3320
src/sql/parts/profiler/service/testData.tsv
Normal file
3320
src/sql/parts/profiler/service/testData.tsv
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user