usage-statistics-impl/src/jetbrains/buildServer/usageStatistics/impl/providers/ServerLoadUsageStatisticsProvider.java (180 lines of code) (raw):

package jetbrains.buildServer.usageStatistics.impl.providers; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Set; import jetbrains.buildServer.serverSide.BuildServerEx; import jetbrains.buildServer.serverSide.db.queries.GenericQuery; import jetbrains.buildServer.serverSide.impl.CompositeRunningBuild; import jetbrains.buildServer.usageStatistics.UsageStatisticsPublisher; import jetbrains.buildServer.usageStatistics.presentation.UsageStatisticsFormatter; import jetbrains.buildServer.usageStatistics.presentation.UsageStatisticsGroupPosition; import jetbrains.buildServer.usageStatistics.presentation.UsageStatisticsPresentationManager; import jetbrains.buildServer.usageStatistics.presentation.formatters.PercentageFormatter; import jetbrains.buildServer.usageStatistics.presentation.formatters.TimeFormatter; import jetbrains.buildServer.util.CollectionsUtil; import jetbrains.buildServer.util.positioning.PositionAware; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class ServerLoadUsageStatisticsProvider extends BaseDynamicUsageStatisticsProvider { @NotNull private static final UsageStatisticsFormatter ourTimeFormatter = new TimeFormatter(); @NotNull private static final GenericQuery<Void> ourCompositeBuildsQuery = new GenericQuery<>( "select count(h.build_id) as build_count" + " from (" + " select history.build_id from history where build_finish_time_server > ? and agent_name like '" + CompositeRunningBuild.FAKE_SERVER_AGENT + "'" + " union all" + " select build_id from removed_builds_history where build_finish_time_server > ? and agent_name like '" + CompositeRunningBuild.FAKE_SERVER_AGENT + "'" + " union all" + " select build_id from light_history where build_finish_time_server > ? and agent_name like '" + CompositeRunningBuild.FAKE_SERVER_AGENT + "'" + ") h" ); @NotNull private static final GenericQuery<Void> ourRegularBuildsQuery = new GenericQuery<>( "select" + " count(h.build_id) as build_count," + " sum(h.is_personal) as personal_build_count," + " avg(h.remove_from_queue_time - h.queued_time) as avg_build_queue_time," + " avg(h.build_finish_time_server - h.build_start_time_server) as avg_build_duration" + " from (" + " select history.build_id, history.is_personal,build_finish_time_server,build_start_time_server, history.remove_from_queue_time as remove_from_queue_time, history.queued_time as queued_time" + " from history where build_finish_time_server > ? and agent_name not like '" + CompositeRunningBuild.FAKE_SERVER_AGENT + "'" + " union all" + " select build_id, is_personal,build_finish_time_server,build_start_time_server, remove_from_queue_time, queued_time" + " from removed_builds_history" + " where build_finish_time_server > ? and agent_name not like '" + CompositeRunningBuild.FAKE_SERVER_AGENT + "' " + " union all" + " select build_id, is_personal,build_finish_time_server,build_start_time_server, remove_from_queue_time, queued_time" + " from light_history" + " where build_finish_time_server > ? and agent_name not like '" + CompositeRunningBuild.FAKE_SERVER_AGENT + "' " + ") h" ); @NotNull private static final GenericQuery<Void> ourBuildTestCountQuery = new GenericQuery<>( "select" + " max(s.test_count) as max_test_count" + " from stats s" + " inner join history h on s.build_id = h.build_id" + " where h.build_finish_time_server > ? and agent_name not like '" + CompositeRunningBuild.FAKE_SERVER_AGENT + "'" ); @NotNull private static final GenericQuery<Void> ourVcsChangesCountQuery = new GenericQuery<>( "select count(*) as vcs_changes_count" + " from vcs_history h" + " where register_date > ?" ); @NotNull private final BuildServerEx myServer; @NotNull private final WebUsersProvider myWebUsersProvider; @NotNull private final IDEUsersProvider myIDEUsersProvider; public ServerLoadUsageStatisticsProvider(@NotNull final BuildServerEx server, @NotNull final WebUsersProvider webUsersProvider, @NotNull final IDEUsersProvider ideUsersProvider) { super(createDWMPeriodDescriptions(), null); myServer = server; myWebUsersProvider = webUsersProvider; myIDEUsersProvider = ideUsersProvider; } @NotNull @Override protected PositionAware getGroupPosition() { return UsageStatisticsGroupPosition.SERVER_LOAD; } @Override protected void accept(@NotNull final UsageStatisticsPublisher publisher, @NotNull final UsageStatisticsPresentationManager presentationManager, @NotNull final String periodDescription, final long startDate) { publishBuildData(publisher, presentationManager, periodDescription, startDate); publishOnlineUsers(publisher, presentationManager, periodDescription, startDate); publishVcsChanges(publisher, presentationManager, periodDescription, startDate); } private void publishBuildData(@NotNull final UsageStatisticsPublisher publisher, @NotNull final UsageStatisticsPresentationManager presentationManager, @NotNull final String periodDescription, final long fromDate) { apply(presentationManager, periodDescription, "buildCount", "Build count", null, null); apply(presentationManager, periodDescription, "compositeBuildCount", "Composite build count", null, null); apply(presentationManager, periodDescription, "personalBuildCount", "Personal build count", null, null); apply(presentationManager, periodDescription, "avgBuildWaitInQueueTime", "Average build waiting in queue time", ourTimeFormatter, null); apply(presentationManager, periodDescription, "avgBuildDuration", "Average build duration", ourTimeFormatter, null); apply(presentationManager, periodDescription, "maxBuildTestCount", "Maximum test count per build", null, null); ourRegularBuildsQuery.execute(myServer.getSQLRunner(), rs -> { if (rs.next()) { publish(publisher, periodDescription, "buildCount", rs.getLong(1)); publish(publisher, periodDescription, "personalBuildCount", rs.getLong(2)); publish(publisher, periodDescription, "avgBuildWaitInQueueTime", getNullableLong(rs, 3)); publish(publisher, periodDescription, "avgBuildDuration", getNullableLong(rs, 4)); } return null; }, fromDate, fromDate, fromDate); ourCompositeBuildsQuery.execute(myServer.getSQLRunner(), rs -> { if (rs.next()) { publish(publisher, periodDescription, "compositeBuildCount", rs.getLong(1)); } return null; }, fromDate, fromDate, fromDate); ourBuildTestCountQuery.execute(myServer.getSQLRunner(), rs -> { if (rs.next()) { publish(publisher, periodDescription, "maxBuildTestCount", getNullableLong(rs, 1)); } return null; }, fromDate); } private void publishOnlineUsers(@NotNull final UsageStatisticsPublisher publisher, @NotNull final UsageStatisticsPresentationManager presentationManager, @NotNull final String periodDescription, final long fromDate) { final String webUsersId = "webUsers"; final String ideUsersId = "ideUsers"; final String webOnlyUsersId = "webOnlyUsers"; final String ideOnlyUsersId = "ideOnlyUsers"; final UsageStatisticsFormatter formatter = new PercentageFormatter(myServer.getUserModel().getNumberOfRegisteredUsers()); final String valueTooltip = "User count (% of all users)"; apply(presentationManager, periodDescription, webUsersId, "Web users", formatter, valueTooltip); apply(presentationManager, periodDescription, ideUsersId, "IDE users", formatter, valueTooltip); apply(presentationManager, periodDescription, webOnlyUsersId, "Web only users", formatter, valueTooltip); apply(presentationManager, periodDescription, ideOnlyUsersId, "IDE only users", formatter, valueTooltip); final Set<String> webUsers = myWebUsersProvider.getWebUsers(fromDate); final Set<String> ideUsers = myIDEUsersProvider.getIDEUsers(fromDate); publish(publisher, periodDescription, webUsersId, webUsers.size()); publish(publisher, periodDescription, ideUsersId, ideUsers.size()); publish(publisher, periodDescription, webOnlyUsersId, CollectionsUtil.minus(webUsers, ideUsers).size()); publish(publisher, periodDescription, ideOnlyUsersId, CollectionsUtil.minus(ideUsers, webUsers).size()); } private void publishVcsChanges(@NotNull final UsageStatisticsPublisher publisher, @NotNull final UsageStatisticsPresentationManager presentationManager, @NotNull final String periodDescription, final long fromDate) { final String vcsChangesId = "vcsChanges"; apply(presentationManager, periodDescription, vcsChangesId, "VCS changes", null, null); ourVcsChangesCountQuery.execute(myServer.getSQLRunner(), rs -> { if (rs.next()) { publish(publisher, periodDescription, vcsChangesId, rs.getInt(1)); } return null; }, fromDate); } @Override protected boolean mustSortStatistics() { return false; } @Nullable private Long getNullableLong(final ResultSet rs, final int index) throws SQLException { final long value = rs.getLong(index); return rs.wasNull() ? null : value; } private void apply(@NotNull final UsageStatisticsPresentationManager presentationManager, @NotNull final String periodDescription, @NotNull final String id, @NotNull final String name, @Nullable final UsageStatisticsFormatter formatter, @Nullable final String valueTooltip) { presentationManager.applyPresentation(makeId(id, periodDescription), name, myGroupName, formatter, valueTooltip); } private void publish(@NotNull final UsageStatisticsPublisher publisher, @NotNull final String periodDescription, @NotNull final String id, @Nullable final Object value) { publisher.publishStatistic(makeId(id, periodDescription), value); } }