Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ public void ResetWaitingTasks()
HistoryTaskCompletionSource = new TaskCompletionSource();
RequestPredictionTaskCompletionSource = new TaskCompletionSource();
SendTelemetryTaskCompletionSource = new TaskCompletionSource();
HistoryData = default;
RequestPredictionData = default;
}

protected override TelemetryClient GetApplicationInsightTelemetryClient()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

<PropertyGroup>
<PackageId>Az.Tools.Predictor</PackageId>
<Version>0.2.0</Version>
<Version>0.2.1</Version>
<Authors>Microsoft Corporation</Authors>
<Company>Microsoft Corporation</Company>
<Copyright>Microsoft Corporation. All rights reserved.</Copyright>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
RootModule = ''

# Version number of this module.
ModuleVersion = '0.2.0'
ModuleVersion = '0.2.1'

# Supported PSEditions
CompatiblePSEditions = 'Core'
Expand Down Expand Up @@ -47,7 +47,7 @@ NestedModules = @("Microsoft.Azure.PowerShell.Tools.AzPredictor.dll")

ScriptsToProcess = @("PromptSurvey.ps1")

CmdletsToExport = @("Enable-AzPredictor", "Disable-AzPredictor")
CmdletsToExport = @("Enable-AzPredictor", "Disable-AzPredictor", "Open-AzSurveyLink")

# Format files (.ps1xml) to be loaded when importing this module

Expand Down
22 changes: 9 additions & 13 deletions tools/Az.Tools.Predictor/Az.Tools.Predictor/AzPredictor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,11 @@ public void StartEarlyProcessing(string clientId, IReadOnlyList<string> history)
{
string secondToLastLine = history.TakeLast(AzPredictorConstants.CommandHistoryCountToProcess).First();
var secondToLastCommand = GetAstAndMaskedCommandLine(secondToLastLine);
_lastTwoMaskedCommands.Enqueue(secondToLastCommand.Item2);
_lastTwoMaskedCommands.Enqueue(secondToLastCommand.IsSupported ? secondToLastCommand.MaskedValue : AzPredictorConstants.CommandPlaceholder);

if (!string.Equals(AzPredictorConstants.CommandPlaceholder, secondToLastCommand.Item2, StringComparison.Ordinal))
if (secondToLastCommand.IsSupported)
{
_service.RecordHistory(secondToLastCommand.Item1);
_service.RecordHistory(secondToLastCommand.Ast);
}
}
else
Expand All @@ -139,7 +139,7 @@ public void StartEarlyProcessing(string clientId, IReadOnlyList<string> history)

string lastLine = history.Last();
var lastCommand = GetAstAndMaskedCommandLine(lastLine);
bool isLastCommandSupported = !string.Equals(AzPredictorConstants.CommandPlaceholder, lastCommand.Item2, StringComparison.Ordinal);
bool isLastCommandSupported = lastCommand.IsSupported;

if (isLastCommandSupported)
{
Expand All @@ -162,7 +162,7 @@ public void StartEarlyProcessing(string clientId, IReadOnlyList<string> history)
_lastTwoMaskedCommands.Enqueue(existingInQueue);
}

_telemetryClient.OnHistory(new HistoryTelemetryData(clientId, lastCommand.Item2));
_telemetryClient.OnHistory(new HistoryTelemetryData(clientId, lastCommand.MaskedValue ?? AzPredictorConstants.CommandPlaceholder));

if (isLastTwoCommandsChanged)
{
Expand Down Expand Up @@ -202,21 +202,17 @@ public void StartEarlyProcessing(string clientId, IReadOnlyList<string> history)
}
}

