Skip to content
Permalink
Browse files
IGNITE-10153 Implement tests running time report - Fixes #64.
Signed-off-by: Dmitriy Pavlov <dpavlov@apache.org>
  • Loading branch information
sergey-chugunov-1985 authored and dspavlov committed Nov 12, 2018
1 parent f7fc6d3 commit 2f565739048b54c33f1015a2bc5c5f9696e25950
Show file tree
Hide file tree
Showing 12 changed files with 431 additions and 30 deletions.
@@ -14,6 +14,9 @@
.idea/
*.iml

# gradle build files
.gradle/

# Package Files #
*.jar
*.war
@@ -19,6 +19,7 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
@@ -50,6 +51,8 @@
import org.apache.ignite.ci.teamcity.ignited.fatbuild.FatBuildCompacted;
import org.apache.ignite.ci.util.FutureUtil;
import org.apache.ignite.ci.web.TcUpdatePool;
import org.apache.ignite.ci.web.model.long_running.LRTest;
import org.apache.ignite.ci.web.model.long_running.SuiteLRTestsSummary;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@@ -68,6 +71,85 @@ public class BuildChainProcessor {
/** Compactor. */
@Inject private IStringCompactor compactor;

/**
* Collects data about all long-running tests (run time more than one minute) across all suites in RunAll chain
* in master branch.
*
* @param teamcityIgnited interface to TC bot database.
* @param entryPoints
* @return list of summaries about individual suite runs.
*/
public List<SuiteLRTestsSummary> loadLongRunningTestsSummary(
ITeamcityIgnited teamcityIgnited,
Collection<BuildRef> entryPoints
) {
final List<SuiteLRTestsSummary> res = new ArrayList<>();

if (entryPoints.isEmpty())
return res;

Map<Integer, FatBuildCompacted> builds = new ConcurrentHashMap<>();

final Stream<FatBuildCompacted> entryPointsFatBuilds = entryPoints.stream().map(BuildRef::getId)
.filter(Objects::nonNull)
.filter(id -> !builds.containsKey(id)) //load and propagate only new entry points
.map(id -> builds.computeIfAbsent(id, teamcityIgnited::getFatBuild));

final ExecutorService svc = tcUpdatePool.getService();

final Stream<FatBuildCompacted> depsFirstLevel = entryPointsFatBuilds
.map(ref -> svc.submit(() -> dependencies(teamcityIgnited, builds, ref)))
.collect(Collectors.toList())
.stream()
.flatMap(fut -> FutureUtil.getResult(fut));

depsFirstLevel
.filter(b -> !b.isComposite() && b.getTestsCount() > 0)
.forEach(b ->
{
List<LRTest> lrTests = new ArrayList<>();

b.getAllTests()
.filter(t -> t.getDuration() > 60 * 1000)
.forEach(
t -> lrTests
.add(new LRTest(t.testName(compactor), t.getDuration(), null))
);

if (!lrTests.isEmpty()) {
Collections.sort(lrTests, (test0, test1) -> {
long t0 = test0.time;
long t1 = test1.time;

if (t0 < t1)
return 1;

if (t0 == t1)
return 0;

return -1;
});

res.add(
new SuiteLRTestsSummary(b.buildTypeName(compactor),
b.buildDuration(compactor) / b.getTestsCount(),
lrTests));
}
});

Collections.sort(res, (s0, s1) -> {
if (s0.testAvgTime < s1.testAvgTime)
return 1;

if (s0.testAvgTime == s1.testAvgTime)
return 0;

return -1;
});

return res;
}

/**
* @param teamcity Teamcity.
* @param teamcityIgnited
@@ -111,7 +193,7 @@ public FullChainRunCtx loadFullChainContext(
.stream()
.flatMap(fut -> FutureUtil.getResult(fut));

// builds may became non unique because of rece in filtering and acquiring deps
// builds may became non unique because of race in filtering and acquiring deps
final List<Future<Stream<FatBuildCompacted>>> phase3Submitted = secondLevelDeps
.map((fatBuild) -> svc.submit(
() -> replaceWithRecent(teamcityIgnited, includeLatestRebuild, builds, fatBuild, entryPoints.size())))
@@ -23,18 +23,19 @@
import javax.inject.Inject;
import org.apache.ignite.ci.HelperConfig;
import org.apache.ignite.ci.IAnalyticsEnabledTeamcity;
import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
import org.apache.ignite.ci.teamcity.restcached.ITcServerProvider;
import org.apache.ignite.ci.analysis.FullChainRunCtx;
import org.apache.ignite.ci.analysis.mode.LatestRebuildMode;
import org.apache.ignite.ci.analysis.mode.ProcessLogsMode;
import org.apache.ignite.ci.conf.BranchTracked;
import org.apache.ignite.ci.di.AutoProfiling;
import org.apache.ignite.ci.tcmodel.hist.BuildRef;
import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnited;
import org.apache.ignite.ci.teamcity.ignited.ITeamcityIgnitedProvider;
import org.apache.ignite.ci.teamcity.restcached.ITcServerProvider;
import org.apache.ignite.ci.user.ICredentialsProv;
import org.apache.ignite.ci.web.model.current.ChainAtServerCurrentStatus;
import org.apache.ignite.ci.web.model.current.TestFailuresSummary;
import org.apache.ignite.ci.web.model.long_running.FullLRTestsSummary;
import org.apache.ignite.ci.web.rest.parms.FullQueryParams;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -124,4 +125,46 @@ public TestFailuresSummary getTrackedBranchTestFailures(

return res;
}

/**
* Collects data about all long-running tests (run time more than one minute) within one transfer object.
*
* @param branch
* @param creds
* @return
*/
public FullLRTestsSummary getTrackedBranchLongRunningTestsSummary(@Nullable String branch,
ICredentialsProv creds) {
FullLRTestsSummary summary = new FullLRTestsSummary();

final String branchNn = isNullOrEmpty(branch) ? FullQueryParams.DEFAULT_TRACKED_BRANCH_NAME : branch;
final BranchTracked tracked = HelperConfig.getTrackedBranches().getBranchMandatory(branchNn);

tracked.chains.stream()
.filter(chainTracked -> creds.hasAccess(chainTracked.serverId))
.map(chainTracked -> {
final String srvId = chainTracked.serverId;

final String branchForTc = chainTracked.getBranchForRestMandatory();

IAnalyticsEnabledTeamcity teamcity = srvProv.server(srvId, creds);

ITeamcityIgnited tcIgnited = tcIgnitedProv.server(srvId, creds);

final List<BuildRef> buildsList = teamcity.getFinishedBuildsIncludeSnDepFailed(
chainTracked.getSuiteIdMandatory(),
branchForTc);

List<BuildRef> chains = buildsList.stream()
.filter(ref -> !ref.isFakeStub())
.sorted(Comparator.comparing(BuildRef::getId).reversed())
.limit(1)
.filter(b -> b.getId() != null).collect(Collectors.toList());

return chainProc.loadLongRunningTestsSummary(tcIgnited, chains);
})
.forEach(summary::addSuiteSummaries);

return summary;
}
}
@@ -355,6 +355,10 @@ public Stream<TestCompacted> getAllTests() {
return tests.stream();
}

