How do I programmatically report the TFS/AzureDevOps changeset number in my logsLog4Net, how to add a custom field to my loggingI ran into a merge conflict. How can I abort the merge?How to undo 'git add' before commit?How to change the author and committer name and e-mail of multiple commits in Git?How to list branches that contain a given commit?How do I generate a random int number?How can I view a git log of just one user's commits?How can I delete all Git branches which have been merged?Does anyone have benchmarks (code & results) comparing performance of Android apps written in Xamarin C# and Java?How to see the changes in a Git commit?Using IPython notebooks under version control

Can I cause damage to electrical appliances by unplugging them when they are turned on?

What is the smallest number n> 5 so that 5 ^ n ends with "3125"?

What does "tick" mean in this sentence?

Alignment of six matrices

Sigmoid with a slope but no asymptotes?

If the only attacker is removed from combat, is a creature still counted as having attacked this turn?

How to leave product feedback on macOS?

Can you identify this lizard-like creature I observed in the UK?

Personal or impersonal in a technical resume

In One Punch Man, is King actually weak?

Would this string work as string?

SOQL query causes internal Salesforce error

Why is the Sun approximated as a black body at ~ 5800 K?

Is there a reason to prefer HFS+ over APFS for disk images in High Sierra and/or Mojave?

Sound waves in different octaves

Possible Eco thriller, man invents a device to remove rain from glass

How much do grades matter for a future academia position?

Ways of geometrical multiplication

I'm just a whisper. Who am I?

Did I make a mistake by ccing email to boss to others?

Is there a RAID 0 Equivalent for RAM?

Air travel with refrigerated insulin

Identifying "long and narrow" polygons in with PostGIS

How to make a list of partial sums using forEach



How do I programmatically report the TFS/AzureDevOps changeset number in my logs


Log4Net, how to add a custom field to my loggingI ran into a merge conflict. How can I abort the merge?How to undo 'git add' before commit?How to change the author and committer name and e-mail of multiple commits in Git?How to list branches that contain a given commit?How do I generate a random int number?How can I view a git log of just one user's commits?How can I delete all Git branches which have been merged?Does anyone have benchmarks (code & results) comparing performance of Android apps written in Xamarin C# and Java?How to see the changes in a Git commit?Using IPython notebooks under version control













0















I sometimes find myself binary searching through changesets and running tests to determine when a defect was introduced. This leaves me with a lot of very similar logs to sift through, and sometimes I have trouble remembering which diagnostic file came from which changeset run.



I would like to include the changeset number in the diagnostic files somehow. Is there any way to do this with Visual Studio/C#/AzureDevOps?










share|improve this question






















  • What logging framework are you using? I might be able to provide a framework-specific example.

    – xander
    Mar 8 at 0:26











  • log4net plus some adhoc csv files

    – ORcoder
    Mar 8 at 16:22











  • Here's a related answer that gives an example of adding custom fields to log4net output: stackoverflow.com/questions/12139486/…

    – xander
    Mar 8 at 17:25















0















I sometimes find myself binary searching through changesets and running tests to determine when a defect was introduced. This leaves me with a lot of very similar logs to sift through, and sometimes I have trouble remembering which diagnostic file came from which changeset run.



I would like to include the changeset number in the diagnostic files somehow. Is there any way to do this with Visual Studio/C#/AzureDevOps?










share|improve this question






















  • What logging framework are you using? I might be able to provide a framework-specific example.

    – xander
    Mar 8 at 0:26











  • log4net plus some adhoc csv files

    – ORcoder
    Mar 8 at 16:22











  • Here's a related answer that gives an example of adding custom fields to log4net output: stackoverflow.com/questions/12139486/…

    – xander
    Mar 8 at 17:25













0












0








0








I sometimes find myself binary searching through changesets and running tests to determine when a defect was introduced. This leaves me with a lot of very similar logs to sift through, and sometimes I have trouble remembering which diagnostic file came from which changeset run.