ValueTuple<CommandAst, string> GetAstAndMaskedCommandLine(string commandLine)
(CommandAst Ast, string MaskedValue, bool IsSupported) GetAstAndMaskedCommandLine(string commandLine)
{
var asts = Parser.ParseInput(commandLine, out _, out _);
var allNestedAsts = asts?.FindAll((ast) => ast is CommandAst, true);
var commandAst = allNestedAsts?.LastOrDefault() as CommandAst;
string maskedCommandLine = AzPredictorConstants.CommandPlaceholder;

var commandName = commandAst?.CommandElements?.FirstOrDefault().ToString();
bool isSupported = _service.IsSupportedCommand(commandName);
string maskedCommandLine = CommandLineUtilities.MaskCommandLine(commandAst);

if (_service.IsSupportedCommand(commandName))
{
maskedCommandLine = CommandLineUtilities.MaskCommandLine(commandAst);
}

return ValueTuple.Create(commandAst, maskedCommandLine);
return (commandAst, maskedCommandLine, isSupported);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ public virtual async Task<bool> RequestPredictionsAsync(IEnumerable<string> comm
{
SetCommandToRequestPrediction(localCommands);

AzPredictorService.SetHttpRequestHeader(_client?.DefaultRequestHeaders, _azContext.HashUserId, _telemetryClient.CorrelationId);
AzPredictorService.SetHttpRequestHeader(_client?.DefaultRequestHeaders, _azContext.HashUserId, _telemetryClient.RequestId);

var requestContext = new PredictionRequestBody.RequestContext()
{
Expand Down Expand Up @@ -313,7 +313,7 @@ protected virtual void RequestAllPredictiveCommands()

try
{
AzPredictorService.SetHttpRequestHeader(_client.DefaultRequestHeaders, _azContext.HashUserId, _telemetryClient.CorrelationId);
AzPredictorService.SetHttpRequestHeader(_client.DefaultRequestHeaders, _azContext.HashUserId, _telemetryClient.RequestId);

var httpResponseMessage = await _client.GetAsync(_commandsEndpoint);
hasSentHttpRequest = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// ----------------------------------------------------------------------------------
//
// Copyright Microsoft Corporation
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------------

using Microsoft.Azure.PowerShell.Tools.AzPredictor.Utilities;
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Management.Automation;
using System.Text;
using System.Text.Json;

namespace Microsoft.Azure.PowerShell.Tools.AzPredictor
{
/// <summary>
/// <para type="synopsis">Cmdlet to open a survey link in the default browser</para>
/// <para type="description">Use this cmdlet to open a survey link in the default browser</para>
/// </summary>
[Cmdlet("Open", "AzSurveyLink"), OutputType(typeof(bool))]
public sealed class OpenAzSurveyLink : PSCmdlet
{
private const string _SurveyLinkFormat = "https://aka.ms/azpredictorisurvey?SessionId={0}&from=cmdlet";
/// <summary>
/// <para type="description">Indicates whether the user would like to receive output. </para>
/// </summary>
[Parameter(Mandatory = false)]
public SwitchParameter PassThru { get; set; }

/// <inheritdoc/>
protected override void ProcessRecord()
{
var profileSettings = Settings.GetProfileSettings();
var surveyId = profileSettings?.SurveyId?.ToString(CultureInfo.InvariantCulture) ?? "000000";

var link = string.Format(OpenAzSurveyLink._SurveyLinkFormat, surveyId, CultureInfo.InvariantCulture);

Console.WriteLine($"Opening survey {link}");

// TODO [mahuang] Ouput the link for user to copy/paste in case it's not open in the default browser.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you able to do this now or is this a later thing?

var processStartInfo = new ProcessStartInfo();
processStartInfo.FileName = link;
processStartInfo.UseShellExecute = true;

Process.Start(processStartInfo);

if (profileSettings != null)
{
profileSettings.SurveyId = null;

try
{
var fileContent = JsonSerializer.Serialize<Settings>(profileSettings, new JsonSerializerOptions(JsonUtilities.DefaultSerializerOptions)
{
WriteIndented = true,
});
var profileSettingFilePath = Settings.GetProfileSettingsFilePath();
File.WriteAllText(profileSettingFilePath, fileContent, Encoding.UTF8);
}
catch
{
// Ignore all exceptions.
}
}

if (PassThru.IsPresent)
{
WriteObject(true);
}
}
}
}
37 changes: 24 additions & 13 deletions tools/Az.Tools.Predictor/Az.Tools.Predictor/InterceptSurvey.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ if ($env:Azure_PS_Intercept_Survey -eq "false") {
$mutexName = "AzModulesInterceptSurvey"
$mutexTiimeout = 1000
$interceptDays = 30
$interceptLoadTimes = 3
$interceptIntervals = ( 3, 2, 5 )
$interceptMaxTimes = 3 # Show intercept this many times in total.
$today = Get-Date
$mutexTimeout = 500

Expand All @@ -54,17 +55,21 @@ function ConvertTo-String {
return $date.ToString("yyyy-MM-dd")
}

function Init-InterceptFile {
$interceptContent = @{
function Init-InterceptObject {
return @{
"lastInterceptCheckDate"=ConvertTo-String($today);
"interceptTriggered"=$false;
"interceptTriggered"=0;
"modules"=@(@{
"name"=$moduleName;
"majorVersion"=$majorVersion;
"activeDays"=1;
"lastActiveDate"=ConvertTo-String($today);
})
}
}

function Init-InterceptFile {
$interceptContent = Init-InterceptObject

ConvertTo-Json -InputObject $interceptContent | Out-File -FilePath $interceptFilePath -Encoding utf8
}
Expand Down Expand Up @@ -106,12 +111,12 @@ function Update-InterceptObject {
if ($recordedMajorVersion -ne $majorVersion) {
$thisModule.activeDays = 1
$thisModule.lastActiveDate = ConvertTo-String($today)
$interceptObject.interceptTriggered = $false
$interceptObject.interceptTriggered = 0

return $false
}

if ($interceptObject.interceptTriggered) {
if ($interceptObject.interceptTriggered -ge $interceptMaxTimes) {
return $false
}

Expand All @@ -133,10 +138,10 @@ function Update-InterceptObject {
$newActiveDays++
}

if ($newActiveDays -ge $interceptLoadTimes) {
if ($newActiveDays -ge $interceptIntervals[$interceptObject.interceptTriggered]) {
$thisModule.activeDays = 0
$thisModule.lastActiveDate = ConvertTo-String($today)
$interceptObject.interceptTriggered = $true
$interceptObject.interceptTriggered++
return $true
}

Expand Down Expand Up @@ -166,15 +171,21 @@ try
try {
$fileContent = Get-Content $interceptFilePath | Out-String
$interceptObject = ConvertFrom-Json $fileContent

if ($interceptObject.interceptTriggered.GetType() -eq $true.GetType()) {
# HACK change the use of interceptTriggered from a boolean to an integer. It's to count how many times the intercept is tirggered.
$interceptObject.interceptTriggered = 0
}
} catch {
Init-InterceptFile
}

if (-not ($interceptObject -eq $null)) {
$shouldIntercept = Update-InterceptObject($interceptObject)

ConvertTo-Json -InputObject $interceptObject | Out-File $interceptFilePath -Encoding utf8
if ($null -eq $interceptObject) {
$interceptObject = Init-InterceptObject
}

$shouldIntercept = Update-InterceptObject($interceptObject)

ConvertTo-Json -InputObject $interceptObject | Out-File $interceptFilePath -Encoding utf8
}
} catch {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
# ----------------------------------------------------------------------------------

$targetScript = (Join-Path -Path $PSScriptRoot -ChildPath "InterceptSurvey.ps1")
& $targetScript "Az.Tools.Predictor" 0
& $targetScript "Az.Tools.Predictor-Preview3" 0
Loading