public int getTestsCount() {
return tests != null ? tests.size() : 0;
}

public Stream<String> getAllTestNames(IStringCompactor compactor) {
return getAllTests().map(t -> t.testName(compactor));
}
@@ -0,0 +1,32 @@
/*
* 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.web.model.long_running;

import java.util.ArrayList;
import java.util.List;

/**
*
*/
@SuppressWarnings("WeakerAccess")
public class FullLRTestsSummary {
public List<SuiteLRTestsSummary> suiteSummaries = new ArrayList<>();

public void addSuiteSummaries(List<SuiteLRTestsSummary> summaries) {
suiteSummaries.addAll(summaries);
}
}
@@ -0,0 +1,39 @@
/*
* 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.web.model.long_running;

import static org.apache.ignite.ci.util.TimeUtil.millisToDurationPrintable;

/**
*
*/
public class LRTest {
public String name;

public long time;

public String timePrintable;

public String webLink;

public LRTest(String name, long time, String webLink) {
this.name = name;
this.time = time;
timePrintable = millisToDurationPrintable(time);
this.webLink = webLink;
}
}
@@ -0,0 +1,42 @@
/*
* 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.web.model.long_running;

import java.util.List;

import static org.apache.ignite.ci.util.TimeUtil.millisToDurationPrintable;

/**
*
*/
@SuppressWarnings("WeakerAccess")
public class SuiteLRTestsSummary {
public String name;

public long testAvgTime;

public String testAvgTimePrintable;

public List<LRTest> tests;

public SuiteLRTestsSummary(String name, long testAvgTime, List<LRTest> tests) {
this.name = name;
this.testAvgTime = testAvgTime;
testAvgTimePrintable = millisToDurationPrintable(testAvgTime);
this.tests = tests;
}
}
@@ -0,0 +1,56 @@
/*
* 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.web.rest.long_running;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import org.apache.ignite.ci.tcbot.chain.TrackedBranchChainsProcessor;
import org.apache.ignite.ci.user.ICredentialsProv;
import org.apache.ignite.ci.web.CtxListener;
import org.apache.ignite.ci.web.model.long_running.FullLRTestsSummary;
import org.jetbrains.annotations.Nullable;

@Path(BuildsLongRunningTestsReport.LONG_RUNNING_SUMMARY)
@Produces(MediaType.APPLICATION_JSON)
public class BuildsLongRunningTestsReport {
public static final String LONG_RUNNING_SUMMARY = "long_running";

/** Servlet Context. */
@Context
private ServletContext ctx;

/** Current Request. */
@Context
private HttpServletRequest req;

@GET
@Path("summary")
@Produces(MediaType.APPLICATION_JSON)
public FullLRTestsSummary getBranch(@Nullable @QueryParam("branch") String branchOrNull) {
final ICredentialsProv creds = ICredentialsProv.get(req);

final TrackedBranchChainsProcessor tbProc = CtxListener.getInjector(ctx).getInstance(TrackedBranchChainsProcessor.class);

return tbProc.getTrackedBranchLongRunningTestsSummary(null, creds);
}
}

0 comments on commit 2f56573

Please sign in to comment.