I would like to include the changeset number in the diagnostic files somehow. Is there any way to do this with Visual Studio/C#/AzureDevOps?










share|improve this question














I sometimes find myself binary searching through changesets and running tests to determine when a defect was introduced. This leaves me with a lot of very similar logs to sift through, and sometimes I have trouble remembering which diagnostic file came from which changeset run.



I would like to include the changeset number in the diagnostic files somehow. Is there any way to do this with Visual Studio/C#/AzureDevOps?







c# tfs version-control azure-devops system-testing






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Mar 7 at 21:52









ORcoderORcoder

1144




1144












  • What logging framework are you using? I might be able to provide a framework-specific example.

    – xander
    Mar 8 at 0:26











  • log4net plus some adhoc csv files

    – ORcoder
    Mar 8 at 16:22











  • Here's a related answer that gives an example of adding custom fields to log4net output: stackoverflow.com/questions/12139486/…

    – xander
    Mar 8 at 17:25

















  • What logging framework are you using? I might be able to provide a framework-specific example.

    – xander
    Mar 8 at 0:26











  • log4net plus some adhoc csv files

    – ORcoder
    Mar 8 at 16:22











  • Here's a related answer that gives an example of adding custom fields to log4net output: stackoverflow.com/questions/12139486/…

    – xander
    Mar 8 at 17:25
















What logging framework are you using? I might be able to provide a framework-specific example.

– xander
Mar 8 at 0:26





What logging framework are you using? I might be able to provide a framework-specific example.

– xander
Mar 8 at 0:26













log4net plus some adhoc csv files

– ORcoder
Mar 8 at 16:22





log4net plus some adhoc csv files

– ORcoder
Mar 8 at 16:22













Here's a related answer that gives an example of adding custom fields to log4net output: stackoverflow.com/questions/12139486/…

– xander
Mar 8 at 17:25





Here's a related answer that gives an example of adding custom fields to log4net output: stackoverflow.com/questions/12139486/…

– xander
Mar 8 at 17:25












1 Answer
1






active

oldest

votes


















0














Microsoft used to support a file called BuildInfo.config that was useful for this exact sort of thing, but I think support for it was dropped after Visual Studio 2015.



Basically, it was a simple XML file that was created by MSBuild. When deployed alongside the app binaries, a logging framework could read the file and include the details in log output.



There are a bunch of ways you might create similar functionality yourself. Here's what I'd do...



  1. Create an empty build info file and check it in with your source code. This file is just a reference example--use placeholder data. It can be XML, JSON, or any other format (but should probably be text-based). Set the file's build action to "Content," so it will be included in the build output.

  2. Use your logging framework's template or telemetry initialization functionality to read the build info file and include its contents in log output. The exact implementation will depend on your logging framework.

  3. Add a Powershell script task to your Azure DevOps pipeline. The script should either update or overwrite the build info file. You can get some good info from build variables. The task should run before the MSBuild compilation step.

Create and Parse a BuildInfo file



For this example, I'm going to implement my build info file as simple key/value
pairs in a text file. I chose simple text because it allows a clear example
without requiring any third-party libraries or complex parsing. In your app, you
might want to use JSON, XML, or something else more standardized.



First, create a placeholder build info file. This file will be used in your
local dev environment, and will serve as a reference for your build info schema.
I called mine BuildInfo.txt, and put it in my project's root directory.



COMMIT=commit not set
BUILD=build not set


Next, write a helper to parse the build info file. Mine's very rudimentary. It
would be wise to add some defenses against missing or malformed build info, but
I chose to omit any defensive code to keep the example focused.



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"];




Add the Build Info to your Log Output



I'm using log4net here, but any logging framework should have some similar
mechanism to customise the log output. Consult the framework's documentation for
more info.



First, add your build info to the logging context. This should go somewhere in
your app's startup code--as early as possible.



log4net.GlobalContext.Properties["Build"] = BuildInfo.Instance.Build;
log4net.GlobalContext.Properties["Commit"] = BuildInfo.Instance.Commit;


