Browse Source

SONAR-12038 Add pendingTime to api/ce/activity_status and ComputeEngineTasks JMX metrics

tags/7.8
Duarte Meneses 5 years ago
parent
commit
36d13bae20
18 changed files with 208 additions and 47 deletions
  1. 14
    8
      server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CEQueueStatus.java
  2. 12
    1
      server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CEQueueStatusImpl.java
  3. 11
    5
      server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeTasksMBean.java
  4. 7
    0
      server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeTasksMBeanImpl.java
  5. 3
    2
      server/sonar-ce/src/main/java/org/sonar/ce/monitoring/DistributedCEQueueStatusImpl.java
  6. 2
    1
      server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CEQueueStatusImplConcurrentTest.java
  7. 2
    1
      server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CEQueueStatusImplTest.java
  8. 10
    1
      server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CeTasksMBeanImplTest.java
  9. 2
    1
      server/sonar-ce/src/test/java/org/sonar/ce/monitoring/DistributedCEQueueStatusImplTest.java
  10. 1
    1
      server/sonar-ce/src/test/java/org/sonar/ce/queue/InternalCeQueueImplTest.java
  11. 4
    1
      server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeQueueDao.java
  12. 3
    0
      server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeQueueMapper.java
  13. 12
    0
      server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeQueueMapper.xml
  14. 61
    1
      server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeQueueDaoTest.java
  15. 27
    19
      server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityStatusAction.java
  16. 2
    1
      server/sonar-server/src/main/resources/org/sonar/server/ce/ws/activity_status-example.json
  17. 34
    4
      server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityStatusActionTest.java
  18. 1
    0
      sonar-ws/src/main/protobuf/ws-ce.proto

+ 14
- 8
server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CEQueueStatus.java View File

@@ -19,6 +19,7 @@
*/
package org.sonar.ce.monitoring;

import java.util.Optional;
import org.sonar.api.ce.ComputeEngineSide;

