Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,9 @@
* SPDX-License-Identifier: Apache-2.0
*/

import * as nls from 'vscode-nls'
import { DefaultCloudWatchLogsClient } from '../../../shared/clients/cloudWatchLogsClient'
import { createBackButton, createExitButton, createHelpButton } from '../../../shared/ui/buttons'
import { createInputBox } from '../../../shared/ui/inputPrompter'
import { DataQuickPickItem } from '../../../shared/ui/pickerPrompter'
import { Wizard } from '../../../shared/wizards/wizard'
import { CloudWatchLogsGroupInfo } from '../registry/logDataRegistry'
import { RegionSubmenu, RegionSubmenuResponse } from '../../../shared/ui/common/regionSubmenu'
import { TailLogGroupWizard } from '../wizard/tailLogGroupWizard'
import { getLogger } from '../../../shared'
import { CancellationError } from '../../../shared/utilities/timeoutUtils'
import { LogStreamFilterResponse, LogStreamFilterSubmenu } from '../liveTailLogStreamSubmenu'
import { getLogger, ToolkitError } from '../../../shared'
import { cwlFilterPatternHelpUrl } from '../../../shared/constants'

const localize = nls.loadMessageBundle()

export interface TailLogGroupWizardResponse {
regionLogGroupSubmenuResponse: RegionSubmenuResponse<string>
logStreamFilter: LogStreamFilterResponse
filterPattern: string
}