Then, update your log appender's configuration to include the custom fields.
Here's an example configuration for the the console appender. The important bits
are %propertyBuildId and %propertyCommit.



<?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 [%propertyBuildId] [%propertyCommit] - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>


Now, when you call log.Warn("Some log mesage"), you'll see the following
console output:



WARN [build not set] [commit not set] - Some log mesage


Get Build Details from CI



Finally, you need to get the real build details from your CI environment. I did
this with a very simple PowerShell script task. Make sure the task runs before
your build step!



@(
"COMMIT=$($Env:BUILD_SOURCEVERSION)",
"BUILD=$($Env:BUILD_BUILDID)"
) | Out-File BuildInfo.txt


(Tip: You can see all of the environment variables available by running Get-ChildItem Env: | Sort Name in a PowerShell task)



(Another tip: if you want to use JSON instead of text, take a look at the ConvertTo-Json cmdlet)



Now, if all of the pieces are in place, the CI server should overwrite the
checked-in build info file. The new file should then be packages with your
deployable artifacts, and copied to your server. On startup, your app should
read the build info, and then the info should be included in every log message.



There are a lot of little things to get lined up between your build and deploy
process, so be prepared for some trial and error. CI/CD setup tends to be
tedious, in my experience.






share|improve this answer

























  • I assume the you are saying that the build info file holds the changeset number and the Powershell script task overwrites it with the correct changeset. How does the powershell script know which changeset we are on?

    – ORcoder
    Mar 8 at 19:58






  • 1





    Take a look at the "build variables" link. The variables expose lots of good information--the changeset (Build.SourceVersion), the branch (Build.SourceBranchName), even the commit message (Build.SourceVersionMessage). I'll add some example code as soon as I have time to write/test it.

    – xander
    Mar 8 at 20:09










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55053393%2fhow-do-i-programmatically-report-the-tfs-azuredevops-changeset-number-in-my-logs%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














Microsoft used to support a file called BuildInfo.config that was useful for this exact sort of thing, but I think support for it was dropped after Visual Studio 2015.



Basically, it was a simple XML file that was created by MSBuild. When deployed alongside the app binaries, a logging framework could read the file and include the details in log output.



There are a bunch of ways you might create similar functionality yourself. Here's what I'd do...



  1. Create an empty build info file and check it in with your source code. This file is just a reference example--use placeholder data. It can be XML, JSON, or any other format (but should probably be text-based). Set the file's build action to "Content," so it will be included in the build output.

  2. Use your logging framework's template or telemetry initialization functionality to read the build info file and include its contents in log output. The exact implementation will depend on your logging framework.

  3. Add a Powershell script task to your Azure DevOps pipeline. The script should either update or overwrite the build info file. You can get some good info from build variables. The task should run before the MSBuild compilation step.

Create and Parse a BuildInfo file



For this example, I'm going to implement my build info file as simple key/value
pairs in a text file. I chose simple text because it allows a clear example
without requiring any third-party libraries or complex parsing. In your app, you
might want to use JSON, XML, or something else more standardized.



First, create a placeholder build info file. This file will be used in your
local dev environment, and will serve as a reference for your build info schema.
I called mine BuildInfo.txt, and put it in my project's root directory.



COMMIT=commit not set
BUILD=build not set


Next, write a helper to parse the build info file. Mine's very rudimentary. It
would be wise to add some defenses against missing or malformed build info, but
I chose to omit any defensive code to keep the example focused.



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"];




Add the Build Info to your Log Output



I'm using log4net here, but any logging framework should have some similar
mechanism to customise the log output. Consult the framework's documentation for
more info.



First, add your build info to the logging context. This should go somewhere in
your app's startup code--as early as possible.



log4net.GlobalContext.Properties["Build"] = BuildInfo.Instance.Build;
log4net.GlobalContext.Properties["Commit"] = BuildInfo.Instance.Commit;


Then, update your log appender's configuration to include the custom fields.
Here's an example configuration for the the console appender. The important bits
are %propertyBuildId and %propertyCommit.



