mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 18:46:40 -05:00
Add Azure Monitor Extension (#15397)
* Added Azure Log Analytics resource for generating AAD Token. * Fixed AzureResource * Removed debug code from connectionManagementService * Moved AzureLogAnalytics from AzureResource enum in azdata.d.ts to azdata.proposed.d.ts. Added azureLogAnalyticsResource to all azureSettings in providerSettings.ts * Updated endpoint for generating AAD Token for LogAnalytics for UsGov, UsNat, and China * Initial Commit of Azure Monitor Extension * Added extension name to azuremonitor package strings * Removed azureMonitor resource from germanyCloud in providerSettings * Added logic to exclude menuItems in object explorer for LogAnalytics * Changed exe from AzureMonitor to Kusto * Added if clause for queryName for new queries * Changed queryWindow name from KustoQuery to KQLQuery for Kusto and LogAnalytics. * Added LogAnalytics for setTaskBarContent * Added serialization and telemetry feature classes to AzureMonitor. Added references for azdata and vscode. * Added azure monitor light and dark icons * Added config for Dashboard in package.json * Added workspace information to dashboard * Added language support for LogAnalytics * Added Notebook support * Added Hide flag to package.json for databaseName * Changed providerId from LogAnalytics to LOGANALYTICS * Changed Workspace to Workspace ID in package.nls.json * Added support for Azure Widget browser * Changed fullName to use workspaceId when connecting * Changed providerId from alertsManagement to azureMonitor * Added .gitignore and *.vsix to vscodeignore. * Removed unused devDependencies * Code Review Feedback * Changed tsconfig.json to match Kusto and Sql * Changed package.json to match kusto package. * Changed tsconfig to validate unused params and implictAny. Changed existing code to satisfy build. * Fixed tsconfig to use the correct base class. * Added objectExplorerNodeProvider and all related classes. * Removed unused tmLanguage file * Added logic to to download extension from toolservice * Fixed launchArgs. Removed commented code from extension.ts. Changed config.json to use net5.0 * Added displayName to package.nls.json. Removed hide flag from databaseName. Other code review feedback. * Added readme info to AzureMonitor * Removed unused client-error-handler and ui-references files. Combined outputChannel in azuremonitorServer. Removed TODO from contextProvider. Renamed function in extension.ts. Removed unneeded 'use strict' from cancelableStream.ts. Removed second outputChannel from objectExplorerNodeProvider. * Removed unused files
This commit is contained in:
65
extensions/azuremonitor/src/features/accountFeature.ts
Normal file
65
extensions/azuremonitor/src/features/accountFeature.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import * as nls from 'vscode-nls';
|
||||
import { SqlOpsDataClient } from 'dataprotocol-client';
|
||||
import { ClientCapabilities, StaticFeature } from 'vscode-languageclient';
|
||||
import { window } from 'vscode';
|
||||
import * as contracts from './contracts';
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
export class AccountFeature implements StaticFeature {
|
||||
|
||||
constructor(private _client: SqlOpsDataClient) { }
|
||||
|
||||
fillClientCapabilities(_capabilities: ClientCapabilities): void { }
|
||||
|
||||
initialize(): void {
|
||||
this._client.onRequest(contracts.SecurityTokenRequest.type, async (request): Promise<contracts.RequestSecurityTokenResponse | undefined> => {
|
||||
return this.getToken(request);
|
||||
});
|
||||
}
|
||||
|
||||
protected async getToken(request: contracts.RequestSecurityTokenParams): Promise<contracts.RequestSecurityTokenResponse | undefined> {
|
||||
const accountList = await azdata.accounts.getAllAccounts();
|
||||
let account: azdata.Account | undefined;
|
||||
|
||||
if (accountList.length < 1) {
|
||||
// TODO: Prompt user to add account
|
||||
window.showErrorMessage(localize('kusto.missingLinkedAzureAccount', "Azure Data Studio needs to contact Azure Key Vault to access a column master key for Always Encrypted, but no linked Azure account is available. Please add a linked Azure account and retry the query."));
|
||||
return undefined;
|
||||
} else {
|
||||
account = accountList.find(a => a.key.accountId === request.accountId);
|
||||
}
|
||||
|
||||
if (!account) {
|
||||
window.showErrorMessage(localize('kusto.accountDoesNotExist', "Account does not exist."));
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const unauthorizedMessage = localize('kusto.insufficientlyPrivelagedAzureAccount', "The configured Azure account for {0} does not have sufficient permissions for Azure Key Vault to access a column master key for Always Encrypted.", account.key.accountId);
|
||||
|
||||
let tenantId: string = '';
|
||||
if (request.provider !== 'dstsAuth') {
|
||||
const tenant = account.properties.tenants.find((t: { [key: string]: string }) => request.authority.includes(t.id));
|
||||
if (!tenant) {
|
||||
window.showErrorMessage(unauthorizedMessage);
|
||||
return undefined;
|
||||
}
|
||||
tenantId = tenant.id;
|
||||
}
|
||||
|
||||
const securityToken = await azdata.accounts.getAccountSecurityToken(account, tenantId, azdata.AzureResource.Sql);
|
||||
|
||||
if (!securityToken?.token) {
|
||||
window.showErrorMessage(unauthorizedMessage);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let params: contracts.RequestSecurityTokenResponse = {
|
||||
accountKey: JSON.stringify(account.key),
|
||||
token: securityToken.token
|
||||
};
|
||||
|
||||
return params;
|
||||
}
|
||||
}
|
||||
81
extensions/azuremonitor/src/features/contracts.ts
Normal file
81
extensions/azuremonitor/src/features/contracts.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { NotificationType, RequestType } from 'vscode-languageclient';
|
||||
import { ITelemetryEventProperties, ITelemetryEventMeasures } from '../telemetry';
|
||||
import * as azdata from 'azdata';
|
||||
|
||||
// ------------------------------- < Telemetry Sent Event > ------------------------------------
|
||||
|
||||
/**
|
||||
* Event sent when the language service send a telemetry event
|
||||
*/
|
||||
export namespace TelemetryNotification {
|
||||
export const type = new NotificationType<TelemetryParams, void>('telemetry/sqlevent');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update event parameters
|
||||
*/
|
||||
export class TelemetryParams {
|
||||
public params!: {
|
||||
eventName: string;
|
||||
properties: ITelemetryEventProperties;
|
||||
measures: ITelemetryEventMeasures;
|
||||
};
|
||||
}
|
||||
|
||||
// ------------------------------- </ Telemetry Sent Event > ----------------------------------
|
||||
|
||||
// ------------------------------- < Security Token Request > ------------------------------------------
|
||||
export interface RequestSecurityTokenParams {
|
||||
authority: string;
|
||||
provider: string;
|
||||
resource: string;
|
||||
accountId: string;
|
||||
}
|
||||
|
||||
export interface RequestSecurityTokenResponse {
|
||||
accountKey: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
export namespace SecurityTokenRequest {
|
||||
export const type = new RequestType<RequestSecurityTokenParams, RequestSecurityTokenResponse, void, void>('account/securityTokenRequest');
|
||||
}
|
||||
// ------------------------------- </ Security Token Request > ------------------------------------------
|
||||
|
||||
// ------------------------------- <Serialization> -----------------------------
|
||||
export namespace SerializeDataStartRequest {
|
||||
export const type = new RequestType<azdata.SerializeDataStartRequestParams, azdata.SerializeDataResult, void, void>('serialize/start');
|
||||
}
|
||||
|
||||
export namespace SerializeDataContinueRequest {
|
||||
export const type = new RequestType<azdata.SerializeDataContinueRequestParams, azdata.SerializeDataResult, void, void>('serialize/continue');
|
||||
}
|
||||
// ------------------------------- <Serialization> -----------------------------
|
||||
|
||||
// ------------------------------- < Load Completion Extension Request > ------------------------------------
|
||||
/**
|
||||
* Completion extension load parameters
|
||||
*/
|
||||
export class CompletionExtensionParams {
|
||||
/// <summary>
|
||||
/// Absolute path for the assembly containing the completion extension
|
||||
/// </summary>
|
||||
public assemblyPath?: string;
|
||||
/// <summary>
|
||||
/// The type name for the completion extension
|
||||
/// </summary>
|
||||
public typeName?: string;
|
||||
/// <summary>
|
||||
/// Property bag for initializing the completion extension
|
||||
/// </summary>
|
||||
public properties?: {};
|
||||
}
|
||||
|
||||
export namespace CompletionExtLoadRequest {
|
||||
export const type = new RequestType<CompletionExtensionParams, boolean, void, void>('completion/extLoad');
|
||||
}
|
||||
68
extensions/azuremonitor/src/features/serializationFeature.ts
Normal file
68
extensions/azuremonitor/src/features/serializationFeature.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { SqlOpsDataClient, SqlOpsFeature } from 'dataprotocol-client';
|
||||
import { ClientCapabilities, RPCMessageType, ServerCapabilities } from 'vscode-languageclient';
|
||||
import { Disposable } from 'vscode';
|
||||
import * as contracts from './contracts';
|
||||
import * as azdata from 'azdata';
|
||||
import * as Utils from '../utils';
|
||||
import * as UUID from 'vscode-languageclient/lib/utils/uuid';
|
||||
|
||||
export class SerializationFeature extends SqlOpsFeature<undefined> {
|
||||
private static readonly messageTypes: RPCMessageType[] = [
|
||||
contracts.SerializeDataStartRequest.type,
|
||||
contracts.SerializeDataContinueRequest.type,
|
||||
];
|
||||
|
||||
constructor(client: SqlOpsDataClient) {
|
||||
super(client, SerializationFeature.messageTypes);
|
||||
}
|
||||
|
||||
public fillClientCapabilities(_capabilities: ClientCapabilities): void {
|
||||
}
|
||||
|
||||
public initialize(_capabilities: ServerCapabilities): void {
|
||||
this.register(this.messages, {
|
||||
id: UUID.generateUuid(),
|
||||
registerOptions: undefined
|
||||
});
|
||||
}
|
||||
|
||||
protected registerProvider(_options: undefined): Disposable {
|
||||
const client = this._client;
|
||||
|
||||
let startSerialization = (requestParams: azdata.SerializeDataStartRequestParams): Thenable<azdata.SerializeDataResult> => {
|
||||
return client.sendRequest(contracts.SerializeDataStartRequest.type, requestParams).then(
|
||||
r => {
|
||||
return r;
|
||||
},
|
||||
e => {
|
||||
client.logFailedRequest(contracts.SerializeDataStartRequest.type, e);
|
||||
return Promise.resolve(<azdata.SerializeDataResult>{
|
||||
succeeded: false,
|
||||
messages: Utils.getErrorMessage(e)
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
let continueSerialization = (requestParams: azdata.SerializeDataContinueRequestParams): Thenable<azdata.SerializeDataResult> => {
|
||||
return client.sendRequest(contracts.SerializeDataContinueRequest.type, requestParams).then(
|
||||
r => {
|
||||
return r;
|
||||
},
|
||||
e => {
|
||||
client.logFailedRequest(contracts.SerializeDataContinueRequest.type, e);
|
||||
return Promise.resolve(<azdata.SerializeDataResult>{
|
||||
succeeded: false,
|
||||
messages: Utils.getErrorMessage(e)
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
return azdata.dataprotocol.registerSerializationProvider({
|
||||
providerId: client.providerId,
|
||||
startSerialization,
|
||||
continueSerialization
|
||||
});
|
||||
}
|
||||
}
|
||||
25
extensions/azuremonitor/src/features/telemetryFeature.ts
Normal file
25
extensions/azuremonitor/src/features/telemetryFeature.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { SqlOpsDataClient } from 'dataprotocol-client';
|
||||
import { ClientCapabilities, StaticFeature } from 'vscode-languageclient';
|
||||
import { Telemetry } from '../telemetry';
|
||||
import * as contracts from './contracts';
|
||||
import * as Utils from '../utils';
|
||||
|
||||
export class TelemetryFeature implements StaticFeature {
|
||||
|
||||
constructor(private _client: SqlOpsDataClient) { }
|
||||
|
||||
fillClientCapabilities(capabilities: ClientCapabilities): void {
|
||||
Utils.ensure(capabilities, 'telemetry')!.telemetry = true;
|
||||
}
|
||||
|
||||
initialize(): void {
|
||||
this._client.onNotification(contracts.TelemetryNotification.type, e => {
|
||||
Telemetry.sendTelemetryEvent(e.params.eventName, e.params.properties, e.params.measures);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user