This is an automated email from the ASF dual-hosted git repository.

dpavlov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite-teamcity-bot.git


The following commit(s) were added to refs/heads/master by this push:
     new 460e5f8  IGNITE-10030 statistics done in prod: Background upload of 
changes, problems, and statistics - Fixes #49.
460e5f8 is described below

commit 460e5f89add920612c884852ac6a24d821d749b3
Author: Dmitriy Pavlov <[email protected]>
AuthorDate: Sat Oct 27 20:14:58 2018 +0300

    IGNITE-10030 statistics done in prod: Background upload of changes, 
problems, and statistics - Fixes #49.
    
    Signed-off-by: Dmitriy Pavlov <[email protected]>
---
 .../main/java/org/apache/ignite/ci/ITeamcity.java  |  23 +--
 .../apache/ignite/ci/IgnitePersistentTeamcity.java |  70 +++------
 .../apache/ignite/ci/IgniteTeamcityConnection.java |  49 +++----
 .../apache/ignite/ci/analysis/FullChainRunCtx.java |  12 --
 .../apache/ignite/ci/analysis/MultBuildRunCtx.java |  79 ++++------
 .../ignite/ci/analysis/SingleBuildRunCtx.java      |  37 ++---
 .../java/org/apache/ignite/ci/db/DbMigrations.java |  27 ++--
 .../ci/tcbot/builds/CompareBuildsService.java      |   4 +-
 .../ignite/ci/tcbot/chain/BuildChainProcessor.java |  12 +-
 .../ignite/ci/tcmodel/conf/bt/Parameters.java      |   5 +
 .../apache/ignite/ci/tcmodel/conf/bt/Property.java |   4 +
 .../tcmodel/result/problems/ProblemOccurrence.java |   8 +
 .../ignite/ci/tcmodel/result/stat/Statistics.java  |   8 +-
 .../ci/teamcity/ignited/TeamcityIgnitedImpl.java   |   4 +-
 .../ignited/fatbuild/FatBuildCompacted.java        |  57 ++++++-
 .../ci/teamcity/ignited/fatbuild/FatBuildDao.java  |  25 ++--
 .../ignited/fatbuild/ProactiveFatBuildSync.java    |  33 +++--
 .../ignited/fatbuild/ProblemCompacted.java         | 163 +++++++++++++++++++++
 .../ignited/fatbuild/StatisticsCompacted.java      | 101 +++++++++++++
 .../teamcity/ignited/fatbuild/TestCompacted.java   |   2 +-
 .../ignite/ci/teamcity/pure/ITeamcityConn.java     |   8 +-
 .../ignited/IgnitedTcInMemoryIntegrationTest.java  |  19 ++-
 .../src/test/resources/problemList.xml             |  20 +++
 23 files changed, 534 insertions(+), 236 deletions(-)

diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITeamcity.java 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITeamcity.java
index 12446b9..dac1546 100644
--- a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITeamcity.java
+++ b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/ITeamcity.java
@@ -59,16 +59,6 @@ public interface ITeamcity extends ITeamcityConn {
 
     CompletableFuture<List<BuildType>> getProjectSuites(String projectId);
 
-
-    /**
-     * @param projectId Suite ID (string without spaces).
-     * @param branch Branch in TC identification.
-     * @return List of builds in historical order, recent builds coming last.
-     */
-    default List<BuildRef> getFinishedBuilds(String projectId, String branch) {
-        return getFinishedBuilds(projectId, branch, null, null, null);
-    };
-
     /**
      * @param projectId suite ID (string without spaces).
      * @param branch Branch name in TC identification.
@@ -77,6 +67,7 @@ public interface ITeamcity extends ITeamcityConn {
      * @param sinceBuildId Some build ID in the past to to use as minimal 
build to export.
      * @return list of builds in historical order, recent builds coming last.
      */
+    @Deprecated
     List<BuildRef> getFinishedBuilds(String projectId, String branch, Date 
sinceDate, Date untilDate, Integer sinceBuildId);
 
     /**
@@ -105,10 +96,6 @@ public interface ITeamcity extends ITeamcityConn {
 
     /**   */
     @Deprecated
-    CompletableFuture<List<BuildRef>> getRunningBuilds(@Nullable String 
branch);
-
-    /**   */
-    @Deprecated
     CompletableFuture<List<BuildRef>> getQueuedBuilds(@Nullable String branch);
 
     /**
@@ -118,6 +105,7 @@ public interface ITeamcity extends ITeamcityConn {
      * @param untilDate Until date.
      * @return List of build numbers in historical order in date interval, 
recent builds coming last.
      */
+    @Deprecated
     default int[] getBuildNumbersFromHistory(String projectId, String 
branchNameForHist, Date sinceDate, Date untilDate) {
         return getFinishedBuilds(projectId, branchNameForHist, sinceDate, 
untilDate, null).stream().mapToInt(BuildRef::getId).toArray();
     }
@@ -137,10 +125,7 @@ public interface ITeamcity extends ITeamcityConn {
         return "app/rest/latest/builds/id:" + Integer.toString(id);
     }
 
-    /**
-     * @param build
-     * @return
-     */
+    @Deprecated
     ProblemOccurrences getProblems(BuildRef build);
 
     @Deprecated
@@ -149,8 +134,6 @@ public interface ITeamcity extends ITeamcityConn {
     @Deprecated
     TestOccurrences getFailedTests(String href, int count, String 
normalizedBranch);
 
-    Statistics getBuildStatistics(String href);
-
     @Deprecated
     CompletableFuture<TestOccurrenceFull> getTestFull(String href);
 
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
index 3487566..043154c 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgnitePersistentTeamcity.java
@@ -106,7 +106,6 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
     @Deprecated
     private static final String TEST_FULL = "testFull";
     private static final String BUILD_PROBLEMS = "buildProblems";
-    private static final String BUILD_STATISTICS = "buildStatistics";
     private static final String BUILD_HIST_FINISHED = "buildHistFinished";
     private static final String BUILD_HIST_FINISHED_OR_FAILED = 
"buildHistFinishedOrFailed";
     public static final String BOT_DETECTED_ISSUES = "botDetectedIssues";
@@ -142,12 +141,6 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
     /** cached loads of queued builds for branch. */
     private ConcurrentMap<String, CompletableFuture<List<BuildRef>>> 
queuedBuildsFuts = new ConcurrentHashMap<>();
 
-    /** cached running builds for branch. */
-    private ConcurrentMap<String, Expirable<List<BuildRef>>> runningBuilds = 
new ConcurrentHashMap<>();
-
-    /** cached loads of running builds for branch. */
-    private ConcurrentMap<String, CompletableFuture<List<BuildRef>>> 
runningBuildsFuts = new ConcurrentHashMap<>();
-
     /**   */
     private ConcurrentMap<SuiteInBranch, Long> lastQueuedHistory = new 
ConcurrentHashMap<>();
 
@@ -171,10 +164,8 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
                 buildsFailureRunStatCache(), testRunStatCache(),
                 testFullCache(),
                 buildProblemsCache(),
-                buildStatisticsCache(),
                 buildHistCache(),
-                buildHistIncFailedCache(),
-                testRefsCache());
+                buildHistIncFailedCache());
     }
 
     @Override
@@ -255,12 +246,6 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
         return getOrCreateCacheV2(ignCacheNme(BUILD_PROBLEMS));
     }
 