<?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 [%propertyBuildId] [%propertyCommit] - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>


Now, when you call log.Warn("Some log mesage"), you'll see the following
console output:



WARN [build not set] [commit not set] - Some log mesage


Get Build Details from CI



Finally, you need to get the real build details from your CI environment. I did
this with a very simple PowerShell script task. Make sure the task runs before
your build step!



@(
"COMMIT=$($Env:BUILD_SOURCEVERSION)",
"BUILD=$($Env:BUILD_BUILDID)"
) | Out-File BuildInfo.txt


(Tip: You can see all of the environment variables available by running Get-ChildItem Env: | Sort Name in a PowerShell task)



(Another tip: if you want to use JSON instead of text, take a look at the ConvertTo-Json cmdlet)



Now, if all of the pieces are in place, the CI server should overwrite the
checked-in build info file. The new file should then be packages with your
deployable artifacts, and copied to your server. On startup, your app should
read the build info, and then the info should be included in every log message.



There are a lot of little things to get lined up between your build and deploy
process, so be prepared for some trial and error. CI/CD setup tends to be
tedious, in my experience.






share|improve this answer

























  • I assume the you are saying that the build info file holds the changeset number and the Powershell script task overwrites it with the correct changeset. How does the powershell script know which changeset we are on?

    – ORcoder
    Mar 8 at 19:58






  • 1





    Take a look at the "build variables" link. The variables expose lots of good information--the changeset (Build.SourceVersion), the branch (Build.SourceBranchName), even the commit message (Build.SourceVersionMessage). I'll add some example code as soon as I have time to write/test it.

    – xander
    Mar 8 at 20:09















0














Microsoft used to support a file called BuildInfo.config that was useful for this exact sort of thing, but I think support for it was dropped after Visual Studio 2015.



Basically, it was a simple XML file that was created by MSBuild. When deployed alongside the app binaries, a logging framework could read the file and include the details in log output.



There are a bunch of ways you might create similar functionality yourself. Here's what I'd do...



  1. Create an empty build info file and check it in with your source code. This file is just a reference example--use placeholder data. It can be XML, JSON, or any other format (but should probably be text-based). Set the file's build action to "Content," so it will be included in the build output.

  2. Use your logging framework's template or telemetry initialization functionality to read the build info file and include its contents in log output. The exact implementation will depend on your logging framework.

  3. Add a Powershell script task to your Azure DevOps pipeline. The script should either update or overwrite the build info file. You can get some good info from build variables. The task should run before the MSBuild compilation step.

Create and Parse a BuildInfo file



For this example, I'm going to implement my build info file as simple key/value
pairs in a text file. I chose simple text because it allows a clear example
without requiring any third-party libraries or complex parsing. In your app, you
might want to use JSON, XML, or something else more standardized.



First, create a placeholder build info file. This file will be used in your
local dev environment, and will serve as a reference for your build info schema.
I called mine BuildInfo.txt, and put it in my project's root directory.



COMMIT=commit not set
BUILD=build not set


Next, write a helper to parse the build info file. Mine's very rudimentary. It
would be wise to add some defenses against missing or malformed build info, but
I chose to omit any defensive code to keep the example focused.



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"];




Add the Build Info to your Log Output



I'm using log4net here, but any logging framework should have some similar
mechanism to customise the log output. Consult the framework's documentation for
more info.



First, add your build info to the logging context. This should go somewhere in
your app's startup code--as early as possible.



log4net.GlobalContext.Properties["Build"] = BuildInfo.Instance.Build;
log4net.GlobalContext.Properties["Commit"] = BuildInfo.Instance.Commit;


Then, update your log appender's configuration to include the custom fields.
Here's an example configuration for the the console appender. The important bits
are %propertyBuildId and %propertyCommit.



<?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 [%propertyBuildId] [%propertyCommit] - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>


Now, when you call log.Warn("Some log mesage"), you'll see the following
console output:



WARN [build not set] [commit not set] - Some log mesage


Get Build Details from CI