export async function tailLogGroup(logData?: { regionName: string; groupName: string }): Promise<void> {
const wizard = new TailLogGroupWizard(logData)
Expand All @@ -34,75 +17,3 @@ export async function tailLogGroup(logData?: { regionName: string; groupName: st
//TODO: Remove Log. For testing while we aren't yet consuming the wizardResponse.
getLogger().info(JSON.stringify(wizardResponse))
}

export class TailLogGroupWizard extends Wizard<TailLogGroupWizardResponse> {
public constructor(logGroupInfo?: CloudWatchLogsGroupInfo) {
super({
initState: {
regionLogGroupSubmenuResponse: logGroupInfo
? {
data: logGroupInfo.groupName,
region: logGroupInfo.regionName,
}
: undefined,
},
})
this.form.regionLogGroupSubmenuResponse.bindPrompter(createRegionLogGroupSubmenu)
this.form.logStreamFilter.bindPrompter((state) => {
if (!state.regionLogGroupSubmenuResponse?.data) {
throw new ToolkitError('LogGroupName is null')
}
return new LogStreamFilterSubmenu(
state.regionLogGroupSubmenuResponse.data,
state.regionLogGroupSubmenuResponse.region
)
})
this.form.filterPattern.bindPrompter((state) => createFilterPatternPrompter())
}
}

export function createRegionLogGroupSubmenu(): RegionSubmenu<string> {
return new RegionSubmenu(
getLogGroupQuickPickOptions,
{
title: localize('AWS.cwl.tailLogGroup.logGroupPromptTitle', 'Select Log Group to tail'),
buttons: [createExitButton()],
},
{ title: localize('AWS.cwl.tailLogGroup.regionPromptTitle', 'Select Region for Log Group') },
'LogGroups'
)
}

async function getLogGroupQuickPickOptions(regionCode: string): Promise<DataQuickPickItem<string>[]> {
const client = new DefaultCloudWatchLogsClient(regionCode)
const logGroups = client.describeLogGroups()

const logGroupsOptions: DataQuickPickItem<string>[] = []

for await (const logGroupObject of logGroups) {
if (!logGroupObject.arn || !logGroupObject.logGroupName) {
throw new ToolkitError('LogGroupObject name or arn undefined')
}

logGroupsOptions.push({
label: logGroupObject.logGroupName,
data: formatLogGroupArn(logGroupObject.arn),
})
}

return logGroupsOptions
}

function formatLogGroupArn(logGroupArn: string): string {
return logGroupArn.endsWith(':*') ? logGroupArn.substring(0, logGroupArn.length - 2) : logGroupArn
}

export function createFilterPatternPrompter() {
const helpUri = cwlFilterPatternHelpUrl
return createInputBox({
title: 'Provide log event filter pattern',
placeholder: 'filter pattern (case sensitive; empty matches all)',
prompt: 'Optional pattern to use to filter the results to include only log events that match the pattern.',
buttons: [createHelpButton(helpUri), createBackButton(), createExitButton()],
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
*/
import * as vscode from 'vscode'
import { CloudWatchLogsClient, StartLiveTailCommand, StartLiveTailCommandOutput } from '@aws-sdk/client-cloudwatch-logs'
import { LogStreamFilterResponse } from '../liveTailLogStreamSubmenu'
import { LogStreamFilterResponse } from '../wizard/liveTailLogStreamSubmenu'
import { CloudWatchLogsSettings } from '../cloudWatchLogsUtils'
import { Settings, ToolkitError } from '../../../shared'
import { createLiveTailURIFromArgs } from './liveTailSessionRegistry'
import { getUserAgent } from '../../../shared/telemetry/util'

export type LiveTailSessionConfiguration = {
logGroupName: string
Expand Down Expand Up @@ -35,7 +36,10 @@ export class LiveTailSession {
this._logGroupName = configuration.logGroupName
this.logStreamFilter = configuration.logStreamFilter
this.liveTailClient = {
cwlClient: new CloudWatchLogsClient({ region: configuration.region }),
cwlClient: new CloudWatchLogsClient({
region: configuration.region,
customUserAgent: getUserAgent(),
}),
abortController: new AbortController(),
}
this._maxLines = LiveTailSession.settings.get('liveTailMaxEvents', 10000)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
import { Prompter, PromptResult } from '../../shared/ui/prompter'
import { DefaultCloudWatchLogsClient } from '../../shared/clients/cloudWatchLogsClient'
import { createCommonButtons } from '../../shared/ui/buttons'
import { createInputBox, InputBoxPrompter } from '../../shared/ui/inputPrompter'
import { createQuickPick, DataQuickPickItem, QuickPickPrompter } from '../../shared/ui/pickerPrompter'
import { pageableToCollection } from '../../shared/utilities/collectionUtils'
import { Prompter, PromptResult } from '../../../shared/ui/prompter'
import { DefaultCloudWatchLogsClient } from '../../../shared/clients/cloudWatchLogsClient'
import { createCommonButtons } from '../../../shared/ui/buttons'
import { createInputBox, InputBoxPrompter } from '../../../shared/ui/inputPrompter'
import { createQuickPick, DataQuickPickItem, QuickPickPrompter } from '../../../shared/ui/pickerPrompter'
import { pageableToCollection } from '../../../shared/utilities/collectionUtils'
import { CloudWatchLogs } from 'aws-sdk'
import { isValidResponse, StepEstimator } from '../../shared/wizards/wizard'
import { isNonNullable } from '../../shared/utilities/tsUtils'
import { isValidResponse, StepEstimator } from '../../../shared/wizards/wizard'
import { isNonNullable } from '../../../shared/utilities/tsUtils'
import {
startLiveTailHelpUrl,
startLiveTailLogStreamNamesHelpUrl,
startLiveTailLogStreamPrefixHelpUrl,
} from '../../shared/constants'
} from '../../../shared/constants'

export type LogStreamFilterType = 'menu' | 'prefix' | 'specific' | 'all'

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*!
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/

import * as nls from 'vscode-nls'
import { ToolkitError } from '../../../shared'
import { DefaultCloudWatchLogsClient } from '../../../shared/clients/cloudWatchLogsClient'
import { cwlFilterPatternHelpUrl } from '../../../shared/constants'
import { createBackButton, createExitButton, createHelpButton } from '../../../shared/ui/buttons'
import { RegionSubmenu, RegionSubmenuResponse } from '../../../shared/ui/common/regionSubmenu'
import { createInputBox } from '../../../shared/ui/inputPrompter'
import { DataQuickPickItem } from '../../../shared/ui/pickerPrompter'
import { Wizard } from '../../../shared/wizards/wizard'
import { CloudWatchLogsGroupInfo } from '../registry/logDataRegistry'
import { LogStreamFilterResponse, LogStreamFilterSubmenu } from './liveTailLogStreamSubmenu'

const localize = nls.loadMessageBundle()

export interface TailLogGroupWizardResponse {
regionLogGroupSubmenuResponse: RegionSubmenuResponse<string>
logStreamFilter: LogStreamFilterResponse
filterPattern: string
}

export class TailLogGroupWizard extends Wizard<TailLogGroupWizardResponse> {
public constructor(logGroupInfo?: CloudWatchLogsGroupInfo) {
super({
initState: {
regionLogGroupSubmenuResponse: logGroupInfo
? {
data: logGroupInfo.groupName,
region: logGroupInfo.regionName,
}
: undefined,
},
})
this.form.regionLogGroupSubmenuResponse.bindPrompter(createRegionLogGroupSubmenu)
this.form.logStreamFilter.bindPrompter((state) => {
if (!state.regionLogGroupSubmenuResponse?.data) {
throw new ToolkitError('LogGroupName is null')
}
return new LogStreamFilterSubmenu(
state.regionLogGroupSubmenuResponse.data,
state.regionLogGroupSubmenuResponse.region
)
})
this.form.filterPattern.bindPrompter((state) => createFilterPatternPrompter())
}
}

export function createRegionLogGroupSubmenu(): RegionSubmenu<string> {
return new RegionSubmenu(
getLogGroupQuickPickOptions,
{
title: localize('AWS.cwl.tailLogGroup.logGroupPromptTitle', 'Select Log Group to tail'),
buttons: [createExitButton()],
},
{ title: localize('AWS.cwl.tailLogGroup.regionPromptTitle', 'Select Region for Log Group') },
'LogGroups'
)
}

async function getLogGroupQuickPickOptions(regionCode: string): Promise<DataQuickPickItem<string>[]> {
const client = new DefaultCloudWatchLogsClient(regionCode)
const logGroups = client.describeLogGroups()

const logGroupsOptions: DataQuickPickItem<string>[] = []

for await (const logGroupObject of logGroups) {
if (!logGroupObject.arn || !logGroupObject.logGroupName) {
throw new ToolkitError('LogGroupObject name or arn undefined')
}

logGroupsOptions.push({
label: logGroupObject.logGroupName,
data: formatLogGroupArn(logGroupObject.arn),
})
}

return logGroupsOptions
}

function formatLogGroupArn(logGroupArn: string): string {
return logGroupArn.endsWith(':*') ? logGroupArn.substring(0, logGroupArn.length - 2) : logGroupArn
}

export function createFilterPatternPrompter() {
const helpUri = cwlFilterPatternHelpUrl
return createInputBox({
title: 'Provide log event filter pattern',
placeholder: 'filter pattern (case sensitive; empty matches all)',
prompt: 'Optional pattern to use to filter the results to include only log events that match the pattern.',
buttons: [createHelpButton(helpUri), createBackButton(), createExitButton()],
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
*/

import assert from 'assert'
import { LogStreamFilterSubmenu } from '../../../awsService/cloudWatchLogs/liveTailLogStreamSubmenu'
import { createQuickPickPrompterTester, QuickPickPrompterTester } from '../../shared/ui/testUtils'
import { getTestWindow } from '../../shared/vscode/window'
import { LogStreamFilterSubmenu } from '../../../../awsService/cloudWatchLogs/wizard/liveTailLogStreamSubmenu'
import { createQuickPickPrompterTester, QuickPickPrompterTester } from '../../../shared/ui/testUtils'
import { getTestWindow } from '../../../shared/vscode/window'

describe('liveTailLogStreamSubmenu', async function () {
let logStreamFilterSubmenu: LogStreamFilterSubmenu
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

import { TailLogGroupWizard } from '../../../../awsService/cloudWatchLogs/commands/tailLogGroup'
import { TailLogGroupWizard } from '../../../../awsService/cloudWatchLogs/wizard/tailLogGroupWizard'
import { createWizardTester } from '../../../shared/wizards/wizardTestUtils'

describe('TailLogGroupWizard', async function () {
Expand Down
Loading