mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Add session templates to profiler (#2115)
* Initial support for handling available sessions * Displaying sessions in drop down, send session name in start profiling request * More support for starting existing sessions * New session dialog and session templates in user files * Create profiler dialog and session templates * Preliminary session template changes * Saving some changes * Send session templates when creating sessions * Saving changes * UI Fixes for dialog * Formatting fixes * removing comments * Fixing PR comments * bumping toolsservice and dataprotocolclient versions * Fixing starting existing sessions
This commit is contained in:
committed by
GitHub
parent
2a650d4d74
commit
79269cdfd5
@@ -658,7 +658,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.3",
|
"dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.4",
|
||||||
"opener": "^1.4.3",
|
"opener": "^1.4.3",
|
||||||
"service-downloader": "github:anthonydresser/service-downloader#0.1.4",
|
"service-downloader": "github:anthonydresser/service-downloader#0.1.4",
|
||||||
"vscode-extension-telemetry": "^0.0.15"
|
"vscode-extension-telemetry": "^0.0.15"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}",
|
||||||
"version": "1.5.0-alpha.20",
|
"version": "1.5.0-alpha.22",
|
||||||
"downloadFileNames": {
|
"downloadFileNames": {
|
||||||
"Windows_86": "win-x86-netcoreapp2.1.zip",
|
"Windows_86": "win-x86-netcoreapp2.1.zip",
|
||||||
"Windows_64": "win-x64-netcoreapp2.1.zip",
|
"Windows_64": "win-x64-netcoreapp2.1.zip",
|
||||||
|
|||||||
26
extensions/profiler/client/src/data/createSessionData.ts
Normal file
26
extensions/profiler/client/src/data/createSessionData.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import * as sqlops from 'sqlops';
|
||||||
|
|
||||||
|
export class CreateSessionData {
|
||||||
|
public ownerUri: string;
|
||||||
|
public sessionName: string;
|
||||||
|
public templates: Array<sqlops.ProfilerSessionTemplate> = new Array<sqlops.ProfilerSessionTemplate>();
|
||||||
|
|
||||||
|
constructor(ownerUri: string, templates: Array<sqlops.ProfilerSessionTemplate>) {
|
||||||
|
this.ownerUri = ownerUri;
|
||||||
|
this.templates = templates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTemplateNames(): string[] {
|
||||||
|
return this.templates.map(e => e.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public selectTemplate(name: string): sqlops.ProfilerSessionTemplate {
|
||||||
|
return this.templates.find((t) => { return t.name === name; });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
import * as nls from 'vscode-nls';
|
||||||
|
import * as sqlops from 'sqlops';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { CreateSessionData } from '../data/createSessionData';
|
||||||
|
|
||||||
|
const localize = nls.loadMessageBundle();
|
||||||
|
|
||||||
|
export class CreateSessionDialog {
|
||||||
|
|
||||||
|
// Top level
|
||||||
|
private readonly DialogTitle: string = localize('createSessionDialog.newSession', 'New Session');
|
||||||
|
private readonly CancelButtonText: string = localize('createSessionDialog.cancel', 'Cancel');
|
||||||
|
private readonly CreateButtonText: string = localize('createSessionDialog.create', 'Create');
|
||||||
|
private readonly DialogTitleText: string = localize('createSessionDialog.title', 'Create New Profiler Session');
|
||||||
|
|
||||||
|
// UI Components
|
||||||
|
private dialog: sqlops.window.modelviewdialog.Dialog;
|
||||||
|
private templatesBox: sqlops.DropDownComponent;
|
||||||
|
private sessionNameBox: sqlops.InputBoxComponent;
|
||||||
|
|
||||||
|
private model: CreateSessionData;
|
||||||
|
|
||||||
|
private _onSuccess: vscode.EventEmitter<CreateSessionData> = new vscode.EventEmitter<CreateSessionData>();
|
||||||
|
public readonly onSuccess: vscode.Event<CreateSessionData> = this._onSuccess.event;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(ownerUri: string, templates: Array<sqlops.ProfilerSessionTemplate>) {
|
||||||
|
if (typeof (templates) === 'undefined' || templates === null) {
|
||||||
|
throw new Error(localize('createSessionDialog.templatesInvalid', "Invalid templates list, cannot open dialog"));
|
||||||
|
}
|
||||||
|
if (typeof (ownerUri) === 'undefined' || ownerUri === null) {
|
||||||
|
throw new Error(localize('createSessionDialog.dialogOwnerInvalid', "Invalid dialog owner, cannot open dialog"));
|
||||||
|
}
|
||||||
|
this.model = new CreateSessionData(ownerUri, templates);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async showDialog(): Promise<void> {
|
||||||
|
this.dialog = sqlops.window.modelviewdialog.createDialog(this.DialogTitle);
|
||||||
|
this.initializeContent();
|
||||||
|
this.dialog.okButton.onClick(() => this.execute());
|
||||||
|
this.dialog.cancelButton.onClick(() => { });
|
||||||
|
this.dialog.okButton.label = this.CreateButtonText;
|
||||||
|
this.dialog.cancelButton.label = this.CancelButtonText;
|
||||||
|
|
||||||
|
sqlops.window.modelviewdialog.openDialog(this.dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
private initializeContent(): void {
|
||||||
|
this.dialog.registerContent(async view => {
|
||||||
|
this.templatesBox = view.modelBuilder.dropDown()
|
||||||
|
.withProperties({
|
||||||
|
values: []
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
this.sessionNameBox = view.modelBuilder.inputBox()
|
||||||
|
.withProperties({
|
||||||
|
required: true,
|
||||||
|
multiline: false,
|
||||||
|
value: ''
|
||||||
|
}).component();
|
||||||
|
|
||||||
|
let formModel = view.modelBuilder.formContainer()
|
||||||
|
.withFormItems([{
|
||||||
|
components: [{
|
||||||
|
component: this.templatesBox,
|
||||||
|
title: localize('createSessionDialog.selectTemplates', "Select session template:")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: this.sessionNameBox,
|
||||||
|
|
||||||
|
title: localize('createSessionDialog.enterSessionName', "Enter session name:")
|
||||||
|
}],
|
||||||
|
title: this.DialogTitleText
|
||||||
|
}]).withLayout({ width: '100%' }).component();
|
||||||
|
|
||||||
|
await view.initializeModel(formModel);
|
||||||
|
|
||||||
|
if (this.model.templates) {
|
||||||
|
this.templatesBox.values = this.model.getTemplateNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sessionNameBox.onTextChanged(() => {
|
||||||
|
if (this.sessionNameBox.value.length > 0) {
|
||||||
|
this.model.sessionName = this.sessionNameBox.value;
|
||||||
|
this.dialog.okButton.enabled = true;
|
||||||
|
} else {
|
||||||
|
this.dialog.okButton.enabled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async execute(): Promise<void> {
|
||||||
|
let currentConnection = await sqlops.connection.getCurrentConnection();
|
||||||
|
let profilerService = sqlops.dataprotocol.getProvider<sqlops.ProfilerProvider>(currentConnection.providerName, sqlops.DataProviderType.ProfilerProvider);
|
||||||
|
|
||||||
|
let name = this.sessionNameBox.value;
|
||||||
|
let selected = this.templatesBox.value.toString();
|
||||||
|
let temp = this.model.selectTemplate(selected);
|
||||||
|
profilerService.createSession(this.model.ownerUri, this.sessionNameBox.value, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,28 +5,33 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as data from 'sqlops';
|
import * as sqlops from 'sqlops';
|
||||||
import { ApiWrapper } from './apiWrapper';
|
import { ApiWrapper } from './apiWrapper';
|
||||||
|
import { CreateSessionDialog } from './dialogs/profilerCreateSessionDialog';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main controller class that initializes the extension
|
* The main controller class that initializes the extension
|
||||||
*/
|
*/
|
||||||
export class MainController {
|
export class MainController {
|
||||||
protected _apiWrapper: ApiWrapper;
|
protected _apiWrapper: ApiWrapper;
|
||||||
protected _context: vscode.ExtensionContext;
|
protected _context: vscode.ExtensionContext;
|
||||||
|
|
||||||
// PUBLIC METHODS //////////////////////////////////////////////////////
|
// PUBLIC METHODS
|
||||||
public constructor(context: vscode.ExtensionContext, apiWrapper?: ApiWrapper) {
|
public constructor(context: vscode.ExtensionContext, apiWrapper?: ApiWrapper) {
|
||||||
this._apiWrapper = apiWrapper || new ApiWrapper();
|
this._apiWrapper = apiWrapper || new ApiWrapper();
|
||||||
this._context = context;
|
this._context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deactivates the extension
|
* Deactivates the extension
|
||||||
*/
|
*/
|
||||||
public deactivate(): void {
|
public deactivate(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
public activate(): void {
|
public activate(): void {
|
||||||
}
|
vscode.commands.registerCommand('profiler.openCreateSessionDialog', (ownerUri: string, templates: Array<sqlops.ProfilerSessionTemplate>) => {
|
||||||
|
let dialog = new CreateSessionDialog(ownerUri, templates);
|
||||||
|
dialog.showDialog();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,4 +5,5 @@
|
|||||||
|
|
||||||
/// <reference path='../../../../../src/vs/vscode.d.ts'/>
|
/// <reference path='../../../../../src/vs/vscode.d.ts'/>
|
||||||
/// <reference path='../../../../../src/sql/sqlops.d.ts'/>
|
/// <reference path='../../../../../src/sql/sqlops.d.ts'/>
|
||||||
|
/// <reference path='../../../../../src/sql/sqlops.proposed.d.ts'/>
|
||||||
/// <reference types='@types/node'/>
|
/// <reference types='@types/node'/>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
],
|
],
|
||||||
"contributes": {
|
"contributes": {
|
||||||
|
|
||||||
"commands": [
|
"commands": [
|
||||||
{
|
{
|
||||||
"command": "profiler.newProfiler",
|
"command": "profiler.newProfiler",
|
||||||
"title": "New Profiler",
|
"title": "New Profiler",
|
||||||
@@ -42,12 +42,19 @@
|
|||||||
"command": "profiler.stop",
|
"command": "profiler.stop",
|
||||||
"title": "Stop",
|
"title": "Stop",
|
||||||
"category": "Profiler"
|
"category": "Profiler"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "profiler.openCreateSessionDialog",
|
||||||
|
"category": "Profiler"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"outputChannels": [
|
"outputChannels": [
|
||||||
"sqlprofiler"
|
"sqlprofiler"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vscode-nls": "^3.2.1"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vscode": "1.0.1"
|
"vscode": "1.0.1"
|
||||||
}
|
}
|
||||||
|
|||||||
1
src/sql/base/browser/ui/taskbar/media/add.svg
Normal file
1
src/sql/base/browser/ui/taskbar/media/add.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#f6f6f6;}.icon-canvas-transparent{opacity:0;}.icon-vs-bg{fill:#424242;}</style></defs><title>add</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,16H0V0H16Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14,6v4H10v4H6V10H2V6H6V2h4V6Z"/></g><g id="iconBg"><path class="icon-vs-bg" d="M13,7V9H9v4H7V9H3V7H7V3H9V7Z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 486 B |
@@ -18,6 +18,12 @@
|
|||||||
background-image: url('start.svg');
|
background-image: url('start.svg');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vs .icon.add,
|
||||||
|
.vs-dark .icon.add,
|
||||||
|
.hc-black .icon.add {
|
||||||
|
background-image: url('add.svg');
|
||||||
|
}
|
||||||
|
|
||||||
.vs .icon.stop,
|
.vs .icon.stop,
|
||||||
.vs-dark .icon.stop,
|
.vs-dark .icon.stop,
|
||||||
.hc-black .icon.stop {
|
.hc-black .icon.stop {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import * as nls from 'vs/nls';
|
|||||||
|
|
||||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||||
import { ProfilerEditor } from 'sql/parts/profiler/editor/profilerEditor';
|
import { ProfilerEditor } from 'sql/parts/profiler/editor/profilerEditor';
|
||||||
import { PROFILER_VIEW_TEMPLATE_SETTINGS, IProfilerViewTemplate } from 'sql/parts/profiler/service/interfaces';
|
import { PROFILER_VIEW_TEMPLATE_SETTINGS, PROFILER_SESSION_TEMPLATE_SETTINGS, IProfilerViewTemplate, IProfilerSessionTemplate } from 'sql/parts/profiler/service/interfaces';
|
||||||
|
|
||||||
const profilerDescriptor = new EditorDescriptor(
|
const profilerDescriptor = new EditorDescriptor(
|
||||||
ProfilerEditor,
|
ProfilerEditor,
|
||||||
@@ -25,212 +25,300 @@ Registry.as<IEditorRegistry>(EditorExtensions.Editors)
|
|||||||
.registerEditor(profilerDescriptor, [new SyncDescriptor(ProfilerInput)]);
|
.registerEditor(profilerDescriptor, [new SyncDescriptor(ProfilerInput)]);
|
||||||
|
|
||||||
const profilerViewTemplateSchema: IJSONSchema = {
|
const profilerViewTemplateSchema: IJSONSchema = {
|
||||||
description: nls.localize('profiler.settings.viewTemplates', "Specifies view templates"),
|
description: nls.localize('profiler.settings.viewTemplates', "Specifies view templates"),
|
||||||
type: 'array',
|
type: 'array',
|
||||||
items: <IJSONSchema>{
|
items: <IJSONSchema>{
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
name: {
|
name: {
|
||||||
type: 'string'
|
type: 'string'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
default: <Array<IProfilerViewTemplate>>[
|
||||||
|
{
|
||||||
|
name: 'Standard View',
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'EventClass',
|
||||||
|
eventsMapped: ['name']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TextData',
|
||||||
|
eventsMapped: ['options_text', 'batch_text']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ApplicationName',
|
||||||
|
width: '1',
|
||||||
|
eventsMapped: ['client_app_name']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'NTUserName',
|
||||||
|
eventsMapped: ['nt_username']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'LoginName',
|
||||||
|
eventsMapped: ['server_principal_name']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ClientProcessID',
|
||||||
|
eventsMapped: ['client_pid']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'SPID',
|
||||||
|
eventsMapped: ['session_id']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'StartTime',
|
||||||
|
eventsMapped: ['timestamp']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'CPU',
|
||||||
|
eventsMapped: ['cpu_time']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Reads',
|
||||||
|
eventsMapped: ['logical_reads']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Writes',
|
||||||
|
eventsMapped: ['writes']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Duration',
|
||||||
|
eventsMapped: ['duration']
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
},
|
},
|
||||||
default: <Array<IProfilerViewTemplate>>[
|
{
|
||||||
{
|
name: 'TSQL View',
|
||||||
name: 'Standard View',
|
columns: [
|
||||||
columns: [
|
{
|
||||||
{
|
name: 'EventClass',
|
||||||
name: 'EventClass',
|
eventsMapped: ['name']
|
||||||
eventsMapped: ['name']
|
},
|
||||||
},
|
{
|
||||||
{
|
name: 'TextData',
|
||||||
name: 'TextData',
|
eventsMapped: ['options_text', 'batch_text']
|
||||||
eventsMapped: ['options_text', 'batch_text']
|
},
|
||||||
},
|
{
|
||||||
{
|
name: 'SPID',
|
||||||
name: 'ApplicationName',
|
eventsMapped: ['session_id']
|
||||||
width: '1',
|
},
|
||||||
eventsMapped: ['client_app_name']
|
{
|
||||||
},
|
name: 'StartTime',
|
||||||
{
|
eventsMapped: ['timestamp']
|
||||||
name: 'NTUserName',
|
}
|
||||||
eventsMapped: ['nt_username']
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'LoginName',
|
name: 'Tuning View',
|
||||||
eventsMapped: ['server_principal_name']
|
columns: [
|
||||||
},
|
{
|
||||||
{
|
name: 'EventClass',
|
||||||
name: 'ClientProcessID',
|
eventsMapped: ['name']
|
||||||
eventsMapped: ['client_pid']
|
},
|
||||||
},
|
{
|
||||||
{
|
name: 'TextData',
|
||||||
name: 'SPID',
|
eventsMapped: ['options_text', 'batch_text']
|
||||||
eventsMapped: ['session_id']
|
},
|
||||||
},
|
{
|
||||||
{
|
name: 'Duration',
|
||||||
name: 'StartTime',
|
eventsMapped: ['duration']
|
||||||
eventsMapped: ['timestamp']
|
},
|
||||||
},
|
{
|
||||||
{
|
name: 'SPID',
|
||||||
name: 'CPU',
|
eventsMapped: ['session_id']
|
||||||
eventsMapped: ['cpu_time']
|
},
|
||||||
},
|
{
|
||||||
{
|
name: 'DatabaseID',
|
||||||
name: 'Reads',
|
eventsMapped: ['database_id']
|
||||||
eventsMapped: ['logical_reads']
|
},
|
||||||
},
|
{
|
||||||
{
|
name: 'DatabaseName',
|
||||||
name: 'Writes',
|
eventsMapped: ['database_name']
|
||||||
eventsMapped: ['writes']
|
},
|
||||||
},
|
{
|
||||||
{
|
name: 'ObjectType',
|
||||||
name: 'Duration',
|
eventsMapped: ['object_type']
|
||||||
eventsMapped: ['duration']
|
},
|
||||||
}
|
{
|
||||||
]
|
name: 'LoginName',
|
||||||
},
|
eventsMapped: ['server_principal_name']
|
||||||
{
|
}
|
||||||
name: 'TSQL View',
|
]
|
||||||
columns: [
|
},
|
||||||
{
|
{
|
||||||
name: 'EventClass',
|
name: 'TSQL_Locks View',
|
||||||
eventsMapped: ['name']
|
columns: [
|
||||||
},
|
{
|
||||||
{
|
name: 'EventClass',
|
||||||
name: 'TextData',
|
eventsMapped: ['name']
|
||||||
eventsMapped: ['options_text', 'batch_text']
|
},
|
||||||
},
|
{
|
||||||
{
|
name: 'TextData',
|
||||||
name: 'SPID',
|
eventsMapped: ['options_text', 'batch_text']
|
||||||
eventsMapped: ['session_id']
|
},
|
||||||
},
|
{
|
||||||
{
|
name: 'ApplicationName',
|
||||||
name: 'StartTime',
|
eventsMapped: ['client_app_name']
|
||||||
eventsMapped: ['timestamp']
|
},
|
||||||
}
|
{
|
||||||
]
|
name: 'NTUserName',
|
||||||
},
|
eventsMapped: ['nt_username']
|
||||||
{
|
},
|
||||||
name: 'Tuning View',
|
{
|
||||||
columns: [
|
name: 'LoginName',
|
||||||
{
|
eventsMapped: ['server_principal_name']
|
||||||
name: 'EventClass',
|
},
|
||||||
eventsMapped: ['name']
|
{
|
||||||
},
|
name: 'ClientProcessID',
|
||||||
{
|
eventsMapped: ['client_pid']
|
||||||
name: 'TextData',
|
},
|
||||||
eventsMapped: ['options_text', 'batch_text']
|
{
|
||||||
},
|
name: 'SPID',
|
||||||
{
|
eventsMapped: ['session_id']
|
||||||
name: 'Duration',
|
},
|
||||||
eventsMapped: ['duration']
|
{
|
||||||
},
|
name: 'StartTime',
|
||||||
{
|
eventsMapped: ['timestamp']
|
||||||
name: 'SPID',
|
},
|
||||||
eventsMapped: ['session_id']
|
{
|
||||||
},
|
name: 'CPU',
|
||||||
{
|
eventsMapped: ['cpu_time']
|
||||||
name: 'DatabaseID',
|
},
|
||||||
eventsMapped: ['database_id']
|
{
|
||||||
},
|
name: 'Reads',
|
||||||
{
|
eventsMapped: ['logical_reads']
|
||||||
name: 'DatabaseName',
|
},
|
||||||
eventsMapped: ['database_name']
|
{
|
||||||
},
|
name: 'Writes',
|
||||||
{
|
eventsMapped: ['writes']
|
||||||
name: 'ObjectType',
|
},
|
||||||
eventsMapped: ['object_type']
|
{
|
||||||
},
|
name: 'Duration',
|
||||||
{
|
eventsMapped: ['duration']
|
||||||
name: 'LoginName',
|
}
|
||||||
eventsMapped: ['server_principal_name']
|
]
|
||||||
}
|
},
|
||||||
]
|
{
|
||||||
},
|
name: 'TSQL_Duration View',
|
||||||
{
|
columns: [
|
||||||
name: 'TSQL_Locks View',
|
{
|
||||||
columns: [
|
name: 'EventClass',
|
||||||
{
|
eventsMapped: ['name']
|
||||||
name: 'EventClass',
|
},
|
||||||
eventsMapped: ['name']
|
{
|
||||||
},
|
name: 'Duration',
|
||||||
{
|
eventsMapped: ['duration']
|
||||||
name: 'TextData',
|
},
|
||||||
eventsMapped: ['options_text', 'batch_text']
|
{
|
||||||
},
|
name: 'TextData',
|
||||||
{
|
eventsMapped: ['options_text', 'batch_text']
|
||||||
name: 'ApplicationName',
|
},
|
||||||
eventsMapped: ['client_app_name']
|
{
|
||||||
},
|
name: 'SPID',
|
||||||
{
|
eventsMapped: ['session_id']
|
||||||
name: 'NTUserName',
|
}
|
||||||
eventsMapped: ['nt_username']
|
]
|
||||||
},
|
}
|
||||||
{
|
]
|
||||||
name: 'LoginName',
|
};
|
||||||
eventsMapped: ['server_principal_name']
|
|
||||||
},
|
const profilerSessionTemplateSchema: IJSONSchema = {
|
||||||
{
|
description: nls.localize('profiler.settings.sessionTemplates', "Specifies session templates"),
|
||||||
name: 'ClientProcessID',
|
type: 'array',
|
||||||
eventsMapped: ['client_pid']
|
items: <IJSONSchema>{
|
||||||
},
|
type: 'object',
|
||||||
{
|
properties: {
|
||||||
name: 'SPID',
|
name: {
|
||||||
eventsMapped: ['session_id']
|
type: 'string'
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'StartTime',
|
|
||||||
eventsMapped: ['timestamp']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'CPU',
|
|
||||||
eventsMapped: ['cpu_time']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Reads',
|
|
||||||
eventsMapped: ['logical_reads']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Writes',
|
|
||||||
eventsMapped: ['writes']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Duration',
|
|
||||||
eventsMapped: ['duration']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'TSQL_Duration View',
|
|
||||||
columns: [
|
|
||||||
{
|
|
||||||
name: 'EventClass',
|
|
||||||
eventsMapped: ['name']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Duration',
|
|
||||||
eventsMapped: ['duration']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'TextData',
|
|
||||||
eventsMapped: ['options_text', 'batch_text']
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'SPID',
|
|
||||||
eventsMapped: ['session_id']
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
};
|
},
|
||||||
|
default: <Array<IProfilerSessionTemplate>>[
|
||||||
|
{
|
||||||
|
name: 'Standard_OnPrem',
|
||||||
|
defaultView: 'Standard View',
|
||||||
|
createStatement:
|
||||||
|
`CREATE EVENT SESSION [{sessionName}] ON SERVER
|
||||||
|
ADD EVENT sqlserver.attention(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id)
|
||||||
|
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))),
|
||||||
|
ADD EVENT sqlserver.existing_connection(SET collect_options_text=(1)
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id)),
|
||||||
|
ADD EVENT sqlserver.login(SET collect_options_text=(1)
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id)),
|
||||||
|
ADD EVENT sqlserver.logout(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_id)),
|
||||||
|
ADD EVENT sqlserver.rpc_completed(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id)
|
||||||
|
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))),
|
||||||
|
ADD EVENT sqlserver.sql_batch_completed(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id)
|
||||||
|
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))),
|
||||||
|
ADD EVENT sqlserver.sql_batch_starting(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.nt_username,sqlserver.query_hash,sqlserver.server_principal_name,sqlserver.session_id)
|
||||||
|
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0))))
|
||||||
|
ADD TARGET package0.ring_buffer(SET max_events_limit=(1000),max_memory=(51200))
|
||||||
|
WITH (MAX_MEMORY=8192 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=PER_CPU,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Standard_Azure',
|
||||||
|
defaultView: 'Standard View',
|
||||||
|
createStatement:
|
||||||
|
`CREATE EVENT SESSION [{sessionName}] ON DATABASE
|
||||||
|
ADD EVENT sqlserver.attention(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.username,sqlserver.query_hash,sqlserver.session_id)
|
||||||
|
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))),
|
||||||
|
ADD EVENT sqlserver.existing_connection(SET collect_options_text=(1)
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.username,sqlserver.session_id)),
|
||||||
|
ADD EVENT sqlserver.login(SET collect_options_text=(1)
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.username,sqlserver.session_id)),
|
||||||
|
ADD EVENT sqlserver.logout(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.username,sqlserver.session_id)),
|
||||||
|
ADD EVENT sqlserver.rpc_completed(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.username,sqlserver.query_hash,sqlserver.session_id)
|
||||||
|
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))),
|
||||||
|
ADD EVENT sqlserver.sql_batch_completed(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.username,sqlserver.query_hash,sqlserver.session_id)
|
||||||
|
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))),
|
||||||
|
ADD EVENT sqlserver.sql_batch_starting(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.client_app_name,sqlserver.client_pid,sqlserver.database_id,sqlserver.username,sqlserver.query_hash,sqlserver.session_id)
|
||||||
|
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0))))
|
||||||
|
ADD TARGET package0.ring_buffer(SET max_events_limit=(1000),max_memory=(51200))
|
||||||
|
WITH (MAX_MEMORY=8192 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=PER_CPU,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'TSQL_OnPrem',
|
||||||
|
defaultView: 'TSQL View',
|
||||||
|
createStatement:
|
||||||
|
`CREATE EVENT SESSION [{sessionName}] ON SERVER
|
||||||
|
ADD EVENT sqlserver.existing_connection(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.session_id,sqlserver.client_hostname)),
|
||||||
|
ADD EVENT sqlserver.login(SET collect_options_text=(1)
|
||||||
|
ACTION(package0.event_sequence,sqlserver.session_id,sqlserver.client_hostname)),
|
||||||
|
ADD EVENT sqlserver.logout(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.session_id)),
|
||||||
|
ADD EVENT sqlserver.rpc_starting(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.session_id,sqlserver.database_name)
|
||||||
|
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0)))),
|
||||||
|
ADD EVENT sqlserver.sql_batch_starting(
|
||||||
|
ACTION(package0.event_sequence,sqlserver.session_id,sqlserver.database_name)
|
||||||
|
WHERE ([package0].[equal_boolean]([sqlserver].[is_system],(0))))
|
||||||
|
ADD TARGET package0.ring_buffer(SET max_events_limit=(1000),max_memory=(51200))
|
||||||
|
WITH (MAX_MEMORY=8192 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=5 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=PER_CPU,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)`
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
const configurationRegistry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration);
|
||||||
const dashboardConfig: IConfigurationNode = {
|
const dashboardConfig: IConfigurationNode = {
|
||||||
id: 'Profiler',
|
id: 'Profiler',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
[PROFILER_VIEW_TEMPLATE_SETTINGS]: profilerViewTemplateSchema
|
[PROFILER_VIEW_TEMPLATE_SETTINGS]: profilerViewTemplateSchema,
|
||||||
|
[PROFILER_SESSION_TEMPLATE_SETTINGS]: profilerSessionTemplateSchema
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { IObjectExplorerService } from '../../objectExplorer/common/objectExplor
|
|||||||
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
import { ProfilerInput } from 'sql/parts/profiler/editor/profilerInput';
|
||||||
import { TPromise } from 'vs/base/common/winjs.base';
|
import { TPromise } from 'vs/base/common/winjs.base';
|
||||||
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
|
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
|
||||||
import { IProfilerService} from '../service/interfaces';
|
import { IProfilerService } from '../service/interfaces';
|
||||||
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||||
import { KeyCode, KeyMod } from 'vs/editor/editor.api';
|
import { KeyCode, KeyMod } from 'vs/editor/editor.api';
|
||||||
import { ProfilerEditor } from '../editor/profilerEditor';
|
import { ProfilerEditor } from '../editor/profilerEditor';
|
||||||
@@ -73,12 +73,12 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
|
|||||||
let activeEditor = editorService.getActiveEditor();
|
let activeEditor = editorService.getActiveEditor();
|
||||||
if (activeEditor instanceof ProfilerEditor) {
|
if (activeEditor instanceof ProfilerEditor) {
|
||||||
let profilerInput = activeEditor.input;
|
let profilerInput = activeEditor.input;
|
||||||
if (profilerInput.state.isRunning){
|
if (profilerInput.state.isRunning) {
|
||||||
return profilerService.stopSession(profilerInput.id);
|
return profilerService.stopSession(profilerInput.id);
|
||||||
} else {
|
} else {
|
||||||
// clear data when profiler is started
|
// clear data when profiler is started
|
||||||
profilerInput.data.clear();
|
profilerInput.data.clear();
|
||||||
return profilerService.startSession(profilerInput.id);
|
return profilerService.startSession(profilerInput.id, profilerInput.sessionName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return TPromise.as(false);
|
return TPromise.as(false);
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ import { Action } from 'vs/base/common/actions';
|
|||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
import { IEditorAction } from 'vs/editor/common/editorCommon';
|
import { IEditorAction } from 'vs/editor/common/editorCommon';
|
||||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
|
import { ICommandService } from 'vs/platform/commands/common/commands'
|
||||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
|
|
||||||
export class ProfilerConnect extends Action {
|
export class ProfilerConnect extends Action {
|
||||||
public static ID = 'profiler.connect';
|
public static ID = 'profiler.connect';
|
||||||
@@ -78,7 +80,27 @@ export class ProfilerStart extends Action {
|
|||||||
|
|
||||||
public run(input: ProfilerInput): TPromise<boolean> {
|
public run(input: ProfilerInput): TPromise<boolean> {
|
||||||
input.data.clear();
|
input.data.clear();
|
||||||
return TPromise.wrap(this._profilerService.startSession(input.id));
|
return TPromise.wrap(this._profilerService.startSession(input.id, input.sessionName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ProfilerCreate extends Action {
|
||||||
|
public static ID = 'profiler.create';
|
||||||
|
public static LABEL = nls.localize('create', "Create");
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
id: string, label: string,
|
||||||
|
@ICommandService private _commandService: ICommandService,
|
||||||
|
@IProfilerService private _profilerService: IProfilerService,
|
||||||
|
@INotificationService private _notificationService: INotificationService
|
||||||
|
) {
|
||||||
|
super(id, label, 'add');
|
||||||
|
}
|
||||||
|
|
||||||
|
public run(input: ProfilerInput): TPromise<boolean> {
|
||||||
|
return TPromise.wrap(this._profilerService.launchCreateSessionDialog(input).then(() => {
|
||||||
|
return true;
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,8 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
|
|
||||||
private _viewTemplateSelector: SelectBox;
|
private _viewTemplateSelector: SelectBox;
|
||||||
private _viewTemplates: Array<IProfilerViewTemplate>;
|
private _viewTemplates: Array<IProfilerViewTemplate>;
|
||||||
|
private _sessionSelector: SelectBox;
|
||||||
|
private _sessionsList: Array<string>;
|
||||||
private _connectionInfoText: HTMLElement;
|
private _connectionInfoText: HTMLElement;
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
@@ -126,6 +128,7 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
private _pauseAction: Actions.ProfilerPause;
|
private _pauseAction: Actions.ProfilerPause;
|
||||||
private _stopAction: Actions.ProfilerStop;
|
private _stopAction: Actions.ProfilerStop;
|
||||||
private _autoscrollAction: Actions.ProfilerAutoScroll;
|
private _autoscrollAction: Actions.ProfilerAutoScroll;
|
||||||
|
private _createAction: Actions.ProfilerCreate;
|
||||||
private _collapsedPanelAction: Actions.ProfilerCollapsablePanelAction;
|
private _collapsedPanelAction: Actions.ProfilerCollapsablePanelAction;
|
||||||
|
|
||||||
|
|
||||||
@@ -186,6 +189,8 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
this._actionBar = new Taskbar(this._header, this._contextMenuService);
|
this._actionBar = new Taskbar(this._header, this._contextMenuService);
|
||||||
this._startAction = this._instantiationService.createInstance(Actions.ProfilerStart, Actions.ProfilerStart.ID, Actions.ProfilerStart.LABEL);
|
this._startAction = this._instantiationService.createInstance(Actions.ProfilerStart, Actions.ProfilerStart.ID, Actions.ProfilerStart.LABEL);
|
||||||
this._startAction.enabled = false;
|
this._startAction.enabled = false;
|
||||||
|
this._createAction = this._instantiationService.createInstance(Actions.ProfilerCreate, Actions.ProfilerCreate.ID, Actions.ProfilerCreate.LABEL);
|
||||||
|
this._createAction.enabled = true;
|
||||||
this._stopAction = this._instantiationService.createInstance(Actions.ProfilerStop, Actions.ProfilerStop.ID, Actions.ProfilerStop.LABEL);
|
this._stopAction = this._instantiationService.createInstance(Actions.ProfilerStop, Actions.ProfilerStop.ID, Actions.ProfilerStop.LABEL);
|
||||||
this._stopAction.enabled = false;
|
this._stopAction.enabled = false;
|
||||||
this._pauseAction = this._instantiationService.createInstance(Actions.ProfilerPause, Actions.ProfilerPause.ID, Actions.ProfilerPause.LABEL);
|
this._pauseAction = this._instantiationService.createInstance(Actions.ProfilerPause, Actions.ProfilerPause.ID, Actions.ProfilerPause.LABEL);
|
||||||
@@ -200,10 +205,22 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
this.input.viewTemplate = this._viewTemplates.find(i => i.name === e.selected);
|
this.input.viewTemplate = this._viewTemplates.find(i => i.name === e.selected);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
let dropdownContainer = document.createElement('div');
|
let viewTemplateContainer = document.createElement('div');
|
||||||
dropdownContainer.style.width = '150px';
|
viewTemplateContainer.style.width = '150px';
|
||||||
dropdownContainer.style.paddingRight = '5px';
|
viewTemplateContainer.style.paddingRight = '5px';
|
||||||
this._viewTemplateSelector.render(dropdownContainer);
|
this._viewTemplateSelector.render(viewTemplateContainer);
|
||||||
|
|
||||||
|
this._sessionsList = [''];
|
||||||
|
this._sessionSelector = new SelectBox(this._sessionsList, '', this._contextViewService);
|
||||||
|
this._register(this._sessionSelector.onDidSelect(e => {
|
||||||
|
if (this.input) {
|
||||||
|
this.input.sessionName = e.selected;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
let sessionsContainer = document.createElement('div');
|
||||||
|
sessionsContainer.style.width = '150px';
|
||||||
|
sessionsContainer.style.paddingRight = '5px';
|
||||||
|
this._sessionSelector.render(sessionsContainer);
|
||||||
|
|
||||||
this._connectionInfoText = document.createElement('div');
|
this._connectionInfoText = document.createElement('div');
|
||||||
this._connectionInfoText.style.paddingRight = '5px';
|
this._connectionInfoText.style.paddingRight = '5px';
|
||||||
@@ -213,15 +230,18 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
this._connectionInfoText.style.alignItems = 'center';
|
this._connectionInfoText.style.alignItems = 'center';
|
||||||
|
|
||||||
this._register(attachSelectBoxStyler(this._viewTemplateSelector, this.themeService));
|
this._register(attachSelectBoxStyler(this._viewTemplateSelector, this.themeService));
|
||||||
|
this._register(attachSelectBoxStyler(this._sessionSelector, this.themeService));
|
||||||
|
|
||||||
this._actionBar.setContent([
|
this._actionBar.setContent([
|
||||||
{ action: this._startAction },
|
{ action: this._startAction },
|
||||||
{ action: this._stopAction },
|
{ action: this._stopAction },
|
||||||
|
{ element: sessionsContainer },
|
||||||
|
{ action: this._createAction },
|
||||||
{ element: Taskbar.createTaskbarSeparator() },
|
{ element: Taskbar.createTaskbarSeparator() },
|
||||||
{ action: this._pauseAction },
|
{ action: this._pauseAction },
|
||||||
{ action: this._autoscrollAction },
|
{ action: this._autoscrollAction },
|
||||||
{ action: this._instantiationService.createInstance(Actions.ProfilerClear, Actions.ProfilerClear.ID, Actions.ProfilerClear.LABEL) },
|
{ action: this._instantiationService.createInstance(Actions.ProfilerClear, Actions.ProfilerClear.ID, Actions.ProfilerClear.LABEL) },
|
||||||
{ element: dropdownContainer },
|
{ element: viewTemplateContainer },
|
||||||
{ element: Taskbar.createTaskbarSeparator() },
|
{ element: Taskbar.createTaskbarSeparator() },
|
||||||
{ element: this._connectionInfoText }
|
{ element: this._connectionInfoText }
|
||||||
]);
|
]);
|
||||||
@@ -416,26 +436,61 @@ export class ProfilerEditor extends BaseEditor {
|
|||||||
|
|
||||||
if (e.isConnected) {
|
if (e.isConnected) {
|
||||||
this._connectAction.connected = this.input.state.isConnected;
|
this._connectAction.connected = this.input.state.isConnected;
|
||||||
if (!this.input.state.isConnected) {
|
|
||||||
this._startAction.enabled = this.input.state.isConnected;
|
if (this.input.state.isConnected) {
|
||||||
|
this._updateToolbar();
|
||||||
|
this._sessionSelector.enable();
|
||||||
|
this._profilerService.getXEventSessions(this.input.id).then((r) => {
|
||||||
|
this._sessionSelector.setOptions(r);
|
||||||
|
this._sessionsList = r;
|
||||||
|
if (this.input.sessionName === undefined || this.input.sessionName === '') {
|
||||||
|
this.input.sessionName = this._sessionsList[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this._startAction.enabled = false;
|
||||||
this._stopAction.enabled = false;
|
this._stopAction.enabled = false;
|
||||||
this._pauseAction.enabled = false;
|
this._pauseAction.enabled = false;
|
||||||
|
this._sessionSelector.setOptions([]);
|
||||||
|
this._sessionSelector.disable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.isPaused){
|
if (e.isPaused) {
|
||||||
this._pauseAction.paused = this.input.state.isPaused;
|
this._pauseAction.paused = this.input.state.isPaused;
|
||||||
this._pauseAction.enabled = !this.input.state.isStopped && (this.input.state.isRunning || this.input.state.isPaused);
|
this._updateToolbar();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.isStopped || e.isRunning) {
|
if (e.isStopped || e.isRunning) {
|
||||||
this._startAction.enabled = !this.input.state.isRunning && !this.input.state.isPaused;
|
if (this.input.state.isRunning) {
|
||||||
this._stopAction.enabled = !this.input.state.isStopped && (this.input.state.isRunning || this.input.state.isPaused);
|
this._updateToolbar();
|
||||||
this._pauseAction.enabled = !this.input.state.isStopped && (this.input.state.isRunning || this.input.state.isPaused);
|
this._sessionSelector.setOptions([this.input.sessionName]);
|
||||||
|
this._sessionSelector.selectWithOptionName(this.input.sessionName);
|
||||||
|
this._sessionSelector.disable();
|
||||||
|
this._viewTemplateSelector.selectWithOptionName(this.input.viewTemplate.name);
|
||||||
|
}
|
||||||
|
if (this.input.state.isStopped) {
|
||||||
|
this._updateToolbar();
|
||||||
|
this._sessionSelector.enable();
|
||||||
|
this._profilerService.getXEventSessions(this.input.id).then((r) => {
|
||||||
|
this._sessionsList = r;
|
||||||
|
this._sessionSelector.setOptions(r);
|
||||||
|
if (this.input.sessionName === undefined || this.input.sessionName === '') {
|
||||||
|
this.input.sessionName = this._sessionsList[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _updateToolbar(): void {
|
||||||
|
this._startAction.enabled = !this.input.state.isRunning && !this.input.state.isPaused && this.input.state.isConnected;
|
||||||
|
this._createAction.enabled = !this.input.state.isRunning && !this.input.state.isPaused && this.input.state.isConnected;
|
||||||
|
this._stopAction.enabled = !this.input.state.isStopped && (this.input.state.isRunning || this.input.state.isPaused) && this.input.state.isConnected;
|
||||||
|
this._pauseAction.enabled = !this.input.state.isStopped && (this.input.state.isRunning || this.input.state.isPaused && this.input.state.isConnected);
|
||||||
|
}
|
||||||
|
|
||||||
public layout(dimension: DOM.Dimension): void {
|
public layout(dimension: DOM.Dimension): void {
|
||||||
this._container.style.width = dimension.width + 'px';
|
this._container.style.width = dimension.width + 'px';
|
||||||
this._container.style.height = dimension.height + 'px';
|
this._container.style.height = dimension.height + 'px';
|
||||||
@@ -453,7 +508,6 @@ abstract class SettingsCommand extends Command {
|
|||||||
return activeEditor;
|
return activeEditor;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { Event, Emitter } from 'vs/base/common/event';
|
|||||||
import { generateUuid } from 'vs/base/common/uuid';
|
import { generateUuid } from 'vs/base/common/uuid';
|
||||||
import { IDialogService, IConfirmation, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs';
|
import { IDialogService, IConfirmation, IConfirmationResult } from 'vs/platform/dialogs/common/dialogs';
|
||||||
import { escape } from 'sql/base/common/strings';
|
import { escape } from 'sql/base/common/strings';
|
||||||
|
import * as types from 'vs/base/common/types';
|
||||||
import URI from 'vs/base/common/uri';
|
import URI from 'vs/base/common/uri';
|
||||||
|
|
||||||
export class ProfilerInput extends EditorInput implements IProfilerSession {
|
export class ProfilerInput extends EditorInput implements IProfilerSession {
|
||||||
@@ -30,6 +31,7 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
private _id: ProfilerSessionID;
|
private _id: ProfilerSessionID;
|
||||||
private _state: ProfilerState;
|
private _state: ProfilerState;
|
||||||
private _columns: string[] = [];
|
private _columns: string[] = [];
|
||||||
|
private _sessionName: string;
|
||||||
private _viewTemplate: IProfilerViewTemplate;
|
private _viewTemplate: IProfilerViewTemplate;
|
||||||
// mapping of event categories to what column they display under
|
// mapping of event categories to what column they display under
|
||||||
// used for coallescing multiple events with different names to the same column
|
// used for coallescing multiple events with different names to the same column
|
||||||
@@ -49,14 +51,17 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
this._state = new ProfilerState();
|
this._state = new ProfilerState();
|
||||||
// set inital state
|
// set inital state
|
||||||
this.state.change({
|
this.state.change({
|
||||||
isConnected: true,
|
isConnected: false,
|
||||||
isStopped: true,
|
isStopped: true,
|
||||||
isPaused: false,
|
isPaused: false,
|
||||||
isRunning: false,
|
isRunning: false,
|
||||||
autoscroll: true
|
autoscroll: true
|
||||||
});
|
});
|
||||||
|
|
||||||
this._id = this._profilerService.registerSession(generateUuid(), _connection, this);
|
this._profilerService.registerSession(generateUuid(), _connection, this).then((id) => {
|
||||||
|
this._id = id;
|
||||||
|
this.state.change({ isConnected: true });
|
||||||
|
});
|
||||||
let searchFn = (val: { [x: string]: string }, exp: string): Array<number> => {
|
let searchFn = (val: { [x: string]: string }, exp: string): Array<number> => {
|
||||||
let ret = new Array<number>();
|
let ret = new Array<number>();
|
||||||
for (let i = 0; i < this._columns.length; i++) {
|
for (let i = 0; i < this._columns.length; i++) {
|
||||||
@@ -108,6 +113,16 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
return this._viewTemplate;
|
return this._viewTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public set sessionName(name: string) {
|
||||||
|
if (!this._state.isRunning || !this.state.isPaused) {
|
||||||
|
this._sessionName = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public get sessionName(): string {
|
||||||
|
return this._sessionName;
|
||||||
|
}
|
||||||
|
|
||||||
public getTypeId(): string {
|
public getTypeId(): string {
|
||||||
return ProfilerInput.ID;
|
return ProfilerInput.ID;
|
||||||
}
|
}
|
||||||
@@ -163,11 +178,11 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public get connectionName(): string {
|
public get connectionName(): string {
|
||||||
if (this._connection !== null) {
|
if (!types.isUndefinedOrNull(this._connection)) {
|
||||||
if (this._connection.databaseName) {
|
if (this._connection.databaseName) {
|
||||||
return `${ this._connection.serverName } ${ this._connection.databaseName }`;
|
return `${this._connection.serverName} ${this._connection.databaseName}`;
|
||||||
} else {
|
} else {
|
||||||
return `${ this._connection.serverName }`;
|
return `${this._connection.serverName}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -193,6 +208,32 @@ export class ProfilerInput extends EditorInput implements IProfilerSession {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public onProfilerSessionCreated(params: sqlops.ProfilerSessionCreatedParams) {
|
||||||
|
if (types.isUndefinedOrNull(params.sessionName) || types.isUndefinedOrNull(params.templateName)) {
|
||||||
|
this._notificationService.error(nls.localize("profiler.sessionCreationError", "Error while starting new session"));
|
||||||
|
} else {
|
||||||
|
this._sessionName = params.sessionName;
|
||||||
|
let sessionTemplate = this._profilerService.getSessionTemplates().find((template) => {
|
||||||
|
return template.name === params.templateName;
|
||||||
|
});
|
||||||
|
if (!types.isUndefinedOrNull(sessionTemplate)) {
|
||||||
|
let newView = this._profilerService.getViewTemplates().find((view) => {
|
||||||
|
return view.name === sessionTemplate.defaultView;
|
||||||
|
});
|
||||||
|
if (!types.isUndefinedOrNull(newView)) {
|
||||||
|
this.viewTemplate = newView;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.data.clear();
|
||||||
|
this.state.change({
|
||||||
|
isStopped: false,
|
||||||
|
isPaused: false,
|
||||||
|
isRunning: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public onSessionStateChanged(state: ProfilerState) {
|
public onSessionStateChanged(state: ProfilerState) {
|
||||||
this.state.change(state);
|
this.state.change(state);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ export const IProfilerService = createDecorator<IProfilerService>(PROFILER_SERVI
|
|||||||
export type ProfilerSessionID = string;
|
export type ProfilerSessionID = string;
|
||||||
|
|
||||||
export const PROFILER_VIEW_TEMPLATE_SETTINGS = 'profiler.viewTemplates';
|
export const PROFILER_VIEW_TEMPLATE_SETTINGS = 'profiler.viewTemplates';
|
||||||
|
export const PROFILER_SESSION_TEMPLATE_SETTINGS = 'profiler.sessionTemplates';
|
||||||
export const PROFILER_SETTINGS = 'profiler';
|
export const PROFILER_SETTINGS = 'profiler';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,6 +31,10 @@ export interface IProfilerSession {
|
|||||||
* Called by the service when the session is closed unexpectedly
|
* Called by the service when the session is closed unexpectedly
|
||||||
*/
|
*/
|
||||||
onSessionStopped(events: sqlops.ProfilerSessionStoppedParams);
|
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
|
* Called by the service when the session state is changed
|
||||||
*/
|
*/
|
||||||
@@ -49,7 +54,7 @@ export interface IProfilerService {
|
|||||||
* Registers a session with the service that acts as the UI for a profiler session
|
* 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
|
* @returns An unique id that should be used to make subsequent calls to this service
|
||||||
*/
|
*/
|
||||||
registerSession(uri: string, connectionProfile: IConnectionProfile, session: IProfilerSession): ProfilerSessionID;
|
registerSession(uri: string, connectionProfile: IConnectionProfile, session: IProfilerSession): Promise<ProfilerSessionID>;
|
||||||
/**
|
/**
|
||||||
* Connects the session specified by the id
|
* Connects the session specified by the id
|
||||||
*/
|
*/
|
||||||
@@ -58,10 +63,14 @@ export interface IProfilerService {
|
|||||||
* Disconnected the session specified by the id
|
* Disconnected the session specified by the id
|
||||||
*/
|
*/
|
||||||
disconnectSession(sessionId: ProfilerSessionID): Thenable<boolean>;
|
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
|
* Starts the session specified by the id
|
||||||
*/
|
*/
|
||||||
startSession(sessionId: ProfilerSessionID): Thenable<boolean>;
|
startSession(sessionId: ProfilerSessionID, sessionName: string): Thenable<boolean>;
|
||||||
/**
|
/**
|
||||||
* Pauses the session specified by the id
|
* Pauses the session specified by the id
|
||||||
*/
|
*/
|
||||||
@@ -70,6 +79,10 @@ export interface IProfilerService {
|
|||||||
* Stops the session specified by the id
|
* Stops the session specified by the id
|
||||||
*/
|
*/
|
||||||
stopSession(sessionId: ProfilerSessionID): Thenable<boolean>;
|
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
|
* The method called by the service provider for when more rows are available to render
|
||||||
*/
|
*/
|
||||||
@@ -78,22 +91,39 @@ export interface IProfilerService {
|
|||||||
* The method called by the service provider for when more rows are available to render
|
* The method called by the service provider for when more rows are available to render
|
||||||
*/
|
*/
|
||||||
onSessionStopped(params: sqlops.ProfilerSessionStoppedParams): void;
|
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
|
* 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
|
* @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),
|
* @returns An array of session templates that match the provider passed, if passed, and generic ones (no provider specified),
|
||||||
* otherwise returns all session templates
|
* otherwise returns all session templates
|
||||||
*/
|
*/
|
||||||
getViewTemplates(providerId?: string): Array<IProfilerViewTemplate>;
|
getSessionTemplates(providerId?: string): Array<IProfilerSessionTemplate>;
|
||||||
/**
|
/**
|
||||||
* Launches the dialog for editing the view columns of a profiler session template for the given input
|
* 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
|
* @param input input object that contains the necessary information which will be modified based on used input
|
||||||
*/
|
*/
|
||||||
launchColumnEditor(input: ProfilerInput): Thenable<void>;
|
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>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IProfilerSettings {
|
export interface IProfilerSettings {
|
||||||
viewTemplates: Array<IProfilerViewTemplate>;
|
viewTemplates: Array<IProfilerViewTemplate>;
|
||||||
|
sessionTemplates: Array<IProfilerSessionTemplate>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IColumnViewTemplate {
|
export interface IColumnViewTemplate {
|
||||||
@@ -105,3 +135,9 @@ export interface IProfilerViewTemplate {
|
|||||||
name: string;
|
name: string;
|
||||||
columns: Array<IColumnViewTemplate>;
|
columns: Array<IColumnViewTemplate>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IProfilerSessionTemplate {
|
||||||
|
name: string;
|
||||||
|
defaultView: string;
|
||||||
|
createStatement: string;
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import { IConnectionManagementService, IConnectionCompletionOptions, ConnectionType, RunQueryOnConnectionMode } from 'sql/parts/connection/common/connectionManagement';
|
import { IConnectionManagementService, IConnectionCompletionOptions, ConnectionType, RunQueryOnConnectionMode } from 'sql/parts/connection/common/connectionManagement';
|
||||||
import {
|
import {
|
||||||
ProfilerSessionID, IProfilerSession, IProfilerService, IProfilerViewTemplate,
|
ProfilerSessionID, IProfilerSession, IProfilerService, IProfilerViewTemplate, IProfilerSessionTemplate,
|
||||||
PROFILER_SETTINGS, IProfilerSettings
|
PROFILER_SETTINGS, IProfilerSettings
|
||||||
} from './interfaces';
|
} from './interfaces';
|
||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
@@ -18,6 +18,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
|||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||||
|
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||||
|
|
||||||
class TwoWayMap<T, K> {
|
class TwoWayMap<T, K> {
|
||||||
private forwardMap: Map<T, K>;
|
private forwardMap: Map<T, K>;
|
||||||
@@ -48,20 +49,21 @@ export class ProfilerService implements IProfilerService {
|
|||||||
private _providers = new Map<string, sqlops.ProfilerProvider>();
|
private _providers = new Map<string, sqlops.ProfilerProvider>();
|
||||||
private _idMap = new TwoWayMap<ProfilerSessionID, string>();
|
private _idMap = new TwoWayMap<ProfilerSessionID, string>();
|
||||||
private _sessionMap = new Map<ProfilerSessionID, IProfilerSession>();
|
private _sessionMap = new Map<ProfilerSessionID, IProfilerSession>();
|
||||||
private _dialog: ProfilerColumnEditorDialog;
|
private _editColumnDialog: ProfilerColumnEditorDialog;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@IConnectionManagementService private _connectionService: IConnectionManagementService,
|
@IConnectionManagementService private _connectionService: IConnectionManagementService,
|
||||||
@IConfigurationService public _configurationService: IConfigurationService,
|
@IConfigurationService public _configurationService: IConfigurationService,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@INotificationService private _notificationService: INotificationService
|
@INotificationService private _notificationService: INotificationService,
|
||||||
|
@ICommandService private _commandService: ICommandService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
public registerProvider(providerId: string, provider: sqlops.ProfilerProvider): void {
|
public registerProvider(providerId: string, provider: sqlops.ProfilerProvider): void {
|
||||||
this._providers.set(providerId, provider);
|
this._providers.set(providerId, provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public registerSession(uri: string, connectionProfile: IConnectionProfile, session: IProfilerSession): ProfilerSessionID {
|
public async registerSession(uri: string, connectionProfile: IConnectionProfile, session: IProfilerSession): Promise<ProfilerSessionID> {
|
||||||
let options: IConnectionCompletionOptions = {
|
let options: IConnectionCompletionOptions = {
|
||||||
params: { connectionType: ConnectionType.default, runQueryOnCompletion: RunQueryOnConnectionMode.none, input: undefined },
|
params: { connectionType: ConnectionType.default, runQueryOnCompletion: RunQueryOnConnectionMode.none, input: undefined },
|
||||||
saveTheConnection: false,
|
saveTheConnection: false,
|
||||||
@@ -69,14 +71,14 @@ export class ProfilerService implements IProfilerService {
|
|||||||
showConnectionDialogOnError: false,
|
showConnectionDialogOnError: false,
|
||||||
showFirewallRuleOnError: true
|
showFirewallRuleOnError: true
|
||||||
};
|
};
|
||||||
this._connectionService.connect(connectionProfile, uri, options).then(() => {
|
try {
|
||||||
|
await this._connectionService.connect(connectionProfile, uri, options);
|
||||||
|
} catch (connectionError) {
|
||||||
|
|
||||||
}).catch(connectionError => {
|
}
|
||||||
|
|
||||||
});
|
|
||||||
this._sessionMap.set(uri, session);
|
this._sessionMap.set(uri, session);
|
||||||
this._idMap.set(uri, uri);
|
this._idMap.set(uri, uri);
|
||||||
return uri;
|
return TPromise.wrap(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
public onMoreRows(params: sqlops.ProfilerSessionEvents): void {
|
public onMoreRows(params: sqlops.ProfilerSessionEvents): void {
|
||||||
@@ -89,6 +91,11 @@ export class ProfilerService implements IProfilerService {
|
|||||||
this._sessionMap.get(this._idMap.reverseGet(params.ownerUri)).onSessionStopped(params);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
public connectSession(id: ProfilerSessionID): Thenable<boolean> {
|
public connectSession(id: ProfilerSessionID): Thenable<boolean> {
|
||||||
return this._runAction(id, provider => provider.connectSession(this._idMap.get(id)));
|
return this._runAction(id, provider => provider.connectSession(this._idMap.get(id)));
|
||||||
}
|
}
|
||||||
@@ -97,8 +104,17 @@ export class ProfilerService implements IProfilerService {
|
|||||||
return this._runAction(id, provider => provider.disconnectSession(this._idMap.get(id)));
|
return this._runAction(id, provider => provider.disconnectSession(this._idMap.get(id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public startSession(id: ProfilerSessionID): Thenable<boolean> {
|
public createSession(id: string, createStatement: string, template: sqlops.ProfilerSessionTemplate): Thenable<boolean> {
|
||||||
return this._runAction(id, provider => provider.startSession(this._idMap.get(id))).then(() => {
|
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> {
|
||||||
|
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 });
|
this._sessionMap.get(this._idMap.reverseGet(id)).onSessionStateChanged({ isRunning: true, isStopped: false, isPaused: false });
|
||||||
return true;
|
return true;
|
||||||
}, (reason) => {
|
}, (reason) => {
|
||||||
@@ -119,6 +135,14 @@ export class ProfilerService implements IProfilerService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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> {
|
private _runAction<T>(id: ProfilerSessionID, action: (handler: sqlops.ProfilerProvider) => Thenable<T>): Thenable<T> {
|
||||||
// let providerId = this._connectionService.getProviderIdFromUri(this._idMap.get(id));
|
// let providerId = this._connectionService.getProviderIdFromUri(this._idMap.get(id));
|
||||||
let providerId = 'MSSQL';
|
let providerId = 'MSSQL';
|
||||||
@@ -144,13 +168,27 @@ export class ProfilerService implements IProfilerService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getSessionTemplates(provider?: string): Array<IProfilerSessionTemplate> {
|
||||||
|
let config = <IProfilerSettings>this._configurationService.getValue(PROFILER_SETTINGS);
|
||||||
|
|
||||||
|
if (provider) {
|
||||||
|
return config.sessionTemplates;
|
||||||
|
} else {
|
||||||
|
return config.sessionTemplates;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public launchColumnEditor(input?: ProfilerInput): Thenable<void> {
|
public launchColumnEditor(input?: ProfilerInput): Thenable<void> {
|
||||||
if (!this._dialog) {
|
if (!this._editColumnDialog) {
|
||||||
this._dialog = this._instantiationService.createInstance(ProfilerColumnEditorDialog);
|
this._editColumnDialog = this._instantiationService.createInstance(ProfilerColumnEditorDialog);
|
||||||
this._dialog.render();
|
this._editColumnDialog.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
this._dialog.open(input);
|
this._editColumnDialog.open(input);
|
||||||
return TPromise.as(null);
|
return TPromise.as(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public launchCreateSessionDialog(input?: ProfilerInput): Thenable<void> {
|
||||||
|
return this._commandService.executeCommand('profiler.openCreateSessionDialog', input.id, this.getSessionTemplates());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,11 @@ export class ProfilerTestBackend implements sqlops.ProfilerProvider {
|
|||||||
constructor(
|
constructor(
|
||||||
@IProfilerService private _profilerService: IProfilerService) { }
|
@IProfilerService private _profilerService: IProfilerService) { }
|
||||||
|
|
||||||
startSession(guid: string): Thenable<boolean> {
|
createSession(guid: string, createStatement: string, template: sqlops.ProfilerSessionTemplate): Thenable<boolean> {
|
||||||
|
this.timeOutMap.set(guid, this.intervalFn(guid));
|
||||||
|
return TPromise.as(true);
|
||||||
|
}
|
||||||
|
startSession(guid: string, sessionName: string): Thenable<boolean> {
|
||||||
this.timeOutMap.set(guid, this.intervalFn(guid));
|
this.timeOutMap.set(guid, this.intervalFn(guid));
|
||||||
return TPromise.as(true);
|
return TPromise.as(true);
|
||||||
}
|
}
|
||||||
@@ -52,6 +56,10 @@ export class ProfilerTestBackend implements sqlops.ProfilerProvider {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
registerOnProfilerSessionCreated(handler: (response: sqlops.ProfilerSessionCreatedParams) => any) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
private intervalFn(guid: string): number {
|
private intervalFn(guid: string): number {
|
||||||
return setTimeout(() => {
|
return setTimeout(() => {
|
||||||
let data = this.testData[this.index++];
|
let data = this.testData[this.index++];
|
||||||
@@ -84,6 +92,11 @@ export class ProfilerTestBackend implements sqlops.ProfilerProvider {
|
|||||||
return TPromise.as(true);
|
return TPromise.as(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getXEventSessions(guid: string): Thenable<string[]> {
|
||||||
|
let retVal = [''];
|
||||||
|
return TPromise.as(retVal);
|
||||||
|
}
|
||||||
|
|
||||||
connectSession(): Thenable<boolean> {
|
connectSession(): Thenable<boolean> {
|
||||||
if (this.testData.length === 0) {
|
if (this.testData.length === 0) {
|
||||||
return new TPromise<boolean>((resolve, reject) => {
|
return new TPromise<boolean>((resolve, reject) => {
|
||||||
|
|||||||
31
src/sql/sqlops.d.ts
vendored
31
src/sql/sqlops.d.ts
vendored
@@ -1680,14 +1680,17 @@ declare module 'sqlops' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface ProfilerProvider extends DataProvider {
|
export interface ProfilerProvider extends DataProvider {
|
||||||
startSession(sessionId: string): Thenable<boolean>;
|
createSession(sessionId: string, sessionName: string, template: ProfilerSessionTemplate): Thenable<boolean>;
|
||||||
|
startSession(sessionId: string, sessionName: string): Thenable<boolean>;
|
||||||
stopSession(sessionId: string): Thenable<boolean>;
|
stopSession(sessionId: string): Thenable<boolean>;
|
||||||
pauseSession(sessionId: string): Thenable<boolean>;
|
pauseSession(sessionId: string): Thenable<boolean>;
|
||||||
|
getXEventSessions(sessionId: string): Thenable<string[]>;
|
||||||
connectSession(sessionId: string): Thenable<boolean>;
|
connectSession(sessionId: string): Thenable<boolean>;
|
||||||
disconnectSession(sessionId: string): Thenable<boolean>;
|
disconnectSession(sessionId: string): Thenable<boolean>;
|
||||||
|
|
||||||
registerOnSessionEventsAvailable(handler: (response: ProfilerSessionEvents) => any): void;
|
registerOnSessionEventsAvailable(handler: (response: ProfilerSessionEvents) => any): void;
|
||||||
registerOnSessionStopped(handler: (response: ProfilerSessionStoppedParams) => any): void;
|
registerOnSessionStopped(handler: (response: ProfilerSessionStoppedParams) => any): void;
|
||||||
|
registerOnProfilerSessionCreated(handler: (response: ProfilerSessionCreatedParams) => any): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IProfilerTableRow {
|
export interface IProfilerTableRow {
|
||||||
@@ -1724,6 +1727,26 @@ declare module 'sqlops' {
|
|||||||
values: {};
|
values: {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Profiler Session Template
|
||||||
|
*/
|
||||||
|
export interface ProfilerSessionTemplate {
|
||||||
|
/**
|
||||||
|
* Template name
|
||||||
|
*/
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default view for template
|
||||||
|
*/
|
||||||
|
defaultView: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TSQL for creating a session
|
||||||
|
*/
|
||||||
|
createStatement: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ProfilerSessionEvents {
|
export interface ProfilerSessionEvents {
|
||||||
sessionId: string;
|
sessionId: string;
|
||||||
|
|
||||||
@@ -1739,6 +1762,12 @@ declare module 'sqlops' {
|
|||||||
sessionId: number;
|
sessionId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ProfilerSessionCreatedParams {
|
||||||
|
ownerUri: string;
|
||||||
|
sessionName: string;
|
||||||
|
templateName: string;
|
||||||
|
}
|
||||||
|
|
||||||
// File browser interfaces -----------------------------------------------------------------------
|
// File browser interfaces -----------------------------------------------------------------------
|
||||||
|
|
||||||
export interface FileBrowserProvider extends DataProvider {
|
export interface FileBrowserProvider extends DataProvider {
|
||||||
|
|||||||
@@ -497,11 +497,18 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
|
|||||||
* Profiler Provider methods
|
* Profiler Provider methods
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new profiler session
|
||||||
|
*/
|
||||||
|
public $createSession(handle: number, sessionId: string, createStatement: string, template: sqlops.ProfilerSessionTemplate): Thenable<boolean> {
|
||||||
|
return this._resolveProvider<sqlops.ProfilerProvider>(handle).createSession(sessionId, createStatement, template);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a profiler session
|
* Start a profiler session
|
||||||
*/
|
*/
|
||||||
public $startSession(handle: number, sessionId: string): Thenable<boolean> {
|
public $startSession(handle: number, sessionId: string, sessionName: string): Thenable<boolean> {
|
||||||
return this._resolveProvider<sqlops.ProfilerProvider>(handle).startSession(sessionId);
|
return this._resolveProvider<sqlops.ProfilerProvider>(handle).startSession(sessionId, sessionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -518,6 +525,12 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
|
|||||||
return this._resolveProvider<sqlops.ProfilerProvider>(handle).pauseSession(sessionId);
|
return this._resolveProvider<sqlops.ProfilerProvider>(handle).pauseSession(sessionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of running XEvent sessions on the session's target server
|
||||||
|
*/
|
||||||
|
public $getXEventSessions(handle: number, sessionId: string): Thenable<string[]> {
|
||||||
|
return this._resolveProvider<sqlops.ProfilerProvider>(handle).getXEventSessions(sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Profiler session events available notification
|
* Profiler session events available notification
|
||||||
@@ -533,6 +546,13 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
|
|||||||
this._proxy.$onSessionStopped(handle, response);
|
this._proxy.$onSessionStopped(handle, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Profiler session created notification
|
||||||
|
*/
|
||||||
|
public $onProfilerSessionCreated(handle: number, response: sqlops.ProfilerSessionCreatedParams): void {
|
||||||
|
this._proxy.$onProfilerSessionCreated(handle, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Agent Job Provider methods
|
* Agent Job Provider methods
|
||||||
|
|||||||
@@ -295,8 +295,11 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape {
|
|||||||
public $registerProfilerProvider(providerId: string, handle: number): TPromise<any> {
|
public $registerProfilerProvider(providerId: string, handle: number): TPromise<any> {
|
||||||
const self = this;
|
const self = this;
|
||||||
this._profilerService.registerProvider(providerId, <sqlops.ProfilerProvider>{
|
this._profilerService.registerProvider(providerId, <sqlops.ProfilerProvider>{
|
||||||
startSession(sessionId: string): Thenable<boolean> {
|
createSession(sessionId: string, createStatement: string, template: sqlops.ProfilerSessionTemplate): Thenable<boolean> {
|
||||||
return self._proxy.$startSession(handle, sessionId);
|
return self._proxy.$createSession(handle, sessionId, createStatement, template);
|
||||||
|
},
|
||||||
|
startSession(sessionId: string, sessionName: string): Thenable<boolean> {
|
||||||
|
return self._proxy.$startSession(handle, sessionId, sessionName);
|
||||||
},
|
},
|
||||||
stopSession(sessionId: string): Thenable<boolean> {
|
stopSession(sessionId: string): Thenable<boolean> {
|
||||||
return self._proxy.$stopSession(handle, sessionId);
|
return self._proxy.$stopSession(handle, sessionId);
|
||||||
@@ -304,6 +307,9 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape {
|
|||||||
pauseSession(sessionId: string): Thenable<boolean> {
|
pauseSession(sessionId: string): Thenable<boolean> {
|
||||||
return self._proxy.$pauseSession(handle, sessionId);
|
return self._proxy.$pauseSession(handle, sessionId);
|
||||||
},
|
},
|
||||||
|
getXEventSessions(sessionId: string): Thenable<string[]> {
|
||||||
|
return self._proxy.$getXEventSessions(handle, sessionId);
|
||||||
|
},
|
||||||
connectSession(sessionId: string): Thenable<boolean> {
|
connectSession(sessionId: string): Thenable<boolean> {
|
||||||
return TPromise.as(true);
|
return TPromise.as(true);
|
||||||
},
|
},
|
||||||
@@ -466,6 +472,10 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape {
|
|||||||
this._profilerService.onSessionStopped(response);
|
this._profilerService.onSessionStopped(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public $onProfilerSessionCreated(handle: number, response: sqlops.ProfilerSessionCreatedParams): void {
|
||||||
|
this._profilerService.onProfilerSessionCreated(response);
|
||||||
|
}
|
||||||
|
|
||||||
// SQL Server Agent handlers
|
// SQL Server Agent handlers
|
||||||
public $onJobDataUpdated(handle: Number): void {
|
public $onJobDataUpdated(handle: Number): void {
|
||||||
this._jobManagementService.fireOnDidChange();
|
this._jobManagementService.fireOnDidChange();
|
||||||
|
|||||||
@@ -254,6 +254,10 @@ export function createApiFactory(
|
|||||||
extHostDataProvider.$onSessionStopped(provider.handle, response);
|
extHostDataProvider.$onSessionStopped(provider.handle, response);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
provider.registerOnProfilerSessionCreated((response: sqlops.ProfilerSessionCreatedParams) => {
|
||||||
|
extHostDataProvider.$onProfilerSessionCreated(provider.handle, response);
|
||||||
|
});
|
||||||
|
|
||||||
return extHostDataProvider.$registerProfilerProvider(provider);
|
return extHostDataProvider.$registerProfilerProvider(provider);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -315,10 +315,15 @@ export abstract class ExtHostDataProtocolShape {
|
|||||||
* Profiler Provider methods
|
* Profiler Provider methods
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a profiler session
|
||||||
|
*/
|
||||||
|
$createSession(handle: number, sessionId: string, createStatement: string, template: sqlops.ProfilerSessionTemplate): Thenable<boolean> { throw ni(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start a profiler session
|
* Start a profiler session
|
||||||
*/
|
*/
|
||||||
$startSession(handle: number, sessionId: string): Thenable<boolean> { throw ni(); }
|
$startSession(handle: number, sessionId: string, sessionName: string): Thenable<boolean> { throw ni(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop a profiler session
|
* Stop a profiler session
|
||||||
@@ -330,6 +335,10 @@ export abstract class ExtHostDataProtocolShape {
|
|||||||
*/
|
*/
|
||||||
$pauseSession(handle: number, sessionId: string): Thenable<boolean> { throw ni(); }
|
$pauseSession(handle: number, sessionId: string): Thenable<boolean> { throw ni(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get list of running XEvent sessions on the profiler session's target server
|
||||||
|
*/
|
||||||
|
$getXEventSessions(handle: number, sessionId: string): Thenable<string[]> { throw ni(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Agent Job list
|
* Get Agent Job list
|
||||||
@@ -469,6 +478,7 @@ export interface MainThreadDataProtocolShape extends IDisposable {
|
|||||||
$onScriptingComplete(handle: number, message: sqlops.ScriptingCompleteResult): void;
|
$onScriptingComplete(handle: number, message: sqlops.ScriptingCompleteResult): void;
|
||||||
$onSessionEventsAvailable(handle: number, response: sqlops.ProfilerSessionEvents): void;
|
$onSessionEventsAvailable(handle: number, response: sqlops.ProfilerSessionEvents): void;
|
||||||
$onSessionStopped(handle: number, response: sqlops.ProfilerSessionStoppedParams): void;
|
$onSessionStopped(handle: number, response: sqlops.ProfilerSessionStoppedParams): void;
|
||||||
|
$onProfilerSessionCreated(handle: number, response: sqlops.ProfilerSessionCreatedParams): void;
|
||||||
$onJobDataUpdated(handle: Number): void;
|
$onJobDataUpdated(handle: Number): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user