Finally, you need to get the real build details from your CI environment. I did
this with a very simple PowerShell script task. Make sure the task runs before
your build step!



@(
"COMMIT=$($Env:BUILD_SOURCEVERSION)",
"BUILD=$($Env:BUILD_BUILDID)"
) | Out-File BuildInfo.txt


(Tip: You can see all of the environment variables available by running Get-ChildItem Env: | Sort Name in a PowerShell task)



(Another tip: if you want to use JSON instead of text, take a look at the ConvertTo-Json cmdlet)



Now, if all of the pieces are in place, the CI server should overwrite the
checked-in build info file. The new file should then be packages with your
deployable artifacts, and copied to your server. On startup, your app should
read the build info, and then the info should be included in every log message.



There are a lot of little things to get lined up between your build and deploy
process, so be prepared for some trial and error. CI/CD setup tends to be
tedious, in my experience.






share|improve this answer

























  • I assume the you are saying that the build info file holds the changeset number and the Powershell script task overwrites it with the correct changeset. How does the powershell script know which changeset we are on?

    – ORcoder
    Mar 8 at 19:58






  • 1





    Take a look at the "build variables" link. The variables expose lots of good information--the changeset (Build.SourceVersion), the branch (Build.SourceBranchName), even the commit message (Build.SourceVersionMessage). I'll add some example code as soon as I have time to write/test it.

    – xander
    Mar 8 at 20:09













0












0








0







Microsoft used to support a file called BuildInfo.config that was useful for this exact sort of thing, but I think support for it was dropped after Visual Studio 2015.



Basically, it was a simple XML file that was created by MSBuild. When deployed alongside the app binaries, a logging framework could read the file and include the details in log output.



There are a bunch of ways you might create similar functionality yourself. Here's what I'd do...



  1. Create an empty build info file and check it in with your source code. This file is just a reference example--use placeholder data. It can be XML, JSON, or any other format (but should probably be text-based). Set the file's build action to "Content," so it will be included in the build output.

  2. Use your logging framework's template or telemetry initialization functionality to read the build info file and include its contents in log output. The exact implementation will depend on your logging framework.

  3. Add a Powershell script task to your Azure DevOps pipeline. The script should either update or overwrite the build info file. You can get some good info from build variables. The task should run before the MSBuild compilation step.

Create and Parse a BuildInfo file



For this example, I'm going to implement my build info file as simple key/value
pairs in a text file. I chose simple text because it allows a clear example
without requiring any third-party libraries or complex parsing. In your app, you
might want to use JSON, XML, or something else more standardized.



First, create a placeholder build info file. This file will be used in your
local dev environment, and will serve as a reference for your build info schema.
I called mine BuildInfo.txt, and put it in my project's root directory.



COMMIT=commit not set
BUILD=build not set


Next, write a helper to parse the build info file. Mine's very rudimentary. It
would be wise to add some defenses against missing or malformed build info, but
I chose to omit any defensive code to keep the example focused.



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"];




Add the Build Info to your Log Output



I'm using log4net here, but any logging framework should have some similar
mechanism to customise the log output. Consult the framework's documentation for
more info.



First, add your build info to the logging context. This should go somewhere in
your app's startup code--as early as possible.



log4net.GlobalContext.Properties["Build"] = BuildInfo.Instance.Build;
log4net.GlobalContext.Properties["Commit"] = BuildInfo.Instance.Commit;


Then, update your log appender's configuration to include the custom fields.
Here's an example configuration for the the console appender. The important bits
are %propertyBuildId and %propertyCommit.



<?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 [%propertyBuildId] [%propertyCommit] - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>


Now, when you call log.Warn("Some log mesage"), you'll see the following
console output:



WARN [build not set] [commit not set] - Some log mesage


Get Build Details from CI



Finally, you need to get the real build details from your CI environment. I did
this with a very simple PowerShell script task. Make sure the task runs before
your build step!



@(
"COMMIT=$($Env:BUILD_SOURCEVERSION)",
"BUILD=$($Env:BUILD_BUILDID)"
) | Out-File BuildInfo.txt


