sdk/Sdk/Tasks/GenerateFunctionMetadata.cs (98 lines of code) (raw):
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
namespace Microsoft.Azure.Functions.Worker.Sdk.Tasks
{
#if NET472
[LoadInSeparateAppDomain]
public class GenerateFunctionMetadata : AppDomainIsolatedTask
#else
public class GenerateFunctionMetadata : Task
#endif
{
[Required]
public string? AssemblyPath { get; set; }
[Required]
public string? OutputPath { get; set; }
public string? ExtensionsCsProjFilePath { get; set; }
[Required]
public ITaskItem[]? ReferencePaths { get; set; }
[Required]
public string? AzureFunctionsVersion { get; set; }
[Required]
public string? TargetFrameworkIdentifier { get; set; }
[Required]
public string? TargetFrameworkVersion { get; set; }
public override bool Execute()
{
try
{
var functionGenerator = new FunctionMetadataGenerator(MSBuildLogger);
IEnumerable<SdkFunctionMetadata> functions = functionGenerator.GenerateFunctionMetadata(AssemblyPath!, ReferencePaths ?? Enumerable.Empty<ITaskItem>());
IDictionary<string, string> extensions = functionGenerator.Extensions;
if (!string.IsNullOrEmpty(ExtensionsCsProjFilePath))
{
// Null/empty ExtensionsCsProjFilePath means the extension project is externally provided.
var extensionsCsProjGenerator = new ExtensionsCsprojGenerator(extensions, ExtensionsCsProjFilePath!, AzureFunctionsVersion!, TargetFrameworkIdentifier!, TargetFrameworkVersion!);
extensionsCsProjGenerator.Generate();
}
WriteMetadataWithRetry(functions);
}
catch (FunctionsMetadataGenerationException)
{
Log.LogError($"Unable to build Azure Functions metadata for {AssemblyPath}");
return false;
}
return true;
}
private void WriteMetadataWithRetry(IEnumerable<SdkFunctionMetadata> functions)
{
int attempt = 0;
while (attempt < 10)
{
try
{
FunctionMetadataJsonWriter.WriteMetadata(functions, OutputPath!);
break;
}
catch (IOException ex)
{
attempt++;
if (attempt == 10)
{
Log.LogErrorFromException(ex);
throw new FunctionsMetadataGenerationException();
}
string message = $"Could not write function metadata. Error: '{ex.Message}'. Beginning retry {attempt} of 10 in 1000ms.";
Log.LogWarning(message);
Thread.Sleep(1000);
}
}
}
private void MSBuildLogger(TraceLevel level, string message, string path)
{
switch (level)
{
case TraceLevel.Error:
Log.LogError(null, null, null, file: path, 0, 0, 0, 0, message: message);
break;
case TraceLevel.Info:
Log.LogMessage(message);
break;
case TraceLevel.Verbose:
Log.LogMessage(MessageImportance.Low, message);
break;
case TraceLevel.Warning:
Log.LogWarning(message);
break;
case TraceLevel.Off:
default:
break;
}
}
}
}