I\'m trying to build a report to show the relative efficiency of my various build agents and having trouble getting the info I need out of the tool.
What I\'d like t
My initial intention was to point you to TFS OLAP Cube & describe how you could retrieve what you were after. Then I realized that the cube does not provide with the info which Agent built what Build.
Then I thought it would be simple to write a small TFS-console app that print the infos you 're after:
using System;
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
namespace BuildDetails
{
class Program
{
static void Main()
{
TfsTeamProjectCollection teamProjectCollection = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("http://TFS:8080/tfs/CoLLeCtIoNNaMe"));
var buildService = (IBuildServer)teamProjectCollection.GetService(typeof(IBuildServer));
IBuildDefinition buildDefinition = buildService.GetBuildDefinition("TeamProjectName", "BuildDefinitionName");
IBuildDetail[] buildDetails = buildService.QueryBuilds(buildDefinition);
foreach (var buildDetail in buildDetails)
{
Console.Write(buildDetail.BuildNumber+"\t");
Console.Write(buildDefinition.Name+"\t");
Console.Write(buildDetail.BuildAgent.Name+"\t");
Console.Write(buildDetail.Status+"\t");
Console.Write(buildDetail.StartTime+"\t");
Console.WriteLine((buildDetail.FinishTime - buildDetail.StartTime).Minutes);
}
}
}
}
This won't compile, since
Eventually I dove into the IBuildInformationNode[]
and got the build agent as follows:
IBuildInformation buildInformation = buildDetail.Information;
IBuildInformationNode[] buildInformationNodes = buildInformation.Nodes;
string agentName;
try
{
agentName = buildInformationNodes[0].Children.Nodes[3].Fields["ReservedAgentName"];
}
catch
{
agentName = "Couldn't determine BuildAgent";
}
Console.Write(agentName + "\t");
The try-catch is necessary, so you can deal with builds that failed/stopped before agent-selection.
If you use this latter part as a substitute to the failing Console.Write(buildDetail.BuildAgent.Name+"\t");
you should end up with a console app, whose output can be piped into a *.CSV file & then imported to Excel.
The following code should help in getting the Build Agent Name for the given build detail.
private string GetBuildAgentName(IBuildDetail build)
{
var buildInformationNodes = build.Information.GetNodesByType("AgentScopeActivityTracking", true);
if (buildInformationNodes != null)
{
var node = buildInformationNodes.Find(s => s.Fields.ContainsKey(InformationFields.ReservedAgentName));
return node != null ? node.Fields[InformationFields.ReservedAgentName] : string.Empty;
}
return string.Empty;
}
Make sure that you have refresh the build information in the build details object.You can do so by the either calling the following code on your build Details object before getting the build agents
string[] refreshAllDetails = {"*"};
build.Refresh(refreshAllDetails, QueryOptions.Agents);
Hope it helps :)
The build agent information isn't always in the same place.
I found it for a build I was looking at in buildInformationNodes[1].Children.Nodes[2].Fields["ReservedAgentName"]. The following seems to work for me (so far).
private static string GetAgentName(IBuildDetail buildDetail)
{
string agentName = "Unknown";
bool fAgentFound = false;
try
{
foreach (IBuildInformationNode node in buildDetail.Information.Nodes)
{
foreach (IBuildInformationNode childNode in node.Children.Nodes)
{
if (childNode.Fields.ContainsKey("ReservedAgentName"))
{
agentName = childNode.Fields["ReservedAgentName"];
break;
}
}
if (fAgentFound) break;
}
}
catch (Exception ex)
{
// change to your own routine as needed
DumpException(ex);
}
return agentName;
}