1 回答
TA贡献1829条经验 获得超7个赞
Microsoft 曾经支持一个名为BuildInfo.config
该文件的文件,该文件对这类事情很有用,但我认为在 Visual Studio 2015 之后就放弃了对它的支持。
基本上,它是一个由 MSBuild 创建的简单 XML 文件。当与应用程序二进制文件一起部署时,日志框架可以读取文件并将详细信息包含在日志输出中。
您可以通过多种方式自己创建类似的功能。这就是我要做的...
创建一个空的构建信息文件并将其与您的源代码一起签入。该文件只是一个参考示例——使用占位符数据。它可以是 XML、JSON 或任何其他格式(但应该是基于文本的)。将文件的构建操作设置为“内容”,以便将其包含在构建输出中。
使用您的日志框架的模板或遥测初始化功能来读取构建信息文件并将其内容包含在日志输出中。确切的实现将取决于您的日志框架。
将 Powershell 脚本任务添加到 Azure DevOps 管道。该脚本应该更新或覆盖构建信息文件。您可以从构建变量中获得一些好的信息。该任务应在 MSBuild 编译步骤之前运行。
创建和解析 BuildInfo 文件
对于此示例,我将在文本文件中将构建信息文件实现为简单的键/值对。我选择了简单的文本,因为它允许一个清晰的示例,而不需要任何第三方库或复杂的解析。在您的应用程序中,您可能希望使用 JSON、XML 或其他更标准化的东西。
首先,创建一个占位符构建信息文件。该文件将在您的本地开发环境中使用,并将作为您的构建信息架构的参考。我打电话给 mine BuildInfo.txt
,并将其放在我项目的根目录中。
COMMIT=commit not set BUILD=build not set
接下来,编写一个帮助程序来解析构建信息文件。我的很简陋。添加一些针对丢失或格式错误的构建信息的防御措施是明智的,但我选择省略任何防御性代码以保持示例的重点。
class BuildInfo
{
// Singleton instance backing field
static readonly Lazy<BuildInfo> instance = new Lazy<BuildInfo>(() => new BuildInfo());
// Singleton instance public accessor
public static BuildInfo Instance => instance.Value;
public string Commit { get; }
public string Build { get; }
private BuildInfo()
{
// This is a very rudimentary example of parsing the info file. It
// will fail loudly on malformed input. Consider:
// 1) Using a standard file format (JSON, XML). I rolled my own
// here to avoid adding a dependency on a parsing library.
// 2) If you want your app to fail when no build info is
// available, add a more descriptive exception. If you don't
// want it to fail, add some devensive code or fallback logic.
var info = File.ReadAllLines("BuildInfo.txt")
.Select(l => l.Split('=', 2))
.ToDictionary(key => key[0], val => val[1]);
Commit = info["COMMIT"];
Build = info["BUILD"];
}
}
将构建信息添加到您的日志输出
我在这里使用 log4net,但是任何日志框架都应该有一些类似的机制来自定义日志输出。有关更多信息,请参阅框架的文档。
首先,将您的构建信息添加到日志记录上下文中。这应该在您的应用程序的启动代码中的某个位置 - 尽可能早。
log4net.GlobalContext.Properties["Build"] = BuildInfo.Instance.Build;
log4net.GlobalContext.Properties["Commit"] = BuildInfo.Instance.Commit;
然后,更新日志附加器的配置以包含自定义字段。这是控制台附加程序的示例配置。重要的位是%property{BuildId}和%property{Commit}。
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<target value="Console.Error" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%-5level [%property{BuildId}] [%property{Commit}] - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>
现在,当您调用 时log.Warn("Some log mesage"),您将看到以下控制台输出:
WARN [build not set] [commit not set] - Some log mesage
从 CI 获取构建详细信息
最后,您需要从 CI 环境中获取真正的构建细节。我用一个非常简单的 PowerShell 脚本任务做到了这一点。确保任务在构建步骤之前运行!
@(
"COMMIT=$($Env:BUILD_SOURCEVERSION)",
"BUILD=$($Env:BUILD_BUILDID)"
) | Out-File BuildInfo.txt
Get-ChildItem Env: | Sort Name(提示:您可以通过在 PowerShell 任务中运行来查看所有可用的环境变量)
(另一个提示:如果您想使用 JSON 而不是文本,请查看ConvertTo-Jsoncmdlet)
现在,如果所有部分都到位,CI 服务器应该覆盖签入的构建信息文件。然后,新文件应与您的可部署工件打包在一起,并复制到您的服务器。启动时,您的应用程序应读取构建信息,然后该信息应包含在每条日志消息中。
在你的构建和部署过程之间有很多小事情要安排好,所以要为一些试验和错误做好准备。根据我的经验,CI/CD 设置往往很乏味。
- 1 回答
- 0 关注
- 90 浏览
添加回答
举报