(Tip: You can see all of the environment variables available by running Get-ChildItem Env: | Sort Name in a PowerShell task)



(Another tip: if you want to use JSON instead of text, take a look at the ConvertTo-Json cmdlet)



Now, if all of the pieces are in place, the CI server should overwrite the
checked-in build info file. The new file should then be packages with your
deployable artifacts, and copied to your server. On startup, your app should
read the build info, and then the info should be included in every log message.



There are a lot of little things to get lined up between your build and deploy
process, so be prepared for some trial and error. CI/CD setup tends to be
tedious, in my experience.






share|improve this answer















Microsoft used to support a file called BuildInfo.config that was useful for this exact sort of thing, but I think support for it was dropped after Visual Studio 2015.



Basically, it was a simple XML file that was created by MSBuild. When deployed alongside the app binaries, a logging framework could read the file and include the details in log output.



There are a bunch of ways you might create similar functionality yourself. Here's what I'd do...



  1. Create an empty build info file and check it in with your source code. This file is just a reference example--use placeholder data. It can be XML, JSON, or any other format (but should probably be text-based). Set the file's build action to "Content," so it will be included in the build output.

  2. Use your logging framework's template or telemetry initialization functionality to read the build info file and include its contents in log output. The exact implementation will depend on your logging framework.

  3. Add a Powershell script task to your Azure DevOps pipeline. The script should either update or overwrite the build info file. You can get some good info from build variables. The task should run before the MSBuild compilation step.

Create and Parse a BuildInfo file



For this example, I'm going to implement my build info file as simple key/value
pairs in a text file. I chose simple text because it allows a clear example
without requiring any third-party libraries or complex parsing. In your app, you
might want to use JSON, XML, or something else more standardized.



First, create a placeholder build info file. This file will be used in your
local dev environment, and will serve as a reference for your build info schema.
I called mine BuildInfo.txt, and put it in my project's root directory.



COMMIT=commit not set
BUILD=build not set


Next, write a helper to parse the build info file. Mine's very rudimentary. It
would be wise to add some defenses against missing or malformed build info, but
I chose to omit any defensive code to keep the example focused.



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"];




Add the Build Info to your Log Output



I'm using log4net here, but any logging framework should have some similar
mechanism to customise the log output. Consult the framework's documentation for
more info.



First, add your build info to the logging context. This should go somewhere in
your app's startup code--as early as possible.



log4net.GlobalContext.Properties["Build"] = BuildInfo.Instance.Build;
log4net.GlobalContext.Properties["Commit"] = BuildInfo.Instance.Commit;


Then, update your log appender's configuration to include the custom fields.
Here's an example configuration for the the console appender. The important bits
are %propertyBuildId and %propertyCommit.



<?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 [%propertyBuildId] [%propertyCommit] - %message%newline" />
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>


Now, when you call log.Warn("Some log mesage"), you'll see the following
console output:



WARN [build not set] [commit not set] - Some log mesage


Get Build Details from CI



Finally, you need to get the real build details from your CI environment. I did
this with a very simple PowerShell script task. Make sure the task runs before
your build step!



@(
"COMMIT=$($Env:BUILD_SOURCEVERSION)",
"BUILD=$($Env:BUILD_BUILDID)"
) | Out-File BuildInfo.txt


(Tip: You can see all of the environment variables available by running Get-ChildItem Env: | Sort Name in a PowerShell task)



(Another tip: if you want to use JSON instead of text, take a look at the ConvertTo-Json cmdlet)



Now, if all of the pieces are in place, the CI server should overwrite the
checked-in build info file. The new file should then be packages with your
deployable artifacts, and copied to your server. On startup, your app should
read the build info, and then the info should be included in every log message.



There are a lot of little things to get lined up between your build and deploy
process, so be prepared for some trial and error. CI/CD setup tends to be
tedious, in my experience.







share|improve this answer














share|improve this answer



share|improve this answer








