/// <summary> /// Requests a list of popular commands from service. These commands are used as fall back suggestion /// if none of the predictions fit for the current input. This method should be called once per session. /// </summary> protected virtual void RequestAllPredictiveCommands() { // We don't need to block on the task. We send the HTTP request and update commands and predictions list at the background. Task.Run(async() => { Exception exception = null; try { AzPredictorService.SetHttpRequestHeader(_client.DefaultRequestHeaders, _azContext.UserId, _telemetryClient.CorrelationId); var httpResponseMessage = await _client.GetAsync(_commandsEndpoint); httpResponseMessage.EnsureSuccessStatusCode(); var reply = await httpResponseMessage.Content.ReadAsStringAsync(); var commandsReply = JsonSerializer.Deserialize <IList <PredictiveCommand> >(reply, JsonUtilities.DefaultSerializerOptions); SetFallbackPredictor(commandsReply); } catch (Exception e) { exception = e; } finally { _telemetryClient.OnRequestPrediction(new RequestPredictionTelemetryData("request_commands", hasSentHttpRequest: true, exception: exception)); } // Initialize predictions RequestPredictions(new string[] { AzPredictorConstants.CommandPlaceholder, AzPredictorConstants.CommandPlaceholder }); }); }
/// <summary> /// Requests a list of popular commands from service. These commands are used as fall back suggestion /// if none of the predictions fit for the current input. This method should be called once per session. /// </summary> protected virtual void RequestAllPredictiveCommands() { // We don't need to block on the task. We send the HTTP request and update commands and predictions list at the background. Task.Run(async() => { var hasSentHttpRequest = false; Exception exception = null; try { AzPredictorService.SetHttpRequestHeader(_client.DefaultRequestHeaders, _azContext.HashUserId, _telemetryClient.RequestId); var httpResponseMessage = await _client.GetAsync(_commandsEndpoint); hasSentHttpRequest = true; httpResponseMessage.EnsureSuccessStatusCode(); var reply = await httpResponseMessage.Content.ReadAsStringAsync(); var commandsReply = JsonSerializer.Deserialize <IList <PredictiveCommand> >(reply, JsonUtilities.DefaultSerializerOptions); SetFallbackPredictor(commandsReply); } catch (Exception e) when(!(e is OperationCanceledException)) { exception = e; } finally { _telemetryClient.OnRequestPrediction(new RequestPredictionTelemetryData(AzPredictorConstants.DefaultClientId, new List <string>(), hasSentHttpRequest, exception)); } // Initialize predictions hasSentHttpRequest = false; var placeholderCommands = new string[] { AzPredictorConstants.CommandPlaceholder, AzPredictorConstants.CommandPlaceholder }; try { hasSentHttpRequest = await RequestPredictionsAsync(placeholderCommands, CancellationToken.None); } catch (ServiceRequestException e) { hasSentHttpRequest = e.IsRequestSent; exception = e.InnerException; } catch (Exception e) { exception = e; } finally { _telemetryClient.OnRequestPrediction(new RequestPredictionTelemetryData(AzPredictorConstants.DefaultClientId, placeholderCommands, hasSentHttpRequest, (exception is OperationCanceledException ? null : exception))); } }); }
/// <inheritdoc/> public virtual async Task <bool?> RequestPredictionsAsync(IEnumerable <string> commands, string requestId, CancellationToken cancellationToken) { Validation.CheckArgument(commands, $"{nameof(commands)} cannot be null."); var localCommands = string.Join(AzPredictorConstants.CommandConcatenator, commands); bool isRequestSent = false; try { if (string.Equals(localCommands, _commandToRequestPrediction, StringComparison.OrdinalIgnoreCase)) { // It's the same history we've already requested the prediction for last time, skip it. return(null); } if (!commands.Any()) { return(null); } // We have a check to avoid sending the request using the same commands. So we only check if it's cancelled // here. We don't cancel the request once we set _commandToRequestPrediction to localCommands. cancellationToken.ThrowIfCancellationRequested(); cancellationToken = CancellationToken.None; SetCommandToRequestPrediction(localCommands); AzPredictorService.SetHttpRequestHeader(_client?.DefaultRequestHeaders, _azContext.HashUserId, requestId); var requestContext = new PredictionRequestBody.RequestContext() { VersionNumber = this._azContext.AzVersion }; var requestBody = new PredictionRequestBody(commands) { Context = requestContext, }; var requestBodyString = JsonSerializer.Serialize(requestBody, JsonUtilities.DefaultSerializerOptions); var httpResponseMessage = await _client.PostAsync(_predictionsEndpoint, new StringContent(requestBodyString, Encoding.UTF8, "application/json"), cancellationToken); isRequestSent = true; httpResponseMessage.EnsureSuccessStatusCode(); var reply = await httpResponseMessage.Content.ReadAsStreamAsync(cancellationToken); var suggestionsList = await JsonSerializer.DeserializeAsync <IList <PredictiveCommand> >(reply, JsonUtilities.DefaultSerializerOptions); SetCommandBasedPreditor(localCommands, suggestionsList); } catch (Exception e) when(!(e is OperationCanceledException)) { throw new ServiceRequestException(e.Message, e) { IsRequestSent = isRequestSent }; } return(isRequestSent); }
cmd.IndexOf(AzPredictorConstants.AzCommandMoniker) > 0; // This is the Az cmdlet. /// <summary> /// Requests a list of popular commands from service. These commands are used as fall back suggestion /// if none of the predictions fit for the current input. This method should be called once per session. /// </summary> protected virtual void RequestAllPredictiveCommands() { // We don't need to block on the task. We send the HTTP request and update commands and predictions list at the background. Task.Run(async() => { var hasSentHttpRequest = false; Exception exception = null; var requestId = Guid.NewGuid().ToString(); try { AzPredictorService.SetHttpRequestHeader(_client.DefaultRequestHeaders, _azContext.HashUserId, requestId); var httpResponseMessage = await _client.GetAsync(_commandsEndpoint); hasSentHttpRequest = true; httpResponseMessage.EnsureSuccessStatusCode(); var reply = await httpResponseMessage.Content.ReadAsStringAsync(); var commandsReply = JsonSerializer.Deserialize <List <PredictiveCommand> >(reply, JsonUtilities.DefaultSerializerOptions); commandsReply.AddRange(_surveyCmdlets); SetFallbackPredictor(commandsReply); } catch (Exception e) when(!(e is OperationCanceledException)) { exception = e; } finally { _telemetryClient.RequestId = requestId; _telemetryClient.OnRequestPrediction(new RequestPredictionTelemetryData(null, new List <string>(), hasSentHttpRequest, exception)); } // Initialize predictions var placeholderCommands = new string[] { AzPredictorConstants.CommandPlaceholder, AzPredictorConstants.CommandPlaceholder }; return(AzPredictorUtilities.RequestPredictionAndCollectTelemetryAync(this, _telemetryClient, null, placeholderCommands, null, CancellationToken.None)); }); }
/// <inheritdoc/> public virtual void RequestPredictions(IEnumerable <string> commands) { Validation.CheckArgument(commands, $"{nameof(commands)} cannot be null."); var localCommands = string.Join(AzPredictorConstants.CommandConcatenator, commands); bool postSuccess = false; Exception exception = null; bool startRequestTask = false; try { if (string.Equals(localCommands, _commandToRequestPrediction, StringComparison.Ordinal)) { // It's the same history we've already requested the prediction for last time, skip it. return; } if (commands.Any()) { SetCommandToRequestPrediction(localCommands); // When it's called multiple times, we only need to keep the one for the latest command. _predictionRequestCancellationSource?.Cancel(); _predictionRequestCancellationSource = new CancellationTokenSource(); var cancellationToken = _predictionRequestCancellationSource.Token; // We don't need to block on the task. We send the HTTP request and update prediction list at the background. startRequestTask = true; Task.Run(async() => { try { AzPredictorService.SetHttpRequestHeader(_client?.DefaultRequestHeaders, _azContext.UserId, _telemetryClient.CorrelationId); var requestContext = new PredictionRequestBody.RequestContext() { VersionNumber = this._azContext.AzVersion }; var requestBody = new PredictionRequestBody(commands) { Context = requestContext, }; var requestBodyString = JsonSerializer.Serialize(requestBody, JsonUtilities.DefaultSerializerOptions); var httpResponseMessage = await _client.PostAsync(_predictionsEndpoint, new StringContent(requestBodyString, Encoding.UTF8, "application/json"), cancellationToken); postSuccess = true; httpResponseMessage.EnsureSuccessStatusCode(); var reply = await httpResponseMessage.Content.ReadAsStreamAsync(cancellationToken); var suggestionsList = await JsonSerializer.DeserializeAsync <IList <PredictiveCommand> >(reply, JsonUtilities.DefaultSerializerOptions); SetCommandBasedPreditor(localCommands, suggestionsList); } catch (Exception e) when(!(e is OperationCanceledException)) { exception = e; } finally { _telemetryClient.OnRequestPrediction(new RequestPredictionTelemetryData(localCommands, postSuccess, exception)); } }, cancellationToken); } } catch (Exception e) { exception = e; } finally { if (!startRequestTask) { _telemetryClient.OnRequestPrediction(new RequestPredictionTelemetryData(localCommands, hasSentHttpRequest: false, exception: exception)); } } }