-
Notifications
You must be signed in to change notification settings - Fork 149
Expand file tree
/
Copy pathstartStreamingLogs.ts
More file actions
99 lines (89 loc) · 5.41 KB
/
startStreamingLogs.ts
File metadata and controls
99 lines (89 loc) · 5.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ApplicationInsightsComponent, ApplicationInsightsManagementClient } from '@azure/arm-appinsights';
import { SiteLogsConfig, StringDictionary } from '@azure/arm-appservice';
import * as appservice from '@microsoft/vscode-azext-azureappservice';
import { ParsedSite } from '@microsoft/vscode-azext-azureappservice';
import { uiUtils } from '@microsoft/vscode-azext-azureutils';
import { AzExtTreeItem, DialogResponses, IActionContext } from '@microsoft/vscode-azext-utils';
import { functionFilter } from '../../constants';
import { ext } from '../../extensionVariables';
import { localize } from '../../localize';
import { SlotTreeItem, isSlotTreeItem } from '../../tree/SlotTreeItem';
import { RemoteFunctionTreeItem } from '../../tree/remoteProject/RemoteFunctionTreeItem';
import { createAppInsightsClient } from '../../utils/azureClients';
import { nonNullProp } from '../../utils/nonNull';
import { openUrl } from '../../utils/openUrl';
import { enableFileLogging } from './enableFileLogging';
export async function startStreamingLogs(context: IActionContext, treeItem?: SlotTreeItem | RemoteFunctionTreeItem): Promise<void> {
if (!treeItem) {
treeItem = await ext.rgApi.pickAppResource<SlotTreeItem>(context, {
filter: functionFilter
});
}
const site: ParsedSite = isSlotTreeItem(treeItem) ? treeItem.site : treeItem.parent.parent.site;
if (site.isLinux) {
try {
// https://github.com/microsoft/vscode-azurefunctions/issues/1472
await appservice.pingFunctionApp(context, site);
} catch {
// ignore and open portal anyways
}
await openLiveMetricsStream(context, site, treeItem);
} else {
const verifyLoggingEnabled: () => Promise<void> = async (): Promise<void> => {
const client = await site.createClient(context);
const logsConfig: SiteLogsConfig = await client.getLogsConfig();
if (!isApplicationLoggingEnabled(logsConfig)) {
const message: string = localize('enableApplicationLogging', 'Do you want to enable application logging for "{0}"?', client.fullName);
await context.ui.showWarningMessage(message, { modal: true, stepName: 'enableAppLogging' }, DialogResponses.yes);
await enableFileLogging(context, site, logsConfig);
}
};
await appservice.startStreamingLogs(context, site, verifyLoggingEnabled, treeItem.logStreamLabel, treeItem.logStreamPath);
}
}
/**
* Linux Function Apps only support streaming through App Insights
* For initial support, we will just open the "Live Metrics Stream" view in the portal
*/
async function openLiveMetricsStream(context: IActionContext, site: ParsedSite, node: AzExtTreeItem): Promise<void> {
const client = await site.createClient(context);
const appSettings: StringDictionary = await client.listApplicationSettings();
const aiKey: string | undefined = appSettings.properties && appSettings.properties.APPINSIGHTS_INSTRUMENTATIONKEY;
if (!aiKey) {
// https://github.com/microsoft/vscode-azurefunctions/issues/1432
throw new Error(localize('mustConfigureAI', 'You must configure Application Insights to stream logs on Linux Function Apps.'));
} else {
const aiClient: ApplicationInsightsManagementClient = await createAppInsightsClient([context, node.subscription]);
const components = await uiUtils.listAllIterator(aiClient.components.list());
const component: ApplicationInsightsComponent | undefined = components.find(c => c.instrumentationKey === aiKey);
if (!component) {
throw new Error(localize('failedToFindAI', 'Failed to find application insights component.'));
} else {
const componentId: string = encodeURIComponent(JSON.stringify({
Name: site.fullName,
SubscriptionId: node.subscription.subscriptionId,
ResourceGroup: site.resourceGroup
}));
const resourceId: string = encodeURIComponent(nonNullProp(component, 'id'));
// Not using `openInPortal` because this url is so unconventional
const url: string = `${node.subscription.environment.portalUrl}/#blade/AppInsightsExtension/QuickPulseBladeV2/ComponentId/${componentId}/ResourceId/${resourceId}`;
await openUrl(url);
}
}
}
function isApplicationLoggingEnabled(config: SiteLogsConfig): boolean {
if (config.applicationLogs) {
if (config.applicationLogs.fileSystem) {
return config.applicationLogs.fileSystem.level !== undefined && config.applicationLogs.fileSystem.level.toLowerCase() !== 'off';
} else if (config.applicationLogs.azureBlobStorage) {
return config.applicationLogs.azureBlobStorage.level !== undefined && config.applicationLogs.azureBlobStorage.level.toLowerCase() !== 'off';
} else if (config.applicationLogs.azureTableStorage) {
return config.applicationLogs.azureTableStorage.level !== undefined && config.applicationLogs.azureTableStorage.level.toLowerCase() !== 'off';
}
}
return false;
}