-    /**
-     * @return Build {@link Statistics} instances cache, 32 parts.
-     */
-    private IgniteCache<String, Statistics> buildStatisticsCache() {
-        return getOrCreateCacheV2(ignCacheNme(BUILD_STATISTICS));
-    }
 
 
     /**
@@ -667,20 +652,6 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
     }
 
 
-    /** {@inheritDoc} */
-    @Override public CompletableFuture<List<BuildRef>> getRunningBuilds(String 
branch) {
-        int defaultSecs = 60;
-        int secondsUseCached = getTriggerRelCacheValidSecs(defaultSecs);
-
-        return loadAsyncIfAbsentOrExpired(
-            runningBuilds,
-            Strings.nullToEmpty(branch),
-            runningBuildsFuts,
-            teamcity::getRunningBuilds,
-            secondsUseCached,
-            secondsUseCached == defaultSecs);
-    }
-
     public static int getTriggerRelCacheValidSecs(int defaultSecs) {
         long msSinceTrigger = System.currentTimeMillis() - lastTriggerMs;
         long secondsSinceTrigger = 
TimeUnit.MILLISECONDS.toSeconds(msSinceTrigger);
@@ -873,26 +844,6 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
 
     /** {@inheritDoc} */
     @AutoProfiling
-    @Override public Statistics getBuildStatistics(String href) {
-        return loadIfAbsent(buildStatisticsCache(),
-            href,
-            href1 -> {
-                try {
-                    return teamcity.getBuildStatistics(href1);
-                }
-                catch (Exception e) {
-                    if (Throwables.getRootCause(e) instanceof 
FileNotFoundException) {
-                        e.printStackTrace();
-                        return new Statistics();// save null result, because 
persistence may refer to some  unexistent build on TC
-                    }
-                    else
-                        throw e;
-                }
-            });
-    }
-
-    /** {@inheritDoc} */
-    @AutoProfiling
     @Override public CompletableFuture<TestOccurrenceFull> getTestFull(String 
href) {
         return CacheUpdateUtil.loadAsyncIfAbsent(
             testFullCache(),
@@ -1142,6 +1093,9 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
     /** {@inheritDoc} */
     @AutoProfiling
     @Override public void calculateBuildStatistic(SingleBuildRunCtx ctx) {
+        if (ctx.buildId() == null)
+            return;
+
         if (calculatedStatistic().containsKey(ctx.buildId()))
             return;
 
@@ -1191,12 +1145,22 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
 
     /** {@inheritDoc} */
     @AutoProfiling
-    @Override public Build triggerBuild(String buildTypeId, String branchName, 
boolean cleanRebuild, boolean queueAtTop) {
+    @Override public Build triggerBuild(String buildTypeId, @NotNull String 
branchName, boolean cleanRebuild, boolean queueAtTop) {
         lastTriggerMs = System.currentTimeMillis();
 
         return teamcity.triggerBuild(buildTypeId, branchName, cleanRebuild, 
queueAtTop);
     }
 
+    @Override
+    public ProblemOccurrences getProblems(int buildId) {
+        return teamcity.getProblems(buildId);
+    }
+
+    @Override
+    public Statistics getStatistics(int buildId) {
+        return teamcity.getStatistics(buildId);
+    }
+
     /** {@inheritDoc} */
     @Override public void setAuthToken(String tok) {
         teamcity.setAuthToken(tok);
@@ -1238,8 +1202,8 @@ public class IgnitePersistentTeamcity implements 
IAnalyticsEnabledTeamcity, ITea
     }
 
     /** {@inheritDoc} */
-    @Override public List<BuildRef> getBuildRefs(String fullUrl, 
AtomicReference<String> nextPage) {
-        return teamcity.getBuildRefs(fullUrl, nextPage);
+    @Override public List<BuildRef> getBuildRefsPage(String fullUrl, 
AtomicReference<String> nextPage) {
+        return teamcity.getBuildRefsPage(fullUrl, nextPage);
     }
 
     /** {@inheritDoc} */
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java
index 12810df..9435540 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/IgniteTeamcityConnection.java
@@ -272,10 +272,10 @@ public class IgniteTeamcityConnection implements 
ITeamcity {
     /** {@inheritDoc} */
     @AutoProfiling
     @Override public Build triggerBuild(
-        String buildTypeId,
-        @Nonnull String branchName,
-        boolean cleanRebuild,
-        boolean queueAtTop
+            String buildTypeId,
+            @NotNull @Nonnull String branchName,
+            boolean cleanRebuild,
+            boolean queueAtTop
     ) {
         String triggeringOptions =
             " <triggeringOptions" +
@@ -317,6 +317,20 @@ public class IgniteTeamcityConnection implements ITeamcity 
{
         }
     }
 
+    @Override
+    @AutoProfiling
+    public ProblemOccurrences getProblems(int buildId) {
+        return getJaxbUsingHref("app/rest/latest/problemOccurrences" +
+                "?locator=build:(id:" + buildId + ")" +
+                
"&fields=problemOccurrence(id,type,identity,href,details,build(id))", 
ProblemOccurrences.class);
+    }
+
+    @Override
+    @AutoProfiling
+    public Statistics getStatistics(int buildId) {
+        return getJaxbUsingHref("app/rest/latest/builds/id:" + buildId + 
"/statistics", Statistics.class);
+    }
+
     private CompletableFuture<List<File>> unzip(CompletableFuture<File> 
zipFileFut) {
         return zipFileFut.thenApplyAsync(ZipUtil::unZipToSameFolder, executor);
     }
@@ -451,12 +465,6 @@ public class IgniteTeamcityConnection implements ITeamcity 
{
 
     /** {@inheritDoc} */
     @AutoProfiling
-    @Override public Statistics getBuildStatistics(String href) {
-        return getJaxbUsingHref(href, Statistics.class);
-    }
-
-    /** {@inheritDoc} */
-    @AutoProfiling
     @Override public CompletableFuture<TestOccurrenceFull> getTestFull(String 
href) {
         return supplyAsync(() -> getJaxbUsingHref(href, 
TestOccurrenceFull.class), executor);
     }
@@ -512,13 +520,6 @@ public class IgniteTeamcityConnection implements ITeamcity 
{
 
     /** {@inheritDoc} */
     @AutoProfiling
-    @Override public List<BuildRef> getFinishedBuilds(String projectId, String 
branch) {
-
-        return getFinishedBuilds(projectId, branch, null, null, null);
-    }
-
-    /** {@inheritDoc} */
-    @AutoProfiling
     @Override public List<BuildRef> getFinishedBuilds(String projectId,
                                             String branch,
                                             Date sinceDate,
@@ -549,16 +550,11 @@ public class IgniteTeamcityConnection implements 
ITeamcity {
 
     /** {@inheritDoc} */
     @Override
-    @AutoProfiling public CompletableFuture<List<BuildRef>> 
getRunningBuilds(@Nullable String branch) {
-        return supplyAsync(() -> getBuildsInState(null, branch, 
BuildRef.STATE_RUNNING), executor);
-    }
-
-    /** {@inheritDoc} */
-    @Override
     @AutoProfiling public CompletableFuture<List<BuildRef>> 
getQueuedBuilds(@Nullable String branch) {
         return supplyAsync(() -> getBuildsInState(null, branch, 
BuildRef.STATE_QUEUED), executor);
     }
 
+    @Deprecated
     private List<BuildRef> getBuildsInState(
             @Nullable final String projectId,
             @Nullable final String branch,
@@ -577,6 +573,7 @@ public class IgniteTeamcityConnection implements ITeamcity {
 
     @SuppressWarnings("WeakerAccess")
     @AutoProfiling
+    @Deprecated
     protected List<BuildRef> getBuildsInState(
             @Nullable final String projectId,
             @Nullable final String branch,
@@ -655,7 +652,7 @@ public class IgniteTeamcityConnection implements ITeamcity {
 
     /** {@inheritDoc} */
     @AutoProfiling
-    @Override public List<BuildRef> getBuildRefs(String fullUrl, 
AtomicReference<String> outNextPage) {
+    @Override public List<BuildRef> getBuildRefsPage(String fullUrl, 
AtomicReference<String> outNextPage) {
         String relPath = "app/rest/latest/builds?locator=defaultFilter:false";
         String relPathSelected = Strings.isNullOrEmpty(fullUrl) ? relPath : 
fullUrl;
         String url = host + (relPathSelected.startsWith("/") ? 
relPathSelected.substring(1) : relPathSelected);
@@ -678,10 +675,12 @@ public class IgniteTeamcityConnection implements 
ITeamcity {
      * @param buildId Build id.
      * @param testDtls request test details string
      */
-    @NotNull public String testsStartHref(int buildId, boolean testDtls) {
+    @NotNull
+    private String testsStartHref(int buildId, boolean testDtls) {
         String fieldList = "id,name," +
             (testDtls ? "details," : "") +
             
"status,duration,muted,currentlyMuted,currentlyInvestigated,ignored,test(id),build(id)";
+
         return "app/rest/latest/testOccurrences?locator=build:(id:" +
             buildId + ")" +
             "&fields=testOccurrence(" + fieldList + ")";
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/FullChainRunCtx.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/FullChainRunCtx.java
index 0e04ccb..0d01506 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/FullChainRunCtx.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/FullChainRunCtx.java
@@ -40,18 +40,6 @@ public class FullChainRunCtx {
         fakeStub = chainResults.isFakeStub();
     }
 
-    @Deprecated
-    public int buildProblems() {
-        return 
(int)buildCfgsResults.stream().filter(MultBuildRunCtx::hasNontestBuildProblem).count();
-    }
-
-    public int timeoutsOomeCrashBuildProblems() {
-        return (int)buildCfgsResults.stream().filter(context ->
-            context.hasJvmCrashProblem()
-                || context.hasTimeoutProblem()
-                || context.hasOomeProblem()).count();
-    }
-
     public List<MultBuildRunCtx> suites() {
         return buildCfgsResults;
     }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
index 0411fe2..c79ab3b 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/MultBuildRunCtx.java
@@ -17,36 +17,24 @@
 
 package org.apache.ignite.ci.analysis;
 
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
+import java.util.*;
 import java.util.concurrent.ConcurrentSkipListMap;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.Future;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import javax.annotation.Nonnull;
-import org.apache.ignite.ci.tcmodel.conf.BuildType;
+
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
-import org.apache.ignite.ci.tcmodel.result.Build;
-import org.apache.ignite.ci.tcmodel.result.TestOccurrencesRef;
 import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
 import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
-import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrence;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrenceFull;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProblemCompacted;
 import org.apache.ignite.ci.util.CollectionUtil;
-import org.apache.ignite.ci.util.FutureUtil;
-import org.apache.ignite.ci.util.TimeUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
-import static java.util.stream.Stream.concat;
-
 /**
  * Run configuration execution results loaded from different API URLs.
  * Includes tests and problem occurrences; if logs processing is done also 
contains last started test
@@ -55,6 +43,8 @@ public class MultBuildRunCtx implements ISuiteResults {
     /** First build info. */
     @Nonnull private final BuildRef firstBuildInfo;
 
+    private IStringCompactor compactor;
+
     /** Builds: Single execution. */
     private List<SingleBuildRunCtx> builds = new CopyOnWriteArrayList<>();
 
@@ -62,11 +52,6 @@ public class MultBuildRunCtx implements ISuiteResults {
     @Deprecated
     private final Map<String, MultTestFailureOccurrences> tests = new 
ConcurrentSkipListMap<>();
 
-    /**
-     * Statistics for last build.
-     */
-    @Nullable private Statistics stat;
-
     public void addBuild(SingleBuildRunCtx ctx) {
         builds.add(ctx);
     }
@@ -77,8 +62,9 @@ public class MultBuildRunCtx implements ISuiteResults {
     /** Currently scheduled builds */
     private Integer queuedBuildCount;
 
-    public MultBuildRunCtx(@Nonnull final BuildRef buildInfo) {
+    public MultBuildRunCtx(@Nonnull final BuildRef buildInfo, IStringCompactor 
compactor) {
         this.firstBuildInfo = buildInfo;
+        this.compactor = compactor;
     }
 
     public Stream<String> getCriticalFailLastStartedTest() {
@@ -106,23 +92,13 @@ public class MultBuildRunCtx implements ISuiteResults {
         return firstBuildInfo.buildTypeId;
     }
 
-
-    @Deprecated
-    //currently used only in old metrics
-    public boolean hasNontestBuildProblem() {
-        return allProblemsInAllBuilds().anyMatch(problem ->
-            !problem.isFailedTests()
-                && !problem.isSnapshotDepProblem()
-                && 
!ProblemOccurrence.BUILD_FAILURE_ON_MESSAGE.equals(problem.type));
-        //todo what to do with BuildFailureOnMessage, now it is ignored
-    }
-
     public boolean hasAnyBuildProblemExceptTestOrSnapshot() {
         return allProblemsInAllBuilds()
-            .anyMatch(p -> !p.isFailedTests() && !p.isSnapshotDepProblem());
+            .anyMatch(p -> !p.isFailedTests(compactor) && 
!p.isSnapshotDepProblem(compactor));
     }
 
-    @NotNull public Stream<ProblemOccurrence> allProblemsInAllBuilds() {
+    @NotNull
+    private Stream<ProblemCompacted> allProblemsInAllBuilds() {
         return buildsStream().flatMap(SingleBuildRunCtx::getProblemsStream);
     }
 
@@ -184,21 +160,21 @@ public class MultBuildRunCtx implements ISuiteResults {
         addKnownProblemCnt(res, "Exit Code", getExitCodeProblemsCount());
 
         {
-            Stream<ProblemOccurrence> stream =
+            Stream<ProblemCompacted> stream =
                 allProblemsInAllBuilds().filter(p ->
-                    !p.isFailedTests()
-                        && !p.isSnapshotDepProblem()
-                        && !p.isExecutionTimeout()
-                        && !p.isJvmCrash()
-                        && !p.isExitCode()
-                        && !p.isJavaLevelDeadlock()
-                        && !p.isOome());
-            Optional<ProblemOccurrence> bpOpt = stream.findAny();
+                    !p.isFailedTests(compactor)
+                        && !p.isSnapshotDepProblem(compactor)
+                        && !p.isExecutionTimeout(compactor)
+                        && !p.isJvmCrash(compactor)
+                        && !p.isExitCode(compactor)
+                        //&& !p.isJavaLevelDeadlock(compactor)
+                        && !p.isOome(compactor));
+            Optional<ProblemCompacted> bpOpt = stream.findAny();
             if (bpOpt.isPresent()) {
                 if (res.length() > 0)
                     res.append(", ");
 
-                res.append(bpOpt.get().type).append(" ");
+                res.append(bpOpt.get().type(compactor)).append(" ");
             }
         }
 
@@ -279,16 +255,19 @@ public class MultBuildRunCtx implements ISuiteResults {
         return firstBuildInfo.branchName;
     }
 
-    public void setStat(@Nullable Statistics stat) {
-        this.stat = stat;
-    }
-
     /**
      * @return last build duration.
      */
     @Nullable
     public Long getBuildDuration() {
-        return stat == null ? null : stat.getBuildDuration();
+        final OptionalDouble average = buildsStream()
+                .mapToLong(SingleBuildRunCtx::getBuildDuration)
+                .filter(Objects::nonNull)
+                .average();
+        if(average.isPresent())
+            return (long) average.getAsDouble();
+
+        return null;
     }
 
     @Nullable public String suiteName() {
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/SingleBuildRunCtx.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/SingleBuildRunCtx.java
index f34a53d..a471a8a 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/SingleBuildRunCtx.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/analysis/SingleBuildRunCtx.java
@@ -26,12 +26,10 @@ import java.util.concurrent.Future;
 import java.util.stream.Stream;
 import javax.annotation.Nonnull;
 import org.apache.ignite.ci.tcmodel.changes.Change;
-import org.apache.ignite.ci.tcmodel.result.Build;
-import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
-import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrence;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrenceFull;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
+import org.apache.ignite.ci.teamcity.ignited.fatbuild.ProblemCompacted;
 import org.apache.ignite.ci.util.FutureUtil;
 import org.jetbrains.annotations.Nullable;
 
@@ -41,26 +39,22 @@ import org.jetbrains.annotations.Nullable;
 public class SingleBuildRunCtx implements ISuiteResults {
     /** Build compacted. */
     private FatBuildCompacted buildCompacted;
+
     /** Compactor. */
     private IStringCompactor compactor;
 
     /** Logger check result future. */
     private CompletableFuture<LogCheckResult> logCheckResFut;
 
-    /** Build problems occurred during single build run. */
-    @Nullable private List<ProblemOccurrence> problems;
-
     /** Changes. */
     private List<Change> changes = new ArrayList<>();
 
     /**
-     * @param build Build.
      * @param buildCompacted Build compacted.
      * @param compactor Compactor.
      */
-    public SingleBuildRunCtx(Build build,
-        FatBuildCompacted buildCompacted,
-        IStringCompactor compactor) {
+    public SingleBuildRunCtx(FatBuildCompacted buildCompacted,
+                             IStringCompactor compactor) {
         this.buildCompacted = buildCompacted;
         this.compactor = compactor;
     }
@@ -78,26 +72,23 @@ public class SingleBuildRunCtx implements ISuiteResults {
     }
 
     private long getExecutionTimeoutCount() {
-        return 
getProblemsStream().filter(ProblemOccurrence::isExecutionTimeout).count();
+        return getProblemsStream().filter(p -> 
p.isExecutionTimeout(compactor)).count();
     }
 
-    Stream<ProblemOccurrence> getProblemsStream() {
-        if (problems == null)
-            return Stream.empty();
-
-        return problems.stream().filter(Objects::nonNull);
+    Stream<ProblemCompacted> getProblemsStream() {
+        return buildCompacted.problems().stream();
     }
 
     @Override public boolean hasJvmCrashProblem() {
-        return getProblemsStream().anyMatch(ProblemOccurrence::isJvmCrash);
+        return getProblemsStream().anyMatch(p -> p.isJvmCrash(compactor));
     }
 
     @Override public boolean hasOomeProblem() {
-        return getProblemsStream().anyMatch(ProblemOccurrence::isOome);
+        return getProblemsStream().anyMatch(p -> p.isOome(compactor));
     }
 
     @Override public boolean hasExitCodeProblem() {
-        return getProblemsStream().anyMatch(ProblemOccurrence::isExitCode);
+        return getProblemsStream().anyMatch(p -> p.isExitCode(compactor));
     }
 
     @Override public String suiteId() {
@@ -149,10 +140,6 @@ public class SingleBuildRunCtx implements ISuiteResults {
         return logCheckRes;
     }
 
-    public void setProblems(@Nullable List<ProblemOccurrence> problems) {
-        this.problems = problems;
-    }
-
     public void addChange(Change change) {
         if (change.isFakeStub())
             return;
@@ -206,4 +193,8 @@ public class SingleBuildRunCtx implements ISuiteResults {
     public String projectId() {
         return buildCompacted.projectId(compactor);
     }
+
+    public Long getBuildDuration() {
+        return buildCompacted.buildDuration(compactor);
+    }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/DbMigrations.java 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/DbMigrations.java
index 8b06abb..6441ab1 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/DbMigrations.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/db/DbMigrations.java
@@ -42,7 +42,6 @@ import 
org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrences;
 import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrenceFull;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrences;
-import org.apache.ignite.ci.tcmodel.result.tests.TestRef;
 import org.apache.ignite.ci.web.rest.build.GetBuildTestFailures;
 import org.apache.ignite.ci.web.rest.pr.GetPrTestFailures;
 import org.apache.ignite.ci.web.rest.tracked.GetTrackedBranchTestResults;
@@ -64,6 +63,9 @@ public class DbMigrations {
     public static final String TESTS = "tests";
     @Deprecated
     private static final String BUILD_RESULTS = "buildResults";
+
+    private static final String BUILD_STATISTICS = "buildStatistics";
+
     public static final String TESTS_COUNT_7700 = ",count:7700";
 
     //V1 caches, 1024 parts
@@ -108,17 +110,15 @@ public class DbMigrations {
     }
 
     public void dataMigration(
-        IgniteCache<String, TestOccurrences> testOccurrencesCache, 
Consumer<TestOccurrences> saveTestToStat,
-        Consumer<TestOccurrences> saveTestToLatest,
-        Cache<String, Build> buildCache, Consumer<Build> saveBuildToStat,
-        IgniteCache<SuiteInBranch, RunStat> suiteHistCache,
-        IgniteCache<TestInBranch, RunStat> testHistCache,
-        Cache<String, TestOccurrenceFull> testFullCache,
-        Cache<String, ProblemOccurrences> problemsCache,
-        Cache<String, Statistics> buildStatCache,
-        Cache<SuiteInBranch, Expirable<List<BuildRef>>> buildHistCache,
-        Cache<SuiteInBranch, Expirable<List<BuildRef>>> buildHistInFailedCache,
-        Cache<String, TestRef> testRefsCache) {
+            IgniteCache<String, TestOccurrences> testOccurrencesCache, 
Consumer<TestOccurrences> saveTestToStat,
+            Consumer<TestOccurrences> saveTestToLatest,
+            Cache<String, Build> buildCache, Consumer<Build> saveBuildToStat,
+            IgniteCache<SuiteInBranch, RunStat> suiteHistCache,
+            IgniteCache<TestInBranch, RunStat> testHistCache,
+            Cache<String, TestOccurrenceFull> testFullCache,
+            Cache<String, ProblemOccurrences> problemsCache,
+            Cache<SuiteInBranch, Expirable<List<BuildRef>>> buildHistCache,
+            Cache<SuiteInBranch, Expirable<List<BuildRef>>> 
buildHistInFailedCache) {
 
         doneMigrations = doneMigrationsCache();
 
@@ -346,7 +346,6 @@ public class DbMigrations {
             }
         });
         applyV1toV2Migration(PROBLEMS, problemsCache);
-        applyV1toV2Migration(STAT, buildStatCache);
         applyV1toV2Migration(FINISHED_BUILDS, buildHistCache);
         applyV1toV2Migration(FINISHED_BUILDS_INCLUDE_FAILED, 
buildHistInFailedCache);
 
@@ -407,6 +406,8 @@ public class DbMigrations {
 
         applyDestroyCacheMigration(TEAMCITY_BUILD_CACHE_NAME_OLD, 
TEAMCITY_BUILD_CACHE_NAME_OLD);
         applyDestroyIgnCacheMigration(TESTS);
+        applyDestroyIgnCacheMigration(STAT);
+        applyDestroyIgnCacheMigration(BUILD_STATISTICS);
     }
 
     private void applyDestroyIgnCacheMigration(String cacheName) {
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/builds/CompareBuildsService.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/builds/CompareBuildsService.java
index b383dc5..da17398 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/builds/CompareBuildsService.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/builds/CompareBuildsService.java
@@ -26,6 +26,7 @@ import org.apache.ignite.ci.analysis.MultBuildRunCtx;
 import org.apache.ignite.ci.tcbot.chain.BuildChainProcessor;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.Build;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
 import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
 import org.apache.ignite.ci.teamcity.restcached.ITcServerProvider;
@@ -41,6 +42,7 @@ public class CompareBuildsService {
     @Inject ICredentialsProv prov;
     @Inject BuildChainProcessor bcp;
     @Inject ITeamcityIgnitedProvider tcIgnitedProv;
+    @Inject IStringCompactor compactor;
 
     public List<String> tests0(String srvId, Integer buildId ) {
         IAnalyticsEnabledTeamcity teamcity = helper.server(srvId, prov);
@@ -74,7 +76,7 @@ public class CompareBuildsService {
         else {
             logger.info("Loading tests for build {}.", build.getId());
 
-            MultBuildRunCtx buildCtx = new MultBuildRunCtx(build);
+            MultBuildRunCtx buildCtx = new MultBuildRunCtx(build, compactor);
 
             buildCtx.addBuild(bcp.loadTestsAndProblems(tc, build, buildCtx, 
server));
 
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
index cb7a886..8318fa1 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcbot/chain/BuildChainProcessor.java
@@ -23,7 +23,6 @@ import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
@@ -158,7 +157,8 @@ public class BuildChainProcessor {
         ITeamcityIgnited teamcityIgnited, Map<String, MultBuildRunCtx> 
buildsCtxMap,
         Stream<? extends BuildRef> list) {
         list.forEach((BuildRef ref) -> {
-            MultBuildRunCtx ctx = 
buildsCtxMap.computeIfAbsent(ref.buildTypeId, k -> new MultBuildRunCtx(ref));
+            MultBuildRunCtx ctx = buildsCtxMap.computeIfAbsent(ref.buildTypeId,
+                    k -> new MultBuildRunCtx(ref, compactor));
 
             ctx.addBuild(loadTestsAndProblems(teamcity, ref, ctx, 
teamcityIgnited));
         });
@@ -177,9 +177,8 @@ public class BuildChainProcessor {
         @Deprecated MultBuildRunCtx mCtx, ITeamcityIgnited tcIgnited) {
 
         FatBuildCompacted buildCompacted = 
tcIgnited.getFatBuild(buildRef.getId());
-        Build buildFromFat = buildCompacted.toBuild(compactor);
 
-        SingleBuildRunCtx ctx = new SingleBuildRunCtx(buildFromFat, 
buildCompacted, compactor);
+        SingleBuildRunCtx ctx = new SingleBuildRunCtx(buildCompacted, 
compactor);
 
         if (!buildCompacted.isComposite())
             
mCtx.addTests(buildCompacted.getTestOcurrences(compactor).getTests());
@@ -190,8 +189,6 @@ public class BuildChainProcessor {
 
         if (build == null || build.isFakeStub())
             return ctx;
-        if (build.problemOccurrences != null)
-            ctx.setProblems(teamcity.getProblems(build).getProblemsNonNull());
 
         if (build.lastChanges != null) {
             for (ChangeRef next : build.lastChanges.changes) {
@@ -215,9 +212,6 @@ public class BuildChainProcessor {
             }
         }
 
-        if (build.statisticsRef != null)
-            
mCtx.setStat(teamcity.getBuildStatistics(build.statisticsRef.href));
-
         return ctx;
     }
 
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/bt/Parameters.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/bt/Parameters.java
index 3f9393a..b0980a7 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/bt/Parameters.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/bt/Parameters.java
@@ -19,6 +19,7 @@ package org.apache.ignite.ci.tcmodel.conf.bt;
 
 import org.jetbrains.annotations.Nullable;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
@@ -42,4 +43,8 @@ public class Parameters {
             Objects.equals(property.name, key)).findAny();
         return any.map(Property::getValue).orElse(null);
     }
+
+    public List<Property> properties() {
+        return Collections.unmodifiableList(this.properties);
+    }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/bt/Property.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/bt/Property.java
index 107cfed..a3ee651 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/bt/Property.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/conf/bt/Property.java
@@ -36,4 +36,8 @@ public class Property {
     public String getValue() {
         return value;
     }
+
+    public String name() {
+        return name;
+    }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/problems/ProblemOccurrence.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/problems/ProblemOccurrence.java
index 72433f4..efbd438 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/problems/ProblemOccurrence.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/problems/ProblemOccurrence.java
@@ -77,4 +77,12 @@ public class ProblemOccurrence {
     public boolean isJavaLevelDeadlock() {
         return JAVA_LEVEL_DEADLOCK.equals(type);
     }
+
+    public String id() {
+        return id;
+    }
+
+    public void id(String fullStrId) {
+        this.id = fullStrId;
+    }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/stat/Statistics.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/stat/Statistics.java
index 1a72247..2bbe6fb 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/stat/Statistics.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/tcmodel/result/stat/Statistics.java
@@ -29,11 +29,14 @@ import org.jetbrains.annotations.Nullable;
 @XmlRootElement(name = "properties")
 @XmlAccessorType(XmlAccessType.FIELD)
 public class Statistics extends Parameters {
+    public static final String BUILD_DURATION = "BuildDuration";
+    public static final String BUILD_STAGE_DURATION_SOURCES_UPDATE = 
"buildStageDuration:sourcesUpdate";
+
     /**
      * @return build duration in millis or null.
      */
     @Nullable public Long getBuildDuration() {
-        String duration = getParameter("BuildDuration");
+        String duration = getParameter(BUILD_DURATION);
         if (duration == null)
             return null;
 
@@ -44,11 +47,12 @@ public class Statistics extends Parameters {
      * @return source update duration in millis.
      */
     @Nullable public Long getSourceUpdateDuration() {
-        String duration = getParameter(  "buildStageDuration:sourcesUpdate");
+        String duration = getParameter(BUILD_STAGE_DURATION_SOURCES_UPDATE);
 
         if (duration == null)
             return null;
 
         return Long.parseLong(duration);
     }
+
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
index 5603b44..1762693 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/TeamcityIgnitedImpl.java
@@ -211,7 +211,7 @@ public class TeamcityIgnitedImpl implements 
ITeamcityIgnited {
     protected String runActualizeBuildRefs(String srvId, boolean fullReindex,
                                            @Nullable Set<Integer> 
mandatoryToReload) {
         AtomicReference<String> outLinkNext = new AtomicReference<>();
-        List<BuildRef> tcDataFirstPage = conn.getBuildRefs(null, outLinkNext);
+        List<BuildRef> tcDataFirstPage = conn.getBuildRefsPage(null, 
outLinkNext);
 
         Set<Long> buildsUpdated = buildRefDao.saveChunk(srvIdMaskHigh, 
tcDataFirstPage);
         int totalUpdated = buildsUpdated.size();
@@ -228,7 +228,7 @@ public class TeamcityIgnitedImpl implements 
ITeamcityIgnited {
         while (outLinkNext.get() != null) {
             String nextPageUrl = outLinkNext.get();
             outLinkNext.set(null);
-            List<BuildRef> tcDataNextPage = conn.getBuildRefs(nextPageUrl, 
outLinkNext);
+            List<BuildRef> tcDataNextPage = conn.getBuildRefsPage(nextPageUrl, 
outLinkNext);
             Set<Long> curChunkBuildsSaved = 
buildRefDao.saveChunk(srvIdMaskHigh, tcDataNextPage);
             totalUpdated += curChunkBuildsSaved.size();
             buildSync.scheduleBuildsLoad(conn, 
cacheKeysToBuildIds(curChunkBuildsSaved));
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
index 231ed5d..bbbeb9f 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildCompacted.java
@@ -19,7 +19,9 @@ package org.apache.ignite.ci.teamcity.ignited.fatbuild;
 import com.google.common.base.Objects;
 import java.util.ArrayList;
 import java.util.BitSet;
+import java.util.Collections;
 import java.util.List;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.apache.ignite.ci.analysis.IVersionedEntity;
 import org.apache.ignite.ci.db.Persisted;
@@ -27,10 +29,13 @@ import org.apache.ignite.ci.tcmodel.conf.BuildType;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.Build;
 import org.apache.ignite.ci.tcmodel.result.TestOccurrencesRef;
+import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
+import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrenceFull;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
 import org.apache.ignite.ci.teamcity.ignited.BuildRefCompacted;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -39,7 +44,7 @@ import org.jetbrains.annotations.Nullable;
 @Persisted
 public class FatBuildCompacted extends BuildRefCompacted implements 
IVersionedEntity {
     /** Latest version. */
-    private static final int LATEST_VERSION = 2;
+    private static final int LATEST_VERSION = 4;
 
     /** Default branch flag offset. */
     public static final int DEF_BR_F = 0;
@@ -74,6 +79,10 @@ public class FatBuildCompacted extends BuildRefCompacted 
implements IVersionedEn
 
     private BitSet flags = new BitSet();
 
+    @Nullable private List<ProblemCompacted> problems;
+
+    @Nullable private StatisticsCompacted statistics;
+
     /** {@inheritDoc} */
     @Override public int version() {
         return _ver;
@@ -101,7 +110,6 @@ public class FatBuildCompacted extends BuildRefCompacted 
implements IVersionedEn
         finishDate = build.getFinishDate() == null ? -1L : 
build.getFinishDate().getTime();
         queuedDate = build.getQueuedDate() == null ? -1L : 
build.getQueuedDate().getTime();
 
-
         BuildType type = build.getBuildType();
         if (type != null) {
             projectId = compactor.getStringId(type.getProjectId());
@@ -194,7 +202,6 @@ public class FatBuildCompacted extends BuildRefCompacted 
implements IVersionedEn
         }
     }
 
-
     /**
      * @param off Offset.
      * @param val Value.
@@ -257,12 +264,15 @@ public class FatBuildCompacted extends BuildRefCompacted 
implements IVersionedEn
             name == that.name &&
             Objects.equal(tests, that.tests) &&
             Objects.equal(snapshotDeps, that.snapshotDeps) &&
-            Objects.equal(flags, that.flags);
+            Objects.equal(flags, that.flags) &&
+                Objects.equal(problems, that.problems) &&
+                Objects.equal(statistics, that.statistics);
     }
 
     /** {@inheritDoc} */
     @Override public int hashCode() {
-        return Objects.hashCode(super.hashCode(), _ver, startDate, finishDate, 
queuedDate, projectId, name, tests, snapshotDeps, flags);
+        return Objects.hashCode(super.hashCode(), _ver, startDate, finishDate, 
queuedDate, projectId, name, tests,
+                snapshotDeps, flags, problems, statistics);
     }
 
     /**
@@ -297,4 +307,41 @@ public class FatBuildCompacted extends BuildRefCompacted 
implements IVersionedEn
     public String projectId(IStringCompactor compactor) {
         return compactor.getStringFromId(projectId);
     }
+
+    public List<ProblemOccurrence> problems(IStringCompactor compactor) {
+        if (this.problems == null)
+             return Collections.emptyList();
+
+        return this.problems.stream()
+                .map(pc -> pc.toProblemOccurrence(compactor, id()))
+                .collect(Collectors.toList());
+    }
+
+    public List<ProblemCompacted> problems() {
+        if (this.problems == null)
+            return Collections.emptyList();
+
+        return Collections.unmodifiableList(this.problems);
+    }
+
+    public void addProblems(IStringCompactor compactor,
+                            @NotNull List<ProblemOccurrence> occurrences) {
+        if (occurrences.isEmpty())
+            return;
+
+        if (this.problems == null)
+            this.problems = new ArrayList<>();
+
+        occurrences.stream()
+                .map(p -> new ProblemCompacted(compactor, p))
+                .forEach(this.problems::add);
+    }
+
+    public Long buildDuration(IStringCompactor compactor) {
+        return statistics == null ? null : statistics.buildDuration(compactor);
+    }
+
+    public void statistics(IStringCompactor compactor, Statistics statistics) {
+        this.statistics = new StatisticsCompacted(compactor, statistics);
+    }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildDao.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildDao.java
index afe4812..da8c789 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildDao.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/FatBuildDao.java
@@ -24,20 +24,17 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
-import java.util.stream.StreamSupport;
-import javax.cache.Cache;
 import javax.inject.Inject;
 import javax.inject.Provider;
 import javax.validation.constraints.NotNull;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.ci.db.TcHelperDb;
-import org.apache.ignite.ci.di.AutoProfiling;
 import org.apache.ignite.ci.tcmodel.result.Build;
+import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
+import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
-import org.apache.ignite.ci.teamcity.ignited.BuildRefDao;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
-import org.apache.ignite.internal.util.GridIntList;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -68,14 +65,18 @@ public class FatBuildDao {
      * @param buildId
      * @param build Build data.
      * @param tests TestOccurrences one or several pages.
+     * @param problems
+     * @param statistics
      * @param existingBuild existing version of build in the DB.
      * @return Fat Build saved (if modifications detected), otherwise null.
      */
     public FatBuildCompacted saveBuild(long srvIdMaskHigh,
-        int buildId,
-        @NotNull Build build,
-        List<TestOccurrencesFull> tests,
-        @Nullable FatBuildCompacted existingBuild) {
+                                       int buildId,
+                                       @NotNull Build build,
+                                       @NotNull List<TestOccurrencesFull> 
tests,
+                                       @Nullable List<ProblemOccurrence> 
problems,
+                                       @Nullable Statistics statistics,
+                                       @Nullable FatBuildCompacted 
existingBuild) {
         Preconditions.checkNotNull(buildsCache, "init() was not called");
         Preconditions.checkNotNull(build, "build can't be null");
 
@@ -84,6 +85,12 @@ public class FatBuildDao {
         for (TestOccurrencesFull next : tests)
             newBuild.addTests(compactor, next.getTests());
 
+        if (problems != null)
+            newBuild.addProblems(compactor, problems);
+
+        if (statistics != null)
+            newBuild.statistics(compactor, statistics);
+
         if (existingBuild == null || !existingBuild.equals(newBuild)) {
             buildsCache.put(buildIdToCacheKey(srvIdMaskHigh, buildId), 
newBuild);
 
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
index 8eac870..a99463d 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProactiveFatBuildSync.java
@@ -22,6 +22,8 @@ import org.apache.ignite.ci.di.AutoProfiling;
 import org.apache.ignite.ci.di.MonitoredTask;
 import org.apache.ignite.ci.di.scheduler.IScheduler;
 import org.apache.ignite.ci.tcmodel.result.Build;
+import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
+import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
 import org.apache.ignite.ci.teamcity.ignited.BuildRefDao;
 import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
@@ -213,18 +215,28 @@ public class ProactiveFatBuildSync {
 
         Build build;
         List<TestOccurrencesFull> tests = new ArrayList<>();
+        List<ProblemOccurrence> problems = null;
+        Statistics statistics = null;
         try {
             build = conn.getBuild(buildId);
 
-            String nextHref = null;
-            do {
-                boolean testDtls = !build.isComposite(); // don't query test 
details for compoite
-                TestOccurrencesFull page = conn.getTestsPage(buildId, 
nextHref, testDtls);
-                nextHref = page.nextHref();
+            if(build.testOccurrences!=null) {
+                String nextHref = null;
+                do {
+                    boolean testDtls = !build.isComposite(); // don't query 
test details for compoite
+                    TestOccurrencesFull page = conn.getTestsPage(buildId, 
nextHref, testDtls);
+                    nextHref = page.nextHref();
 
-                tests.add(page);
+                    tests.add(page);
+                }
+                while (!Strings.isNullOrEmpty(nextHref));
             }
-            while (!Strings.isNullOrEmpty(nextHref));
+
+            if (build.problemOccurrences != null)
+                problems = conn.getProblems(buildId).getProblemsNonNull();
+
+            if(build.statisticsRef!=null)
+                statistics = conn.getStatistics(buildId);
         }
         catch (Exception e) {
             if (Throwables.getRootCause(e) instanceof FileNotFoundException) {
@@ -237,9 +249,12 @@ public class ProactiveFatBuildSync {
                         build.setCancelled();
 
                     tests = 
Collections.singletonList(existingBuild.getTestOcurrences(compactor));
+
+                    problems = existingBuild.problems(compactor);
                 }
-                else
+                else {
                     build = Build.createFakeStub();
+                }
             } else {
                 logger.error("Loading build [" + buildId + "] for server [" + 
srvNme + "] failed:" + e.getMessage(), e);
 
@@ -251,6 +266,6 @@ public class ProactiveFatBuildSync {
 
         //if we are here because of some sort of outdated version of build,
         // new save will be performed with new entity version for compacted 
build
-        return fatBuildDao.saveBuild(srvIdMask, buildId, build, tests, 
existingBuild);
+        return fatBuildDao.saveBuild(srvIdMask, buildId, build, tests, 
problems, statistics, existingBuild);
     }
 }
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProblemCompacted.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProblemCompacted.java
new file mode 100644
index 0000000..961dbe8
--- /dev/null
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/ProblemCompacted.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ci.teamcity.ignited.fatbuild;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Strings;
+import org.apache.ignite.ci.analysis.RunStat;
+import org.apache.ignite.ci.tcmodel.hist.BuildRef;
+import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
+import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrence;
+import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrenceFull;
+import org.apache.ignite.ci.tcmodel.result.tests.TestRef;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.jetbrains.annotations.Nullable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xerial.snappy.Snappy;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.BitSet;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+import static org.apache.ignite.ci.analysis.RunStat.extractIdPrefixed;
+
+/**
+ *
+ */
+public class ProblemCompacted {
+    /** Logger. */
+    private static final Logger logger = 
LoggerFactory.getLogger(ProblemCompacted.class);
+
+    /** Id  */
+    private int id = -1;
+    private int type = -1;
+    private int identity = -1;
+
+    /** Actual build id. */
+    private int actualBuildId = -1;
+
+    // later details may be needed @Nullable private byte[] details;
+
+    /**
+     * Default constructor.
+     */
+    public ProblemCompacted() {
+    }
+
+    /**
+     * @param compactor Compactor.
+     * @param problemOccurrence TestOccurrence.
+     */
+    public ProblemCompacted(IStringCompactor compactor, ProblemOccurrence 
problemOccurrence) {
+        String problemIdStr = problemOccurrence.id();
+        if (!Strings.isNullOrEmpty(problemIdStr)) {
+            try {
+                final Integer problemId = extractIdPrefixed(problemIdStr, 
"problem:(id:", ")");
+                if (problemId != null)
+                    id = problemId;
+            } catch (Exception e) {
+                logger.error("Failed to handle TC response: " + problemIdStr, 
e);
+            }
+        }
+
+        type = compactor.getStringId(problemOccurrence.type);
+        identity = compactor.getStringId(problemOccurrence.identity);
+
+
+        if (problemOccurrence.buildRef != null && 
problemOccurrence.buildRef.getId() != null)
+            actualBuildId = problemOccurrence.buildRef.getId();
+
+    }
+
+
+    public ProblemOccurrence toProblemOccurrence(IStringCompactor compactor, 
int buildId) {
+        ProblemOccurrence occurrence = new ProblemOccurrence();
+
+        String fullStrId =
+                "problem:(id:" + id + ")," +
+                        " build:(id:" + buildId + ")";
+        occurrence.id(fullStrId);
+        occurrence.type = compactor.getStringFromId(type);
+        occurrence.identity = compactor.getStringFromId(identity);
+        occurrence.href = "problemOccurrences?locator=" + fullStrId;
+
+        if (actualBuildId > 0) {
+            BuildRef buildRef = new BuildRef();
+
+            buildRef.setId(actualBuildId);
+
+            occurrence.buildRef = buildRef;
+        }
+
+        return occurrence;
+    }
+
+    private int id() {
+        return id;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        ProblemCompacted that = (ProblemCompacted) o;
+        return id == that.id &&
+                type == that.type &&
+                identity == that.identity &&
+                actualBuildId == that.actualBuildId;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(id, type, identity, actualBuildId);
+    }
+
+    public boolean isExecutionTimeout(IStringCompactor compactor) {
+        return compactor.getStringId(ProblemOccurrence.TC_EXECUTION_TIMEOUT) 
== type;
+    }
+
+    public String type(IStringCompactor compactor) {
+        return compactor.getStringFromId(type);
+    }
+
+    public boolean isJvmCrash(IStringCompactor compactor) {
+        return compactor.getStringId(ProblemOccurrence.TC_JVM_CRASH) == type;
+    }
+
+    public boolean isOome(IStringCompactor compactor) {
+        return compactor.getStringId(ProblemOccurrence.TC_OOME) == type;
+    }
+
+    public boolean isExitCode(IStringCompactor compactor) {
+        return compactor.getStringId(ProblemOccurrence.TC_EXIT_CODE) == type;
+    }
+
+    public boolean isFailedTests(IStringCompactor compactor) {
+        return compactor.getStringId(ProblemOccurrence.TC_FAILED_TESTS) == 
type;
+    }
+
+    public boolean isSnapshotDepProblem(IStringCompactor compactor) {
+        return 
compactor.getStringId(ProblemOccurrence.SNAPSHOT_DEPENDENCY_ERROR) == type
+                || 
compactor.getStringId(ProblemOccurrence.SNAPSHOT_DEPENDENCY_ERROR_BUILD_PROCEEDS_TYPE)
 == type;
+    }
+}
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/StatisticsCompacted.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/StatisticsCompacted.java
new file mode 100644
index 0000000..52f1e91
--- /dev/null
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/StatisticsCompacted.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ci.teamcity.ignited.fatbuild;
+
+import com.google.common.base.Strings;
+import org.apache.ignite.ci.tcmodel.conf.bt.Property;
+import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
+import org.apache.ignite.ci.teamcity.ignited.IStringCompactor;
+import org.apache.ignite.internal.util.GridIntList;
+import org.apache.ignite.internal.util.GridLongList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+public class StatisticsCompacted {
+    /** Logger. */
+    private static final Logger logger = 
LoggerFactory.getLogger(StatisticsCompacted.class);
+
+    private GridIntList keys;
+    private GridLongList values;
+
+    public StatisticsCompacted() {
+    }
+
+    public StatisticsCompacted(IStringCompactor compactor, Statistics 
statistics) {
+        final List<Property> properties = statistics.properties();
+        final int size = properties.size();
+        keys = new GridIntList(size);
+        values = new GridLongList(size);
+        int idx = 0;
+        for (Property next : properties) {
+            final String name = next.name();
+            if (Strings.isNullOrEmpty(name))
+                continue;
+
+            final String value = next.getValue();
+            if (Strings.isNullOrEmpty(value))
+                continue;
+            final long val;
+            try {
+                val = Long.parseLong(value);
+            } catch (Exception e) {
+                logger.error("Statistics value is not numeric " + name + " 
skipped " + e.getMessage(), e);
+                continue;
+            }
+
+            final int stringId = compactor.getStringId(name);
+
+            keys.add(stringId);
+            values.add(val);
+            idx++;
+        }
+    }
+
+    public Long buildDuration(IStringCompactor compactor) {
+        final Integer buildDurationId = 
compactor.getStringIdIfPresent(Statistics.BUILD_DURATION);
+        if (buildDurationId == null)
+            return null;
+
+        long value = findPropertyValue(buildDurationId);
+
+        if (value < 0) return null;
+
+        return value;
+    }
+
+    private long findPropertyValue(int propertyCode) {
+        final int size = keys.size();
+
+        long value = -1;
+        for (int i = 0; i < size; i++) {
+            final int nameid = keys.get(i);
+
+            if (nameid != propertyCode)
+                continue;
+
+            if (i >= values.size())
+                break;
+
+            value = values.get(i);
+        }
+
+        return value;
+    }
+}
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/TestCompacted.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/TestCompacted.java
index 37a32bc..573b87c 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/TestCompacted.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/ignited/fatbuild/TestCompacted.java
@@ -55,7 +55,7 @@ public class TestCompacted {
     public static final int COMPRESS_TYPE_RFU3 = 10;
     public static final int COMPRESS_TYPE_RFU4 = 11;
 
-    /** Id in this build only. Does not idenfity test for its history */
+    /** Id in this build only. Does not identify test for its history */
     private int idInBuild = -1;
 
     private int name = -1;
diff --git 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java
 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java
index f832088..27f6fe9 100644
--- 
a/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java
+++ 
b/ignite-tc-helper-web/src/main/java/org/apache/ignite/ci/teamcity/pure/ITeamcityConn.java
@@ -23,6 +23,8 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.Build;
+import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrences;
+import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
 
 /**
@@ -41,7 +43,7 @@ public interface ITeamcityConn {
 
     public Build getBuild(int buildId);
 
-    public List<BuildRef> getBuildRefs(String fullUrl, AtomicReference<String> 
nextPage);
+    public List<BuildRef> getBuildRefsPage(String fullUrl, 
AtomicReference<String> nextPage);
 
     /**
      * @param buildId Build id.
@@ -59,4 +61,8 @@ public interface ITeamcityConn {
      * @param queueAtTop Put at the top of the build queue.
      */
     public Build triggerBuild(String buildTypeId, @Nonnull String branchName, 
boolean cleanRebuild, boolean queueAtTop);
+
+    ProblemOccurrences getProblems(int buildId);
+
+    Statistics getStatistics(int buildId);
 }
diff --git 
a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
 
b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
index 173a959..e2649a5 100644
--- 
a/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
+++ 
b/ignite-tc-helper-web/src/test/java/org/apache/ignite/ci/teamcity/ignited/IgnitedTcInMemoryIntegrationTest.java
@@ -40,6 +40,9 @@ import org.apache.ignite.ci.di.scheduler.NoOpSheduler;
 import org.apache.ignite.ci.tcmodel.conf.BuildType;
 import org.apache.ignite.ci.tcmodel.hist.BuildRef;
 import org.apache.ignite.ci.tcmodel.result.Build;
+import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrence;
+import org.apache.ignite.ci.tcmodel.result.problems.ProblemOccurrences;
+import org.apache.ignite.ci.tcmodel.result.stat.Statistics;
 import org.apache.ignite.ci.tcmodel.result.tests.TestOccurrencesFull;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
 import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildDao;
@@ -252,6 +255,8 @@ public class IgnitedTcInMemoryIntegrationTest {
     public void testFatBuild() throws JAXBException, IOException {
         Build refBuild = jaxbTestXml("/build.xml", Build.class);
         TestOccurrencesFull testsRef = jaxbTestXml("/testList.xml", 
TestOccurrencesFull.class);
+        ProblemOccurrences problemsList = jaxbTestXml("/problemList.xml", 
ProblemOccurrences.class);
+        Statistics statistics = jaxbTestXml("/statistics.xml", 
Statistics.class);
 
         Injector injector = Guice.createInjector(new AbstractModule() {
             @Override protected void configure() {
@@ -265,7 +270,8 @@ public class IgnitedTcInMemoryIntegrationTest {
 
         int srvIdMaskHigh = ITeamcityIgnited.serverIdToInt(APACHE);
         List<TestOccurrencesFull> occurrences = 
Collections.singletonList(testsRef);
-        FatBuildCompacted buildCompacted = stor.saveBuild(srvIdMaskHigh, 
refBuild.getId(), refBuild, occurrences, null);
+        FatBuildCompacted buildCompacted = stor.saveBuild(srvIdMaskHigh, 
refBuild.getId(), refBuild, occurrences,
+                problemsList.getProblemsNonNull(), statistics, null);
         assertNotNull(buildCompacted);
 
         FatBuildCompacted fatBuild = stor.getFatBuild(srvIdMaskHigh, 2153237);
@@ -300,6 +306,17 @@ public class IgnitedTcInMemoryIntegrationTest {
         Set<String> testNamesRef = new TreeSet<>();
         testsRef.getTests().forEach(testOccurrence -> 
testNamesRef.add(testOccurrence.name));
         assertEquals(testNamesRef, testNamesAct);
+
+        final List<ProblemOccurrence> problems = 
buildCompacted.problems(compactor);
+        assertEquals(2, problems.size());
+
+        
assertTrue(problems.stream().anyMatch(ProblemOccurrence::isFailedTests));
+        assertTrue(problems.stream().anyMatch(ProblemOccurrence::isExitCode));
+        assertTrue(problems.stream().noneMatch(ProblemOccurrence::isJvmCrash));
+
+        Long duration = buildCompacted.buildDuration(compactor);
+        assertNotNull(duration);
+        assertTrue(duration>10000L);
     }
 
     public void saveTmpFile(Object obj, String name) throws IOException, 
JAXBException {
diff --git a/ignite-tc-helper-web/src/test/resources/problemList.xml 
b/ignite-tc-helper-web/src/test/resources/problemList.xml
new file mode 100644
index 0000000..4a770f2
--- /dev/null
+++ b/ignite-tc-helper-web/src/test/resources/problemList.xml
@@ -0,0 +1,20 @@
+<!-- Syntetic list from:
+ 
https://ci.ignite.apache.org/app/rest/latest/problemOccurrences?locator=build:(id:2153237)&fields=problemOccurrence(id,type,identity,href,details,build(id))-->
+<problemOccurrences>
+    <problemOccurrence id="problem:(id:3481),build:(id:2136678)" 
type="TC_EXIT_CODE" identity="Inspection1"
+                       
href="/app/rest/latest/problemOccurrences/problem:(id:3481),build:(id:2136678)">
+        <details>Process exited with code 1</details>
+        
<additionalData>teamcity.process.flow.id=1200755009805251</additionalData>
+        <problem id="3481" type="TC_EXIT_CODE" identity="Inspection1" 
href="/app/rest/latest/problems/id:3481"/>
+        <build id="2136678" buildTypeId="IgniteTests24Java8_InspectionsAop" 
number="165" status="FAILURE"
+               state="finished" branchName="refs/heads/master" 
defaultBranch="true"
+               href="/app/rest/latest/builds/id:2136678"
+               
webUrl="http://ci.ignite.apache.org/viewLog.html?buildId=2136678&amp;buildTypeId=IgniteTests24Java8_InspectionsAop"/>
+    </problemOccurrence>
+    <problemOccurrence id="problem:(id:3733),build:(id:2153237)" 
type="TC_FAILED_TESTS"
+                       identity="TC_FAILED_TESTS_bt1053"
+                       
href="/app/rest/latest/problemOccurrences/problem:(id:3733),build:(id:2153237)">
+        <details>1 failed test detected</details>
+        <build id="2153237"/>
+    </problemOccurrence>
+</problemOccurrences>
\ No newline at end of file

Reply via email to