@ComputeEngineSide
@@ -50,12 +51,12 @@ public interface CEQueueStatus {
long addSuccess(long processingTime);

/**
* Adds 1 to the count of batch reports which processing ended with an error and removes 1 from the count of batch
* reports under processing. Adds the specified time to the processing time counter.
* Adds 1 to the count of tasks which processing ended with an error and removes 1 from the count of tasks
* under processing. Adds the specified time to the processing time counter.
*
* @param processingTime duration of processing in ms
*
* @return the new count of batch reports which processing ended with an error
* @return the new count of tasks which processing ended with an error
*
* @see #getErrorCount()
* @see #getInProgressCount()
@@ -65,27 +66,32 @@ public interface CEQueueStatus {
long addError(long processingTime);

/**
* Count of batch reports waiting for processing since startup, including reports received before instance startup.
* Number of pending tasks, including tasks received before instance startup.
*/
long getPendingCount();

/**
* Count of batch reports under processing.
* The age, in ms, of the oldest pending task.
*/
Optional<Long> getLongestTimePending();

/**
* Count of tasks under processing.
*/
long getInProgressCount();

/**
* Count of batch reports which processing ended with an error since instance startup.
* Count of tasks which processing ended with an error since instance startup.
*/
long getErrorCount();

/**
* Count of batch reports which processing ended successfully since instance startup.
* Count of tasks which processing ended successfully since instance startup.
*/
long getSuccessCount();

/**
* Time spent processing batch reports since startup, in milliseconds.
* Time spent processing tasks since startup, in milliseconds.
*/
long getProcessingTime();


+ 12
- 1
server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CEQueueStatusImpl.java View File

@@ -21,6 +21,7 @@ package org.sonar.ce.monitoring;

import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.ce.CeQueueDto;
@@ -31,13 +32,15 @@ import static com.google.common.base.Preconditions.checkArgument;
public class CEQueueStatusImpl implements CEQueueStatus {

private final DbClient dbClient;
private final System2 system;
private final AtomicLong inProgress = new AtomicLong(0);
private final AtomicLong error = new AtomicLong(0);
private final AtomicLong success = new AtomicLong(0);
private final AtomicLong processingTime = new AtomicLong(0);

public CEQueueStatusImpl(DbClient dbClient) {
public CEQueueStatusImpl(DbClient dbClient, System2 system) {
this.dbClient = dbClient;
this.system = system;
}

@Override
@@ -71,6 +74,14 @@ public class CEQueueStatusImpl implements CEQueueStatus {
}
}

@Override
public Optional<Long> getLongestTimePending() {
try (DbSession dbSession = dbClient.openSession(false)) {
return dbClient.ceQueueDao().selectCreationDateOfOldestPendingByMainComponentUuid(dbSession, null)
.map(creationDate -> system.now() - creationDate);
}
}

@Override
public boolean areWorkersPaused() {
try (DbSession dbSession = dbClient.openSession(false)) {

+ 11
- 5
server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeTasksMBean.java View File

@@ -20,33 +20,39 @@
package org.sonar.ce.monitoring;

import java.util.List;
import java.util.Optional;

public interface CeTasksMBean {

String OBJECT_NAME = "SonarQube:name=ComputeEngineTasks";

/**
* Count of batch reports waiting for processing since startup, including reports received before instance startup.
* Number of pending tasks, including tasks received before instance startup.
*/
long getPendingCount();

/**
* Count of batch reports under processing.
* The age, in ms, of the oldest pending task.
*/
Optional<Long> getLongestTimePending();

/**
* Count of tasks under processing.
*/
long getInProgressCount();

/**
* Count of batch reports which processing ended with an error since instance startup.
* Count of tasks which processing ended with an error since instance startup.
*/
long getErrorCount();

/**
* Count of batch reports which processing ended successfully since instance startup.
* Count of tasks which processing ended successfully since instance startup.
*/
long getSuccessCount();

/**
* Time spent processing reports since startup, in milliseconds.
* Time spent processing tasks since startup, in milliseconds.
*/
long getProcessingTime();


+ 7
- 0
server/sonar-ce/src/main/java/org/sonar/ce/monitoring/CeTasksMBeanImpl.java View File

@@ -20,6 +20,7 @@
package org.sonar.ce.monitoring;

import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import org.picocontainer.Startable;
@@ -62,6 +63,11 @@ public class CeTasksMBeanImpl implements CeTasksMBean, Startable, SystemInfoSect
return queueStatus.getPendingCount();
}

@Override
public Optional<Long> getLongestTimePending() {
return queueStatus.getLongestTimePending();
}

@Override
public long getInProgressCount() {
return queueStatus.getInProgressCount();
@@ -116,6 +122,7 @@ public class CeTasksMBeanImpl implements CeTasksMBean, Startable, SystemInfoSect
ProtobufSystemInfo.Section.Builder builder = ProtobufSystemInfo.Section.newBuilder();
builder.setName("Compute Engine Tasks");
builder.addAttributesBuilder().setKey("Pending").setLongValue(getPendingCount()).build();
builder.addAttributesBuilder().setKey("Longest Time Pending (ms)").setLongValue(getLongestTimePending().orElse(0L)).build();
builder.addAttributesBuilder().setKey("In Progress").setLongValue(getInProgressCount()).build();
builder.addAttributesBuilder().setKey("Processed With Error").setLongValue(getErrorCount()).build();
builder.addAttributesBuilder().setKey("Processed With Success").setLongValue(getSuccessCount()).build();

+ 3
- 2
server/sonar-ce/src/main/java/org/sonar/ce/monitoring/DistributedCEQueueStatusImpl.java View File

@@ -19,11 +19,12 @@
*/
package org.sonar.ce.monitoring;

import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;

public class DistributedCEQueueStatusImpl extends CEQueueStatusImpl {
public DistributedCEQueueStatusImpl(DbClient dbClient) {
super(dbClient);
public DistributedCEQueueStatusImpl(DbClient dbClient, System2 system2) {
super(dbClient, system2);
}

@Override

+ 2
- 1
server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CEQueueStatusImplConcurrentTest.java View File

@@ -28,6 +28,7 @@ import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;

import static org.assertj.core.api.Assertions.assertThat;
@@ -42,7 +43,7 @@ public class CEQueueStatusImplConcurrentTest {
return new Thread(r, CEQueueStatusImplConcurrentTest.class.getSimpleName() + cnt++);
}
});
private CEQueueStatusImpl underTest = new CEQueueStatusImpl(mock(DbClient.class));
private CEQueueStatusImpl underTest = new CEQueueStatusImpl(mock(DbClient.class), mock(System2.class));

@After
public void tearDown() {

+ 2
- 1
server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CEQueueStatusImplTest.java View File

@@ -21,6 +21,7 @@ package org.sonar.ce.monitoring;

import org.junit.Test;
import org.mockito.Mockito;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;
import org.sonar.db.ce.CeQueueDto;

@@ -31,7 +32,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class CEQueueStatusImplTest extends CommonCEQueueStatusImplTest {
private CEQueueStatusImpl underTest = new CEQueueStatusImpl(getDbClient());
private CEQueueStatusImpl underTest = new CEQueueStatusImpl(getDbClient(), mock(System2.class));

public CEQueueStatusImplTest() {
super(mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS));

+ 10
- 1
server/sonar-ce/src/test/java/org/sonar/ce/monitoring/CeTasksMBeanImplTest.java View File

@@ -22,6 +22,7 @@ package org.sonar.ce.monitoring;
import com.google.common.collect.ImmutableSet;
import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
@@ -46,6 +47,7 @@ import static org.mockito.Mockito.when;

public class CeTasksMBeanImplTest {
private static final long PENDING_COUNT = 2;
private static final Optional<Long> PENDING_TIME = Optional.of(10_000L);
private static final long IN_PROGRESS_COUNT = 5;
private static final long ERROR_COUNT = 10;
private static final long SUCCESS_COUNT = 13;
@@ -91,6 +93,7 @@ public class CeTasksMBeanImplTest {
@Test
public void get_methods_delegate_to_the_CEQueueStatus_instance() {
assertThat(underTest.getPendingCount()).isEqualTo(PENDING_COUNT);
assertThat(underTest.getLongestTimePending()).isEqualTo(PENDING_TIME);
assertThat(underTest.getInProgressCount()).isEqualTo(IN_PROGRESS_COUNT);
assertThat(underTest.getErrorCount()).isEqualTo(ERROR_COUNT);
assertThat(underTest.getSuccessCount()).isEqualTo(SUCCESS_COUNT);
@@ -142,7 +145,7 @@ public class CeTasksMBeanImplTest {
public void export_system_info() {
ProtobufSystemInfo.Section section = underTest.toProtobuf();
assertThat(section.getName()).isEqualTo("Compute Engine Tasks");
assertThat(section.getAttributesCount()).isEqualTo(8);
assertThat(section.getAttributesCount()).isEqualTo(9);
}

private static class DumbCEQueueStatus implements CEQueueStatus {
@@ -152,6 +155,11 @@ public class CeTasksMBeanImplTest {
return PENDING_COUNT;
}

@Override
public Optional<Long> getLongestTimePending() {
return PENDING_TIME;
}

@Override
public long addInProgress() {
return methodNotImplemented();
@@ -197,6 +205,7 @@ public class CeTasksMBeanImplTest {
}

}

private static class DumbCeConfiguration implements CeConfiguration {

@Override

+ 2
- 1
server/sonar-ce/src/test/java/org/sonar/ce/monitoring/DistributedCEQueueStatusImplTest.java View File

@@ -21,6 +21,7 @@ package org.sonar.ce.monitoring;

import org.junit.Test;
import org.mockito.Mockito;
import org.sonar.api.utils.System2;
import org.sonar.db.DbClient;

import static org.assertj.core.api.Assertions.assertThat;
@@ -28,7 +29,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verifyZeroInteractions;

public class DistributedCEQueueStatusImplTest extends CommonCEQueueStatusImplTest {
private DistributedCEQueueStatusImpl underTest = new DistributedCEQueueStatusImpl(getDbClient());
private DistributedCEQueueStatusImpl underTest = new DistributedCEQueueStatusImpl(getDbClient(), mock(System2.class));

public DistributedCEQueueStatusImplTest() {
super(mock(DbClient.class, Mockito.RETURNS_DEEP_STUBS));

+ 1
- 1
server/sonar-ce/src/test/java/org/sonar/ce/queue/InternalCeQueueImplTest.java View File

@@ -80,7 +80,7 @@ public class InternalCeQueueImplTest {
private DbSession session = db.getSession();

private UuidFactory uuidFactory = UuidFactoryImpl.INSTANCE;
private CEQueueStatus queueStatus = new CEQueueStatusImpl(db.getDbClient());
private CEQueueStatus queueStatus = new CEQueueStatusImpl(db.getDbClient(), mock(System2.class));
private DefaultOrganizationProvider defaultOrganizationProvider = mock(DefaultOrganizationProvider.class);
private ComputeEngineStatus computeEngineStatus = mock(ComputeEngineStatus.class);
private InternalCeQueue underTest = new InternalCeQueueImpl(system2, db.getDbClient(), uuidFactory, queueStatus, defaultOrganizationProvider, computeEngineStatus);

+ 4
- 1
server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeQueueDao.java View File

@@ -142,9 +142,12 @@ public class CeQueueDao implements Dao {
return mapper(dbSession).countByStatusAndMainComponentUuid(status, mainComponentUuid);
}

public Optional<Long> selectCreationDateOfOldestPendingByMainComponentUuid(DbSession dbSession, @Nullable String mainComponentUuid) {
return Optional.ofNullable(mapper(dbSession).selectCreationDateOfOldestPendingByMainComponentUuid(mainComponentUuid));
}

/**
* Counts entries in the queue with the specified status for each specified main component uuid.
*
* The returned map doesn't contain any entry for main component uuids for which there is no entry in the queue (ie.
* all entries have a value >= 0).
*/

+ 3
- 0
server/sonar-db-dao/src/main/java/org/sonar/db/ce/CeQueueMapper.java View File

@@ -68,6 +68,9 @@ public interface CeQueueMapper {

int countByStatusAndMainComponentUuid(@Param("status") CeQueueDto.Status status, @Nullable @Param("mainComponentUuid") String mainComponentUuid);

@CheckForNull
Long selectCreationDateOfOldestPendingByMainComponentUuid(@Nullable @Param("mainComponentUuid") String mainComponentUuid);

List<QueueCount> countByStatusAndMainComponentUuids(@Param("status") CeQueueDto.Status status, @Param("mainComponentUuids") List<String> mainComponentUuids);

void insert(CeQueueDto dto);

+ 12
- 0
server/sonar-db-dao/src/main/resources/org/sonar/db/ce/CeQueueMapper.xml View File

@@ -49,6 +49,18 @@
</if>
</select>

<select id="selectCreationDateOfOldestPendingByMainComponentUuid" parameterType="map" resultType="Long">
select
min(created_at)
from
ce_queue
where
status='PENDING'
<if test="mainComponentUuid!=null">
and main_component_uuid=#{mainComponentUuid,jdbcType=VARCHAR}
</if>
</select>

<select id="countByStatusAndMainComponentUuids" resultType="org.sonar.db.ce.QueueCount">
select
main_component_uuid as mainComponentUuid,

+ 61
- 1
server/sonar-db-dao/src/test/java/org/sonar/db/ce/CeQueueDaoTest.java View File

@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Random;
import java.util.function.Consumer;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.junit.Rule;
@@ -172,6 +173,58 @@ public class CeQueueDaoTest {
.containsOnly("p1", "p2", "p3");
}

@Test
public void selectCreationDateOfOldestPendingByMainComponentUuid_on_any_component_returns_date() {
long time = alwaysIncreasingSystem2.now() + 10_000;
insertPending("p1", dto -> {
dto.setCreatedAt(time);
dto.setUpdatedAt(time+500);
dto.setMainComponentUuid("c1");
});
insertPending("p2", dto -> {
dto.setCreatedAt(time + 1000);
dto.setUpdatedAt(time + 2000);
dto.setMainComponentUuid("c2");
});

makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i1", dto -> dto.setMainComponentUuid("c3")));

assertThat(underTest.selectCreationDateOfOldestPendingByMainComponentUuid(db.getSession(), null))
.isEqualTo(Optional.of(time));
}

@Test
public void selectCreationDateOfOldestPendingByMainComponentUuid_on_specific_component_returns_date() {
long time = alwaysIncreasingSystem2.now() + 10_000;
insertPending("p1", dto -> {
dto.setCreatedAt(time);
dto.setUpdatedAt(time+500);
dto.setMainComponentUuid("c2");
});
insertPending("p2", dto -> {
dto.setCreatedAt(time + 2000);
dto.setUpdatedAt(time + 3000);
dto.setMainComponentUuid("c1");
});
insertPending("p3", dto -> {
dto.setCreatedAt(time + 4000);
dto.setUpdatedAt(time + 5000);
dto.setMainComponentUuid("c1");
});

makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i1", dto -> dto.setMainComponentUuid("c1")));

assertThat(underTest.selectCreationDateOfOldestPendingByMainComponentUuid(db.getSession(), "c1"))
.isEqualTo(Optional.of(time+2000));
}

@Test
public void selectCreationDateOfOldestPendingByMainComponentUuid_returns_empty_when_no_pending_tasks() {
makeInProgress("w1", alwaysIncreasingSystem2.now(), insertPending("i1"));
assertThat(underTest.selectCreationDateOfOldestPendingByMainComponentUuid(db.getSession(), null))
.isEmpty();
}

@Test
public void selectWornout_returns_task_pending_with_a_non_null_startedAt() {
insertPending("p1");
@@ -583,11 +636,18 @@ public class CeQueueDaoTest {
}

private CeQueueDto insertPending(String uuid) {
return insertPending(uuid, (Consumer<CeQueueDto>) null);
}

private CeQueueDto insertPending(String uuid, @Nullable Consumer<CeQueueDto> dtoConsumer) {
CeQueueDto dto = new CeQueueDto();
dto.setUuid(uuid);
dto.setTaskType(CeTaskTypes.REPORT);
dto.setStatus(PENDING);
dto.setSubmitterUuid("henri");
if (dtoConsumer != null) {
dtoConsumer.accept(dto);
}
underTestAlwaysIncreasingSystem2.insert(db.getSession(), dto);
db.getSession().commit();
return dto;
@@ -629,7 +689,7 @@ public class CeQueueDaoTest {
}

private void verifyCeQueueStatuses(String taskUuid1, CeQueueDto.Status taskStatus1, String taskUuid2, CeQueueDto.Status taskStatus2) {
verifyCeQueueStatuses(new String[]{taskUuid1, taskUuid2}, new CeQueueDto.Status[]{taskStatus1, taskStatus2});
verifyCeQueueStatuses(new String[] {taskUuid1, taskUuid2}, new CeQueueDto.Status[] {taskStatus1, taskStatus2});
}

private void verifyCeQueueStatuses(String[] taskUuids, CeQueueDto.Status[] statuses) {

+ 27
- 19
server/sonar-server/src/main/java/org/sonar/server/ce/ws/ActivityStatusAction.java View File

@@ -19,10 +19,13 @@
*/
package org.sonar.server.ce.ws;

import com.google.common.base.Optional;
import java.util.Optional;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
@@ -44,18 +47,20 @@ public class ActivityStatusAction implements CeWsAction {
private final UserSession userSession;
private final DbClient dbClient;
private final ComponentFinder componentFinder;
private final System2 system2;

public ActivityStatusAction(UserSession userSession, DbClient dbClient, ComponentFinder componentFinder) {
public ActivityStatusAction(UserSession userSession, DbClient dbClient, ComponentFinder componentFinder, System2 system2) {
this.userSession = userSession;
this.dbClient = dbClient;
this.componentFinder = componentFinder;
this.system2 = system2;
}

@Override
public void define(WebService.NewController controller) {
WebService.NewAction action = controller
.createAction("activity_status")
.setDescription("Return CE activity related metrics.<br>" +
.setDescription("Returns CE activity related metrics.<br>" +
"Requires 'Administer System' permission or 'Administer' rights on the specified project.")
.setSince("5.5")
.setResponseExample(getClass().getResource("activity_status-example.json"))
@@ -70,6 +75,7 @@ public class ActivityStatusAction implements CeWsAction {
.setExampleValue(KeyExamples.KEY_PROJECT_EXAMPLE_001);

action.setChangelog(new Change("6.6", "New field 'inProgress' in response"));
action.setChangelog(new Change("7.8", "New field 'pendingTime' in response, only included when there are pending tasks"));
}

@Override
@@ -81,17 +87,25 @@ public class ActivityStatusAction implements CeWsAction {
private ActivityStatusWsResponse doHandle(Request request) {
try (DbSession dbSession = dbClient.openSession(false)) {
Optional<ComponentDto> component = searchComponent(dbSession, request);
String componentUuid = component.isPresent() ? component.get().uuid() : null;
String componentUuid = component.map(ComponentDto::uuid).orElse(null);
checkPermissions(component);
int pendingCount = dbClient.ceQueueDao().countByStatusAndMainComponentUuid(dbSession, CeQueueDto.Status.PENDING, componentUuid);
int inProgressCount = dbClient.ceQueueDao().countByStatusAndMainComponentUuid(dbSession, CeQueueDto.Status.IN_PROGRESS, componentUuid);
int failingCount = dbClient.ceActivityDao().countLastByStatusAndMainComponentUuid(dbSession, CeActivityDto.Status.FAILED, componentUuid);

return ActivityStatusWsResponse.newBuilder()
Optional<Long> creationDate = dbClient.ceQueueDao().selectCreationDateOfOldestPendingByMainComponentUuid(dbSession, componentUuid);

ActivityStatusWsResponse.Builder builder = ActivityStatusWsResponse.newBuilder()
.setPending(pendingCount)
.setInProgress(inProgressCount)
.setFailing(failingCount)
.build();
.setFailing(failingCount);

creationDate.ifPresent(d -> {
long ageOfOldestPendingTime = system2.now() - d;
builder.setPendingTime(ageOfOldestPendingTime);
});

return builder.build();
}
}

@@ -100,7 +114,7 @@ public class ActivityStatusAction implements CeWsAction {
if (hasComponentInRequest(request)) {
component = componentFinder.getByUuidOrKey(dbSession, request.getComponentId(), request.getComponentKey(), COMPONENT_ID_AND_KEY);
}
return Optional.fromNullable(component);
return Optional.ofNullable(component);
}

private void checkPermissions(Optional<ComponentDto> component) {
@@ -116,30 +130,24 @@ public class ActivityStatusAction implements CeWsAction {
}

private static Request toWsRequest(org.sonar.api.server.ws.Request request) {
return new Request()
.setComponentId(request.param(PARAM_COMPONENT_ID))
.setComponentKey(request.param(DEPRECATED_PARAM_COMPONENT_KEY));
return new Request(request.param(PARAM_COMPONENT_ID), request.param(DEPRECATED_PARAM_COMPONENT_KEY));
}

private static class Request {

private String componentId;
private String componentKey;

public Request setComponentId(String componentId) {
Request(@Nullable String componentId, @Nullable String componentKey) {
this.componentId = componentId;
return this;
this.componentKey = componentKey;
}

@CheckForNull
public String getComponentId() {
return componentId;
}

public Request setComponentKey(String componentKey) {
this.componentKey = componentKey;
return this;
}

@CheckForNull
public String getComponentKey() {
return componentKey;
}

+ 2
- 1
server/sonar-server/src/main/resources/org/sonar/server/ce/ws/activity_status-example.json View File

@@ -1,5 +1,6 @@
{
"pending": 2,
"inProgress": 1,
"failing": 5
"failing": 5,
"pendingTime": 100123
}

+ 34
- 4
server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityStatusActionTest.java View File

@@ -44,6 +44,8 @@ import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.Ce;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.db.ce.CeQueueTesting.newCeQueueDto;
import static org.sonar.db.component.ComponentTesting.newPrivateProjectDto;
import static org.sonar.server.ce.ws.CeWsParameters.DEPRECATED_PARAM_COMPONENT_KEY;
@@ -59,9 +61,11 @@ public class ActivityStatusActionTest {
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);

private System2 system2 = mock(System2.class);

private DbClient dbClient = db.getDbClient();
private DbSession dbSession = db.getSession();
private WsActionTester ws = new WsActionTester(new ActivityStatusAction(userSession, dbClient, TestComponentFinder.from(db)));
private WsActionTester ws = new WsActionTester(new ActivityStatusAction(userSession, dbClient, TestComponentFinder.from(db), system2));

@Test
public void test_definition() {
@@ -74,7 +78,8 @@ public class ActivityStatusActionTest {

@Test
public void json_example() {
dbClient.ceQueueDao().insert(dbSession, newCeQueueDto("ce-queue-uuid-1").setStatus(CeQueueDto.Status.PENDING));
when(system2.now()).thenReturn(200123L);
dbClient.ceQueueDao().insert(dbSession, newCeQueueDto("ce-queue-uuid-1").setStatus(CeQueueDto.Status.PENDING).setCreatedAt(100000));
dbClient.ceQueueDao().insert(dbSession, newCeQueueDto("ce-queue-uuid-2").setStatus(CeQueueDto.Status.PENDING));
dbClient.ceQueueDao().insert(dbSession, newCeQueueDto("ce-queue-uuid-3").setStatus(CeQueueDto.Status.IN_PROGRESS));
for (int i = 0; i < 5; i++) {
@@ -118,6 +123,23 @@ public class ActivityStatusActionTest {
assertThat(result.getFailing()).isEqualTo(1);
}

@Test
public void add_pending_time() {
String projectUuid = "project-uuid";
OrganizationDto organizationDto = db.organizations().insert();
ComponentDto project = newPrivateProjectDto(organizationDto, projectUuid);
db.components().insertComponent(project);

userSession.logIn().addProjectPermission(UserRole.ADMIN, project);
when(system2.now()).thenReturn(2000L);
insertInQueue(CeQueueDto.Status.PENDING, project, 1000L);
Ce.ActivityStatusWsResponse result = call(projectUuid);

assertThat(result).extracting(Ce.ActivityStatusWsResponse::getPending, Ce.ActivityStatusWsResponse::getFailing,
Ce.ActivityStatusWsResponse::getInProgress, Ce.ActivityStatusWsResponse::getPendingTime)
.containsOnly(1, 0, 0, 1000L);
}

@Test
public void empty_status() {
Ce.ActivityStatusWsResponse result = call();
@@ -171,9 +193,17 @@ public class ActivityStatusActionTest {
}

private void insertInQueue(CeQueueDto.Status status, @Nullable ComponentDto componentDto) {
dbClient.ceQueueDao().insert(dbSession, newCeQueueDto(Uuids.createFast())
insertInQueue(status, componentDto, null);
}

private void insertInQueue(CeQueueDto.Status status, @Nullable ComponentDto componentDto, @Nullable Long createdAt) {
CeQueueDto ceQueueDto = newCeQueueDto(Uuids.createFast())
.setStatus(status)
.setComponent(componentDto));
.setComponent(componentDto);
if (createdAt != null) {
ceQueueDto.setCreatedAt(createdAt);
}
dbClient.ceQueueDao().insert(dbSession, ceQueueDto);
db.commit();
}


+ 1
- 0
sonar-ws/src/main/protobuf/ws-ce.proto View File

@@ -49,6 +49,7 @@ message ActivityStatusWsResponse {
optional int32 pending = 1;
optional int32 failing = 2;
optional int32 inProgress = 3;
optional int64 pendingTime = 4;
}

// GET api/ce/analysis_status

Loading…
Cancel
Save