Friday, August 23, 2013

Getting detailed TFS build log ActivityLog.xml information via APIs

The TFS Build Activity logs have lots of useful information.  Unfortunately this information is not real easy to get to.  Using the TFS 2012 APIs we can pull the log info out of the TFS SQL DB without having access to the DB.  This makes it nice because we also don't have to try to parse the activitylog.xml files.

Once you have the information you can start to track and trend how long each TFS build definition takes at each part of the build.  Once you have that piece of data you can start to determine where the best place to optimize to further reduce build times.

The sample code below looks up the LKG build based off the build Definition.  The LKG (Last Known Good) build will be set based on the last build for that build definition that passed/succeeded. It will do a simple output of the activity name and the time it took to complete.  You can take this data along with the buildDetail and create a gantt chart that shows time for each step.

The build may be old (aka not a current LKG) depending on how your system works.  But I found it is the best place to start.  It might be useful for some teams to import all build (success and fail) so you can determine if there is a trend area of where things are failing.


Usings and references
using Microsoft.TeamFoundation.Build.Client;
using Microsoft.TeamFoundation.Client;
logic
 
            Uri tfsCollectionURL = new Uri("http://TFSSERVER:8080/tfs/TFSTPC");
            string tfsProjectName = "TFSPROJECTNAME";

            string buildDefName = "BUILDDEFINITIONNAME";
            var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(tfsCollectionURL);


            IBuildServer buildServer = (IBuildServer)tfs.GetService(typeof(IBuildServer));
            var _buildDefinitions = buildServer.QueryBuildDefinitions(tfsProjectName);
            foreach (var buildDefinition in _buildDefinitions)
            {
                if (buildDefinition.LastGoodBuildUri == null)
                    continue;

                var build = buildServer.GetBuild(buildDefinition.LastGoodBuildUri);
                IBuildDetail buildDetail = buildServer.GetAllBuildDetails(build.Uri);

                var activityTrackingNodes = InformationNodeConverters.GetActivityTrackingNodes(buildDetail);

                foreach (var activity in activityTrackingNodes)
                {
                    if (activity.State != "Canceled" && (activity.Node.Children.Nodes.Count() == 0 || (activity.Node.Children.Nodes.Any(x => x.Type == "BuildMessage") && activity.DisplayName != "Sequence")))
                    {
                        if (activity.FinishTime.ToString() == "1/1/0001 12:00:00 AM")
                            continue;

                        Console.WriteLine(activity.DisplayName + ":" + (activity.FinishTime - activity.StartTime));
                    }

                }
            }

No comments: