All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glowroot.ui.TransactionCommonService Maven / Gradle / Ivy

There is a newer version: 0.9.28
Show newest version
/*
 * Copyright 2014-2015 the original author or authors.
 *
 * Licensed 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.glowroot.ui;

import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;

import org.glowroot.agent.shaded.google.common.collect.Lists;
import org.glowroot.agent.shaded.google.common.collect.Maps;
import org.glowroot.agent.shaded.google.common.collect.Ordering;
import org.glowroot.agent.shaded.google.common.primitives.Doubles;
import org.glowroot.agent.shaded.google.common.primitives.Longs;

import org.glowroot.common.live.ImmutableOverallSummary;
import org.glowroot.common.live.ImmutableThroughputAggregate;
import org.glowroot.common.live.ImmutableTransactionSummary;
import org.glowroot.common.live.LiveAggregateRepository;
import org.glowroot.common.live.LiveAggregateRepository.LiveResult;
import org.glowroot.common.live.LiveAggregateRepository.OverallSummary;
import org.glowroot.common.live.LiveAggregateRepository.OverviewAggregate;
import org.glowroot.common.live.LiveAggregateRepository.PercentileAggregate;
import org.glowroot.common.live.LiveAggregateRepository.ThroughputAggregate;
import org.glowroot.common.live.LiveAggregateRepository.TransactionSummary;
import org.glowroot.common.model.MutableProfileTree;
import org.glowroot.common.model.QueryCollector;
import org.glowroot.storage.repo.AggregateRepository;
import org.glowroot.storage.repo.AggregateRepository.TransactionSummaryQuery;
import org.glowroot.storage.repo.AggregateRepository.TransactionSummarySortOrder;
import org.glowroot.storage.repo.ConfigRepository;
import org.glowroot.storage.repo.ImmutableTransactionSummaryQuery;
import org.glowroot.storage.repo.MutableAggregate;
import org.glowroot.storage.repo.ProfileCollector;
import org.glowroot.storage.repo.Result;
import org.glowroot.storage.repo.Utils;
import org.glowroot.wire.api.model.AggregateOuterClass.Aggregate;
import org.glowroot.wire.api.model.ProfileTreeOuterClass.ProfileTree;

import static org.glowroot.agent.shaded.google.common.base.Preconditions.checkNotNull;

class TransactionCommonService {

    private static final Ordering orderingByTotalTimeDesc =
            new Ordering() {
                @Override
                public int compare(TransactionSummary left, TransactionSummary right) {
                    return Doubles.compare(right.totalNanos(), left.totalNanos());
                }
            };

    private static final Ordering orderingByAverageTimeDesc =
            new Ordering() {
                @Override
                public int compare(TransactionSummary left, TransactionSummary right) {
                    return Doubles.compare(right.totalNanos() / right.transactionCount(),
                            left.totalNanos() / left.transactionCount());
                }
            };

    private static final Ordering orderingByTransactionCountDesc =
            new Ordering() {
                @Override
                public int compare(TransactionSummary left, TransactionSummary right) {
                    return Longs.compare(right.transactionCount(), left.transactionCount());
                }
            };

    private final AggregateRepository aggregateRepository;
    private final LiveAggregateRepository liveAggregateRepository;
    private final ConfigRepository configRepository;

    TransactionCommonService(AggregateRepository aggregateRepository,
            LiveAggregateRepository liveAggregateRepository, ConfigRepository configRepository) {
        this.aggregateRepository = aggregateRepository;
        this.liveAggregateRepository = liveAggregateRepository;
        this.configRepository = configRepository;
    }

    // from is non-inclusive
    OverallSummary readOverallSummary(String serverRollup, String transactionType, long from,
            long to) throws Exception {
        LiveResult liveResult = liveAggregateRepository
                .getLiveOverallSummary(serverRollup, transactionType, from, to);
        if (liveResult == null) {
            return aggregateRepository.readOverallSummary(serverRollup, transactionType, from, to);
        }
        // -1 since query 'to' is inclusive
        // this way don't need to worry about de-dupping between live and stored aggregates
        long revisedTo = liveResult.initialCaptureTime() - 1;
        OverallSummary overallSummary = aggregateRepository.readOverallSummary(serverRollup,
                transactionType, from, revisedTo);
        for (OverallSummary liveOverallSummary : liveResult.get()) {
            overallSummary = combineOverallSummaries(overallSummary, liveOverallSummary);
        }
        return overallSummary;
    }

    // query.from() is non-inclusive
    Result readTransactionSummaries(TransactionSummaryQuery query)
            throws Exception {
        LiveResult> liveResult =
                liveAggregateRepository.getLiveTransactionSummaries(query.serverRollup(),
                        query.transactionType(), query.from(), query.to());
        if (liveResult == null) {
            return aggregateRepository.readTransactionSummaries(query);
        }
        // -1 since query 'to' is inclusive
        // this way don't need to worry about de-dupping between live and stored aggregates
        long revisedTo = liveResult.initialCaptureTime() - 1;
        TransactionSummaryQuery revisedQuery =
                ImmutableTransactionSummaryQuery.builder().copyFrom(query).to(revisedTo).build();
        Result queryResult =
                aggregateRepository.readTransactionSummaries(revisedQuery);

        List transactionSummaries =
                mergeInLiveTransactionSummaries(queryResult.records(), liveResult.get());

        // sort and truncate if necessary
        transactionSummaries = sortTransactionSummaries(transactionSummaries, query.sortOrder());
        boolean moreAvailable = queryResult.moreAvailable();
        if (transactionSummaries.size() > query.limit()) {
            moreAvailable = true;
            transactionSummaries = transactionSummaries.subList(0, query.limit());
        }
        return new Result(transactionSummaries, moreAvailable);
    }

    // from is non-inclusive
    boolean shouldHaveQueries(String serverRollup, String transactionType,
            @Nullable String transactionName, long from, long to) throws Exception {
        if (transactionName == null) {
            return aggregateRepository.shouldHaveOverallQueries(serverRollup, transactionType, from,
                    to);
        } else {
            return aggregateRepository.shouldHaveTransactionQueries(serverRollup, transactionType,
                    transactionName, from, to);
        }
    }

    // from is non-inclusive
    boolean shouldHaveProfile(String serverRollup, String transactionType,
            @Nullable String transactionName, long from, long to) throws Exception {
        if (transactionName == null) {
            return aggregateRepository.shouldHaveOverallProfile(serverRollup, transactionType, from,
                    to);
        } else {
            return aggregateRepository.shouldHaveTransactionProfile(serverRollup, transactionType,
                    transactionName, from, to);
        }
    }

    // from is INCLUSIVE
    List getOverviewAggregates(String serverRollup, String transactionType,
            @Nullable String transactionName, long from, long to, long liveCaptureTime)
                    throws Exception {
        int rollupLevel = aggregateRepository.getRollupLevelForView(serverRollup, from, to);
        LiveResult liveResult =
                liveAggregateRepository.getLiveOverviewAggregates(serverRollup, transactionType,
                        transactionName, from - 1, to, liveCaptureTime);
        // -1 since query 'to' is inclusive
        // this way don't need to worry about de-dupping between live and stored aggregates
        long revisedTo = liveResult == null ? to : liveResult.initialCaptureTime() - 1;
        List aggregates = getOverviewAggregatesFromDao(serverRollup,
                transactionType, transactionName, from, revisedTo, rollupLevel);
        if (rollupLevel == 0) {
            aggregates = Lists.newArrayList(aggregates);
            if (liveResult != null) {
                aggregates.addAll(liveResult.get());
            }
            return aggregates;
        }
        long nonRolledUpFrom = from;
        if (!aggregates.isEmpty()) {
            long lastRolledUpTime = aggregates.get(aggregates.size() - 1).captureTime();
            nonRolledUpFrom = Math.max(nonRolledUpFrom, lastRolledUpTime + 1);
        }
        List orderedNonRolledUpAggregates = Lists.newArrayList();
        orderedNonRolledUpAggregates.addAll(getOverviewAggregatesFromDao(serverRollup,
                transactionType, transactionName, nonRolledUpFrom, revisedTo, 0));
        if (liveResult != null) {
            orderedNonRolledUpAggregates.addAll(liveResult.get());
        }
        aggregates = Lists.newArrayList(aggregates);
        aggregates.addAll(rollUpOverviewAggregates(orderedNonRolledUpAggregates, liveCaptureTime,
                rollupLevel));
        return aggregates;
    }

    // from is INCLUSIVE
    List getPercentileAggregates(String serverRollup, String transactionType,
            @Nullable String transactionName, long from, long to, long liveCaptureTime)
                    throws Exception {
        int rollupLevel = aggregateRepository.getRollupLevelForView(serverRollup, from, to);
        LiveResult liveResult =
                liveAggregateRepository.getLivePercentileAggregates(serverRollup, transactionType,
                        transactionName, from - 1, to, liveCaptureTime);
        // -1 since query 'to' is inclusive
        // this way don't need to worry about de-dupping between live and stored aggregates
        long revisedTo = liveResult == null ? to : liveResult.initialCaptureTime() - 1;
        List aggregates = getPercentileAggregatesFromDao(serverRollup,
                transactionType, transactionName, from, revisedTo, rollupLevel);
        if (rollupLevel == 0) {
            aggregates = Lists.newArrayList(aggregates);
            if (liveResult != null) {
                aggregates.addAll(liveResult.get());
            }
            return aggregates;
        }
        long nonRolledUpFrom = from;
        if (!aggregates.isEmpty()) {
            long lastRolledUpTime = aggregates.get(aggregates.size() - 1).captureTime();
            nonRolledUpFrom = Math.max(nonRolledUpFrom, lastRolledUpTime + 1);
        }
        List orderedNonRolledUpAggregates = Lists.newArrayList();
        orderedNonRolledUpAggregates.addAll(getPercentileAggregatesFromDao(serverRollup,
                transactionType, transactionName, nonRolledUpFrom, revisedTo, 0));
        if (liveResult != null) {
            orderedNonRolledUpAggregates.addAll(liveResult.get());
        }
        aggregates = Lists.newArrayList(aggregates);
        aggregates.addAll(rollUpPercentileAggregates(orderedNonRolledUpAggregates, liveCaptureTime,
                rollupLevel));
        return aggregates;
    }

    // from is INCLUSIVE
    List getThroughputAggregates(String serverRollup, String transactionType,
            @Nullable String transactionName, long from, long to, long liveCaptureTime)
                    throws Exception {
        int rollupLevel = aggregateRepository.getRollupLevelForView(serverRollup, from, to);
        LiveResult liveResult =
                liveAggregateRepository.getLiveThroughputAggregates(serverRollup, transactionType,
                        transactionName, from - 1, to, liveCaptureTime);
        // -1 since query 'to' is inclusive
        // this way don't need to worry about de-dupping between live and stored aggregates
        long revisedTo = liveResult == null ? to : liveResult.initialCaptureTime() - 1;
        List aggregates = getThroughputAggregatesFromDao(serverRollup,
                transactionType, transactionName, from, revisedTo, rollupLevel);
        if (rollupLevel == 0) {
            aggregates = Lists.newArrayList(aggregates);
            if (liveResult != null) {
                aggregates.addAll(liveResult.get());
            }
            return aggregates;
        }
        long nonRolledUpFrom = from;
        if (!aggregates.isEmpty()) {
            long lastRolledUpTime = aggregates.get(aggregates.size() - 1).captureTime();
            nonRolledUpFrom = Math.max(nonRolledUpFrom, lastRolledUpTime + 1);
        }
        List orderedNonRolledUpAggregates = Lists.newArrayList();
        orderedNonRolledUpAggregates.addAll(getThroughputAggregatesFromDao(serverRollup,
                transactionType, transactionName, nonRolledUpFrom, revisedTo, 0));
        if (liveResult != null) {
            orderedNonRolledUpAggregates.addAll(liveResult.get());
        }
        aggregates = Lists.newArrayList(aggregates);
        aggregates.addAll(rollUpThroughputAggregates(orderedNonRolledUpAggregates, liveCaptureTime,
                rollupLevel));
        return aggregates;
    }

    // from is non-inclusive
    MutableProfileTree getMergedProfile(String serverRollup, String transactionType,
            @Nullable String transactionName, long from, long to, List includes,
            List excludes, double truncateBranchPercentage) throws Exception {
        MutableProfileTree profileTree =
                getMergedProfile(serverRollup, transactionType, transactionName, from, to);
        if (!includes.isEmpty() || !excludes.isEmpty()) {
            profileTree.filter(includes, excludes);
        }
        if (truncateBranchPercentage != 0) {
            int minSamples =
                    (int) Math.ceil(profileTree.getSampleCount() * truncateBranchPercentage / 100);
            // don't truncate any root nodes
            profileTree.truncateBranches(minSamples);
        }
        return profileTree;
    }

    // from is non-inclusive
    List getMergedQueries(String serverRollup, String transactionType,
            @Nullable String transactionName, long from, long to) throws Exception {
        return getMergedQueries(serverRollup, transactionType, transactionName, from, to,
                configRepository.getAdvancedConfig(serverRollup).maxAggregateQueriesPerQueryType());
    }

    // from is INCLUSIVE
    private List getOverviewAggregatesFromDao(String serverRollup,
            String transactionType, @Nullable String transactionName, long from, long to,
            int rollupLevel) throws Exception {
        if (transactionName == null) {
            return aggregateRepository.readOverallOverviewAggregates(serverRollup, transactionType,
                    from, to, rollupLevel);
        } else {
            return aggregateRepository.readTransactionOverviewAggregates(serverRollup,
                    transactionType, transactionName, from, to, rollupLevel);
        }
    }

    // from is INCLUSIVE
    private List getPercentileAggregatesFromDao(String serverRollup,
            String transactionType, @Nullable String transactionName, long from, long to,
            int rollupLevel) throws Exception {
        if (transactionName == null) {
            return aggregateRepository.readOverallPercentileAggregates(serverRollup,
                    transactionType, from, to, rollupLevel);
        } else {
            return aggregateRepository.readTransactionPercentileAggregates(serverRollup,
                    transactionType, transactionName, from, to, rollupLevel);
        }
    }

    // from is INCLUSIVE
    private List getThroughputAggregatesFromDao(String serverRollup,
            String transactionType, @Nullable String transactionName, long from, long to,
            int rollupLevel) throws Exception {
        if (transactionName == null) {
            return aggregateRepository.readOverallThroughputAggregates(serverRollup,
                    transactionType, from, to, rollupLevel);
        } else {
            return aggregateRepository.readTransactionThroughputAggregates(serverRollup,
                    transactionType, transactionName, from, to, rollupLevel);
        }
    }

    // this method may return some rolled up profile aggregates and some non-rolled up
    // they are all distinct though
    // this is ok since the results of this method are currently just aggregated into single
    // result as opposed to charted over time period
    //
    // from is non-inclusive
    private MutableProfileTree getMergedProfile(String serverRollup, String transactionType,
            @Nullable String transactionName, long from, long to) throws Exception {
        int initialRollupLevel = aggregateRepository.getRollupLevelForView(serverRollup, from, to);
        LiveResult liveResult = liveAggregateRepository
                .getLiveProfileTree(serverRollup, transactionType, transactionName, from, to);
        // -1 since query 'to' is inclusive
        // this way don't need to worry about de-dupping between live and stored aggregates
        long revisedTo = liveResult == null ? to : liveResult.initialCaptureTime() - 1;
        long revisedFrom = from;
        ProfileCollector mergedProfile = new ProfileCollector();
        for (int rollupLevel = initialRollupLevel; rollupLevel >= 0; rollupLevel--) {
            mergeInProfileFromDao(mergedProfile, serverRollup, transactionType, transactionName,
                    revisedFrom, revisedTo, rollupLevel);
            long lastRolledUpTime = mergedProfile.getLastCaptureTime();
            revisedFrom = Math.max(revisedFrom, lastRolledUpTime + 1);
            if (revisedFrom > revisedTo) {
                break;
            }
        }
        if (liveResult != null) {
            for (ProfileTree profileTree : liveResult.get()) {
                mergedProfile.mergeProfileTree(profileTree);
            }
        }
        return mergedProfile.getProfileTree();
    }

    // this method may return some rolled up query aggregates and some non-rolled up
    // they are all distinct though
    // this is ok since the results of this method are currently just aggregated into single
    // result as opposed to charted over time period
    //
    // from is non-inclusive
    private List getMergedQueries(String serverRollup,
            String transactionType, @Nullable String transactionName, long from, long to,
            int maxAggregateQueriesPerQueryType) throws Exception {
        int initialRollupLevel = aggregateRepository.getRollupLevelForView(serverRollup, from, to);
        LiveResult> liveResult = liveAggregateRepository
                .getLiveQueries(serverRollup, transactionType, transactionName, from, to);
        // -1 since query 'to' is inclusive
        // this way don't need to worry about de-dupping between live and stored aggregates
        long revisedTo = liveResult == null ? to : liveResult.initialCaptureTime() - 1;
        long revisedFrom = from;
        QueryCollector mergedQueries = new QueryCollector(maxAggregateQueriesPerQueryType, 0);
        for (int rollupLevel = initialRollupLevel; rollupLevel >= 0; rollupLevel--) {
            mergeInQueriesFromDao(mergedQueries, serverRollup, transactionType, transactionName,
                    from, revisedTo, rollupLevel);
            long lastRolledUpTime = mergedQueries.getLastCaptureTime();
            revisedFrom = Math.max(revisedFrom, lastRolledUpTime + 1);
            if (revisedFrom > revisedTo) {
                break;
            }
        }
        if (liveResult != null) {
            for (List queries : liveResult.get()) {
                mergedQueries.mergeQueries(queries);
            }
        }
        return mergedQueries.toProtobuf(true);
    }

    // from is non-inclusive
    private void mergeInProfileFromDao(ProfileCollector mergedProfile, String serverRollup,
            String transactionType, @Nullable String transactionName, long from, long to,
            int rollupLevel) throws Exception {
        if (transactionName == null) {
            aggregateRepository.mergeInOverallProfiles(mergedProfile, serverRollup, transactionType,
                    from, to, rollupLevel);
        } else {
            aggregateRepository.mergeInTransactionProfiles(mergedProfile, serverRollup,
                    transactionType, transactionName, from, to, rollupLevel);
        }
    }

    // from is non-inclusive
    private void mergeInQueriesFromDao(QueryCollector mergedQueries, String serverRollup,
            String transactionType, @Nullable String transactionName, long from, long to,
            int rollupLevel) throws Exception {
        if (transactionName == null) {
            aggregateRepository.mergeInOverallQueries(mergedQueries, serverRollup, transactionType,
                    from, to, rollupLevel);
        } else {
            aggregateRepository.mergeInTransactionQueries(mergedQueries, serverRollup,
                    transactionType, transactionName, from, to, rollupLevel);
        }
    }

    private List rollUpOverviewAggregates(
            List orderedNonRolledUpOverviewAggregates, long liveCaptureTime,
            int rollupLevel) throws Exception {
        long fixedIntervalMillis =
                configRepository.getRollupConfigs().get(rollupLevel).intervalMillis();
        List rolledUpOverviewAggregates = Lists.newArrayList();
        MutableAggregate currMergedAggregate = null;
        long currRollupTime = Long.MIN_VALUE;
        for (OverviewAggregate nonRolledUpOverviewAggregate : orderedNonRolledUpOverviewAggregates) {
            long rollupTime = Utils.getNextRollupTime(nonRolledUpOverviewAggregate.captureTime(),
                    fixedIntervalMillis);
            if (rollupTime != currRollupTime && currMergedAggregate != null) {
                rolledUpOverviewAggregates.add(currMergedAggregate
                        .toOverviewAggregate(Math.min(currRollupTime, liveCaptureTime)));
                currMergedAggregate = new MutableAggregate(0);
            }
            if (currMergedAggregate == null) {
                currMergedAggregate = new MutableAggregate(0);
            }
            currRollupTime = rollupTime;
            currMergedAggregate.addTotalNanos(nonRolledUpOverviewAggregate.totalNanos());
            currMergedAggregate
                    .addTransactionCount(nonRolledUpOverviewAggregate.transactionCount());
            currMergedAggregate.addTotalCpuNanos(nonRolledUpOverviewAggregate.totalCpuNanos());
            currMergedAggregate
                    .addTotalBlockedNanos(nonRolledUpOverviewAggregate.totalBlockedNanos());
            currMergedAggregate
                    .addTotalWaitedNanos(nonRolledUpOverviewAggregate.totalWaitedNanos());
            currMergedAggregate
                    .addTotalAllocatedBytes(nonRolledUpOverviewAggregate.totalAllocatedBytes());
            currMergedAggregate.mergeRootTimers(nonRolledUpOverviewAggregate.rootTimers());
        }
        if (currMergedAggregate != null) {
            // roll up final one
            rolledUpOverviewAggregates.add(currMergedAggregate
                    .toOverviewAggregate(Math.min(currRollupTime, liveCaptureTime)));
        }
        return rolledUpOverviewAggregates;
    }

    private List rollUpPercentileAggregates(
            List orderedNonRolledUpPercentileAggregates, long liveCaptureTime,
            int rollupLevel) throws Exception {
        long fixedIntervalMillis =
                configRepository.getRollupConfigs().get(rollupLevel).intervalMillis();
        List rolledUpPercentileAggregates = Lists.newArrayList();
        MutableAggregate currMergedAggregate = null;
        long currRollupTime = Long.MIN_VALUE;
        for (PercentileAggregate nonRolledUpPercentileAggregate : orderedNonRolledUpPercentileAggregates) {
            long rollupTime = Utils.getNextRollupTime(nonRolledUpPercentileAggregate.captureTime(),
                    fixedIntervalMillis);
            if (rollupTime != currRollupTime && currMergedAggregate != null) {
                rolledUpPercentileAggregates.add(currMergedAggregate
                        .toPercentileAggregate(Math.min(currRollupTime, liveCaptureTime)));
                currMergedAggregate = new MutableAggregate(0);
            }
            if (currMergedAggregate == null) {
                currMergedAggregate = new MutableAggregate(0);
            }
            currRollupTime = rollupTime;
            currMergedAggregate.addTotalNanos(nonRolledUpPercentileAggregate.totalNanos());
            currMergedAggregate
                    .addTransactionCount(nonRolledUpPercentileAggregate.transactionCount());
            currMergedAggregate.mergeHistogram(nonRolledUpPercentileAggregate.histogram());
        }
        if (currMergedAggregate != null) {
            // roll up final one
            rolledUpPercentileAggregates.add(currMergedAggregate
                    .toPercentileAggregate(Math.min(currRollupTime, liveCaptureTime)));
        }
        return rolledUpPercentileAggregates;
    }

    private List rollUpThroughputAggregates(
            List orderedNonRolledUpThroughputAggregates, long liveCaptureTime,
            int rollupLevel) throws Exception {
        long fixedIntervalMillis =
                configRepository.getRollupConfigs().get(rollupLevel).intervalMillis();
        List rolledUpThroughputAggregates = Lists.newArrayList();
        long currTransactionCount = 0;
        long currRollupTime = Long.MIN_VALUE;
        for (ThroughputAggregate nonRolledUpThroughputAggregate : orderedNonRolledUpThroughputAggregates) {
            long rollupTime = Utils.getNextRollupTime(nonRolledUpThroughputAggregate.captureTime(),
                    fixedIntervalMillis);
            if (rollupTime != currRollupTime && currTransactionCount != 0) {
                rolledUpThroughputAggregates.add(ImmutableThroughputAggregate
                        .of(Math.min(currRollupTime, liveCaptureTime), currTransactionCount));
                currTransactionCount = 0;
            }
            currRollupTime = rollupTime;
            currTransactionCount += nonRolledUpThroughputAggregate.transactionCount();
        }
        if (currTransactionCount != 0) {
            // roll up final one
            rolledUpThroughputAggregates.add(ImmutableThroughputAggregate
                    .of(Math.min(currRollupTime, liveCaptureTime), currTransactionCount));
        }
        return rolledUpThroughputAggregates;
    }

    private static List mergeInLiveTransactionSummaries(
            List transactionSummaries,
            List> liveTransactionSummaries) {
        Map transactionSummaryMap = Maps.newHashMap();
        for (TransactionSummary transactionSummary : transactionSummaries) {
            String transactionName = transactionSummary.transactionName();
            // transaction name is only null for overall summary
            checkNotNull(transactionName);
            transactionSummaryMap.put(transactionName, transactionSummary);
        }
        for (List mid : liveTransactionSummaries) {
            for (TransactionSummary liveTransactionSummary : mid) {
                String transactionName = liveTransactionSummary.transactionName();
                // transaction name is only null for overall summary
                checkNotNull(transactionName);
                TransactionSummary transactionSummary = transactionSummaryMap.get(transactionName);
                if (transactionSummary == null) {
                    transactionSummaryMap.put(transactionName, liveTransactionSummary);
                } else {
                    transactionSummaryMap.put(transactionName, combineTransactionSummaries(
                            transactionName, transactionSummary, liveTransactionSummary));
                }
            }
        }
        return Lists.newArrayList(transactionSummaryMap.values());
    }

    private static OverallSummary combineOverallSummaries(OverallSummary summary1,
            OverallSummary summary2) {
        return ImmutableOverallSummary.builder()
                .totalNanos(summary1.totalNanos() + summary2.totalNanos())
                .transactionCount(summary1.transactionCount() + summary2.transactionCount())
                .build();
    }

    private static TransactionSummary combineTransactionSummaries(String transactionName,
            TransactionSummary summary1, TransactionSummary summary2) {
        return ImmutableTransactionSummary.builder()
                .transactionName(transactionName)
                .totalNanos(summary1.totalNanos() + summary2.totalNanos())
                .transactionCount(summary1.transactionCount() + summary2.transactionCount())
                .build();
    }

    private static List sortTransactionSummaries(
            Iterable transactionSummaries,
            TransactionSummarySortOrder sortOrder) {
        switch (sortOrder) {
            case TOTAL_TIME:
                return orderingByTotalTimeDesc.immutableSortedCopy(transactionSummaries);
            case AVERAGE_TIME:
                return orderingByAverageTimeDesc.immutableSortedCopy(transactionSummaries);
            case THROUGHPUT:
                return orderingByTransactionCountDesc.immutableSortedCopy(transactionSummaries);
            default:
                throw new AssertionError("Unexpected sort order: " + sortOrder);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy