Skip to content

Project stein - Adding additional logs and exception handling #8231

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Apr 27, 2022
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
7 changes: 6 additions & 1 deletion src/WebJobs.Script.Grpc/Channel/GrpcWorkerChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -545,11 +545,16 @@ internal Task<List<RawFunctionMetadata>> SendFunctionMetadataRequest()
return _functionsIndexingTask.Task;
}

// parse metadata response into RawFunctionMetadata objects for WorkerFunctionMetadataProvider to further parse and validate
// parse metadata response into RawFunctionMetadata objects for AggregateFunctionMetadataProvider to further parse and validate
internal void ProcessFunctionMetadataResponses(FunctionMetadataResponse functionMetadataResponse)
{
_workerChannelLogger.LogDebug("Received the worker function metadata response from worker {worker_id}", _workerId);

if (functionMetadataResponse.Result.IsFailure(out Exception metadataResponseEx))
{
_workerChannelLogger?.LogError(metadataResponseEx, "Worker failed to index functions");
}

var functions = new List<RawFunctionMetadata>();

if (functionMetadataResponse.UseDefaultMetadataIndexing == false)
Expand Down
15 changes: 12 additions & 3 deletions src/WebJobs.Script/Host/AggregateFunctionMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public async Task<ImmutableArray<FunctionMetadata>> GetFunctionMetadataAsync(IEn
await _dispatcher.FinishInitialization(functions);

// Validate if the app has functions in legacy format and add in logs to inform about the mixed app
_ = Task.Delay(TimeSpan.FromMinutes(1)).ContinueWith(t => ValidateFunctionAppFormat(_scriptOptions.Value.RootScriptPath, _logger));
_ = Task.Delay(TimeSpan.FromMinutes(1)).ContinueWith(t => ValidateFunctionAppFormat(_scriptOptions.Value.RootScriptPath, _logger, environment));
}
else
{
Expand All @@ -93,7 +93,7 @@ public async Task<ImmutableArray<FunctionMetadata>> GetFunctionMetadataAsync(IEn
return _functions;
}

internal static void ValidateFunctionAppFormat(string scriptPath, ILogger logger, IFileSystem fileSystem = null)
internal static void ValidateFunctionAppFormat(string scriptPath, ILogger logger, IEnvironment environment, IFileSystem fileSystem = null)
{
fileSystem = fileSystem ?? FileUtility.Instance;
bool mixedApp = false;
Expand All @@ -114,7 +114,16 @@ internal static void ValidateFunctionAppFormat(string scriptPath, ILogger logger

if (mixedApp)
{
logger.Log(LogLevel.Information, $"Detected mixed function app. Some functions may not be indexed - {legacyFormatFunctions}");
string logMessage = $"Detected mixed function app. Some functions may not be indexed - {legacyFormatFunctions}";

if (environment.IsCoreTools())
{
logger.Log(LogLevel.Warning, logMessage + " Refer to the documentation to filter warning - https://docs.microsoft.com/en-us/azure/azure-functions/configure-monitoring?tabs=v2");
}
else
{
logger.Log(LogLevel.Information, logMessage);
}
}
}
}
Expand Down
10 changes: 7 additions & 3 deletions src/WebJobs.Script/Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -906,17 +906,21 @@ public static void ValidateRetryOptions(RetryOptions

public static bool CanWorkerIndex(IEnumerable<RpcWorkerConfig> workerConfigs, IEnvironment environment)
{
if (!FeatureFlags.IsEnabled(ScriptConstants.FeatureFlagEnableWorkerIndexing, environment))
{
return false;
}

var workerRuntime = environment.GetEnvironmentVariable(EnvironmentSettingNames.FunctionWorkerRuntime);
if (workerConfigs != null)
{
var workerConfig = workerConfigs.Where(c => c.Description != null && c.Description.Language != null && c.Description.Language.Equals(workerRuntime, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();

// if feature flag is enabled and workerConfig.WorkerIndexing == true, then return true
if (FeatureFlags.IsEnabled(ScriptConstants.FeatureFlagEnableWorkerIndexing, environment)
&& (workerConfig != null
if (workerConfig != null
&& workerConfig.Description != null
&& workerConfig.Description.WorkerIndexing != null
&& workerConfig.Description.WorkerIndexing.Equals("true", StringComparison.OrdinalIgnoreCase)))
&& workerConfig.Description.WorkerIndexing.Equals("true", StringComparison.OrdinalIgnoreCase))
{
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ public void ValidateFunctionAppFormat_InputMixedApp()
{
_logger.ClearLogMessages();
string scriptPath = Path.Combine(Environment.CurrentDirectory, @"..", "..", "..", "..", "..", "sample", "node");
AggregateFunctionMetadataProvider.ValidateFunctionAppFormat(scriptPath, _logger);
var environment = SystemEnvironment.Instance;
AggregateFunctionMetadataProvider.ValidateFunctionAppFormat(scriptPath, _logger, environment);
var traces = _logger.GetLogMessages();
var functionLoadLogs = traces.Where(m => m.FormattedMessage.Contains("Detected mixed function app. Some functions may not be indexed"));
Assert.True(functionLoadLogs.Any());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,15 @@ public void ReceivesInboundEvent_Failed_FunctionMetadataResponse()
Assert.True(traces.Any(m => string.Equals(m.FormattedMessage, $"Worker failed to index function {functionId}")));
}

[Fact]
public void ReceivesInboundEvent_Failed_OverallFunctionMetadataResponse()
{
var functions = _workerChannel.GetFunctionMetadata();
_testFunctionRpcService.PublishWorkerMetadataResponse("TestFunctionId1", null, null, false, false, false);
var traces = _logger.GetLogMessages();
Assert.True(traces.Any(m => string.Equals(m.FormattedMessage, $"Worker failed to index functions")));
}

[Fact]
public void FunctionLoadRequest_IsExpected()
{
Expand Down
28 changes: 18 additions & 10 deletions test/WebJobs.Script.Tests/Workers/Rpc/TestFunctionRpcService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ public void PublishStartStreamEvent(string workerId)
_eventManager.Publish(new InboundGrpcEvent(_workerId, responseMessage));
}

public void PublishWorkerMetadataResponse(string workerId, string functionId, IEnumerable<FunctionMetadata> functionMetadata, bool successful, bool useDefaultMetadataIndexing = false)
public void PublishWorkerMetadataResponse(string workerId, string functionId, IEnumerable<FunctionMetadata> functionMetadata, bool successful, bool useDefaultMetadataIndexing = false, bool overallStatus = true)
{
StatusResult statusResult = new StatusResult();
if (successful)
Expand All @@ -215,19 +215,27 @@ public void PublishWorkerMetadataResponse(string workerId, string functionId, IE
FunctionMetadataResponse overallResponse = new FunctionMetadataResponse();
overallResponse.UseDefaultMetadataIndexing = useDefaultMetadataIndexing;

foreach (FunctionMetadata response in functionMetadata)
if (functionMetadata != null)
{
RpcFunctionMetadata indexingResponse = new RpcFunctionMetadata()
foreach (FunctionMetadata response in functionMetadata)
{
Name = response.Name,
Language = response.Language,
Status = statusResult,
FunctionId = functionId
};

overallResponse.FunctionMetadataResults.Add(indexingResponse);
RpcFunctionMetadata indexingResponse = new RpcFunctionMetadata()
{
Name = response.Name,
Language = response.Language,
Status = statusResult,
FunctionId = functionId
};

overallResponse.FunctionMetadataResults.Add(indexingResponse);
}
}

overallResponse.Result = new StatusResult()
{
Status = overallStatus == true ? StatusResult.Types.Status.Success : StatusResult.Types.Status.Failure
};

StreamingMessage responseMessage = new StreamingMessage()
{
FunctionMetadataResponse = overallResponse
Expand Down