edited Mar 10 at 0:41

























answered Mar 8 at 0:23









xanderxander

632516




632516












  • I assume the you are saying that the build info file holds the changeset number and the Powershell script task overwrites it with the correct changeset. How does the powershell script know which changeset we are on?

    – ORcoder
    Mar 8 at 19:58






  • 1





    Take a look at the "build variables" link. The variables expose lots of good information--the changeset (Build.SourceVersion), the branch (Build.SourceBranchName), even the commit message (Build.SourceVersionMessage). I'll add some example code as soon as I have time to write/test it.

    – xander
    Mar 8 at 20:09

















  • I assume the you are saying that the build info file holds the changeset number and the Powershell script task overwrites it with the correct changeset. How does the powershell script know which changeset we are on?

    – ORcoder
    Mar 8 at 19:58






  • 1





    Take a look at the "build variables" link. The variables expose lots of good information--the changeset (Build.SourceVersion), the branch (Build.SourceBranchName), even the commit message (Build.SourceVersionMessage). I'll add some example code as soon as I have time to write/test it.

    – xander
    Mar 8 at 20:09
















I assume the you are saying that the build info file holds the changeset number and the Powershell script task overwrites it with the correct changeset. How does the powershell script know which changeset we are on?

– ORcoder
Mar 8 at 19:58





I assume the you are saying that the build info file holds the changeset number and the Powershell script task overwrites it with the correct changeset. How does the powershell script know which changeset we are on?

– ORcoder
Mar 8 at 19:58




1




1





Take a look at the "build variables" link. The variables expose lots of good information--the changeset (Build.SourceVersion), the branch (Build.SourceBranchName), even the commit message (Build.SourceVersionMessage). I'll add some example code as soon as I have time to write/test it.

– xander
Mar 8 at 20:09





Take a look at the "build variables" link. The variables expose lots of good information--the changeset (Build.SourceVersion), the branch (Build.SourceBranchName), even the commit message (Build.SourceVersionMessage). I'll add some example code as soon as I have time to write/test it.

– xander
Mar 8 at 20:09



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55053393%2fhow-do-i-programmatically-report-the-tfs-azuredevops-changeset-number-in-my-logs%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Identity Server 4 is not redirecting to Angular app after login2019 Community Moderator ElectionIdentity Server 4 and dockerIdentityserver implicit flow unauthorized_clientIdentityServer Hybrid Flow - Access Token is null after user successful loginIdentity Server to MVC client : Page Redirect After loginLogin with Steam OpenId(oidc-client-js)Identity Server 4+.NET Core 2.0 + IdentityIdentityServer4 post-login redirect not working in Edge browserCall to IdentityServer4 generates System.NullReferenceException: Object reference not set to an instance of an objectIdentityServer4 without HTTPS not workingHow to get Authorization code from identity server without login form

2005 Ahvaz unrest Contents Background Causes Casualties Aftermath See also References Navigation menue"At Least 10 Are Killed by Bombs in Iran""Iran"Archived"Arab-Iranians in Iran to make April 15 'Day of Fury'"State of Mind, State of Order: Reactions to Ethnic Unrest in the Islamic Republic of Iran.10.1111/j.1754-9469.2008.00028.x"Iran hangs Arab separatists"Iran Overview from ArchivedConstitution of the Islamic Republic of Iran"Tehran puzzled by forged 'riots' letter""Iran and its minorities: Down in the second class""Iran: Handling Of Ahvaz Unrest Could End With Televised Confessions""Bombings Rock Iran Ahead of Election""Five die in Iran ethnic clashes""Iran: Need for restraint as anniversary of unrest in Khuzestan approaches"Archived"Iranian Sunni protesters killed in clashes with security forces"Archived

Can't initialize raids on a new ASUS Prime B360M-A motherboard2019 Community Moderator ElectionSimilar to RAID config yet more like mirroring solution?Can't get motherboard serial numberWhy does the BIOS entry point start with a WBINVD instruction?UEFI performance Asus Maximus V Extreme