
org.glowroot.agent.impl.AggregateCollector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of glowroot-agent-it-harness Show documentation
Show all versions of glowroot-agent-it-harness Show documentation
Glowroot Agent Integration Test Harness
/*
* Copyright 2013-2016 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.agent.impl;
import java.io.IOException;
import java.util.List;
import javax.annotation.Nullable;
import org.glowroot.agent.shaded.google.common.collect.Lists;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.glowroot.agent.config.AdvancedConfig;
import org.glowroot.agent.model.CommonTimerImpl;
import org.glowroot.agent.model.Profile;
import org.glowroot.agent.model.ThreadContextImpl;
import org.glowroot.agent.model.ThreadStats;
import org.glowroot.agent.model.TimerImpl;
import org.glowroot.agent.model.Transaction;
import org.glowroot.agent.shaded.glowroot.common.live.ImmutableOverviewAggregate;
import org.glowroot.agent.shaded.glowroot.common.live.ImmutablePercentileAggregate;
import org.glowroot.agent.shaded.glowroot.common.live.ImmutableThroughputAggregate;
import org.glowroot.agent.shaded.glowroot.common.live.LiveAggregateRepository.OverviewAggregate;
import org.glowroot.agent.shaded.glowroot.common.live.LiveAggregateRepository.PercentileAggregate;
import org.glowroot.agent.shaded.glowroot.common.live.LiveAggregateRepository.ThroughputAggregate;
import org.glowroot.agent.shaded.glowroot.common.model.LazyHistogram;
import org.glowroot.agent.shaded.glowroot.common.model.LazyHistogram.ScratchBuffer;
import org.glowroot.agent.shaded.glowroot.common.model.MutableProfile;
import org.glowroot.agent.shaded.glowroot.common.model.OverallErrorSummaryCollector;
import org.glowroot.agent.shaded.glowroot.common.model.OverallSummaryCollector;
import org.glowroot.agent.shaded.glowroot.common.model.ProfileCollector;
import org.glowroot.agent.shaded.glowroot.common.model.QueryCollector;
import org.glowroot.agent.shaded.glowroot.common.model.ServiceCallCollector;
import org.glowroot.agent.shaded.glowroot.common.model.TransactionErrorSummaryCollector;
import org.glowroot.agent.shaded.glowroot.common.model.TransactionSummaryCollector;
import org.glowroot.agent.shaded.glowroot.common.util.NotAvailableAware;
import org.glowroot.agent.shaded.glowroot.common.util.Styles;
import org.glowroot.agent.shaded.glowroot.wire.api.model.AggregateOuterClass.Aggregate;
import org.glowroot.agent.shaded.glowroot.wire.api.model.Proto.OptionalDouble;
import static org.glowroot.agent.shaded.google.common.base.Preconditions.checkNotNull;
// must be used under an appropriate lock
@Styles.Private
class AggregateCollector {
private final @Nullable String transactionName;
private long totalDurationNanos;
private long transactionCount;
private long errorCount;
private boolean asyncTransactions;
private final List mainThreadRootTimers = Lists.newArrayList();
private final List auxThreadRootTimers = Lists.newArrayList();
private final List asyncRootTimers = Lists.newArrayList();
private final MutableThreadStats mainThreadStats = new MutableThreadStats();
private final MutableThreadStats auxThreadStats = new MutableThreadStats();
// histogram values are in nanoseconds, but with microsecond precision to reduce the number of
// buckets (and memory) required
private final LazyHistogram durationNanosHistogram = new LazyHistogram();
// lazy instantiated to reduce memory footprint
private @MonotonicNonNull QueryCollector queries;
private @MonotonicNonNull ServiceCallCollector serviceCalls;
private @MonotonicNonNull MutableProfile mainThreadProfile;
private @MonotonicNonNull MutableProfile auxThreadProfile;
private final int maxAggregateQueriesPerType;
private final int maxAggregateServiceCallsPerType;
AggregateCollector(@Nullable String transactionName, int maxAggregateQueriesPerType,
int maxAggregateServiceCallsPerType) {
this.transactionName = transactionName;
this.maxAggregateQueriesPerType = maxAggregateQueriesPerType;
this.maxAggregateServiceCallsPerType = maxAggregateServiceCallsPerType;
}
void add(Transaction transaction) {
long totalDurationNanos = transaction.getDurationNanos();
this.totalDurationNanos += totalDurationNanos;
transactionCount++;
if (transaction.getErrorMessage() != null) {
errorCount++;
}
if (transaction.isAsync()) {
asyncTransactions = true;
}
this.mainThreadStats.addThreadStats(transaction.getMainThreadStats());
for (ThreadContextImpl auxThreadContext : transaction.getAuxThreadContexts()) {
this.auxThreadStats.addThreadStats(auxThreadContext.getThreadStats());
}
durationNanosHistogram.add(totalDurationNanos);
}
void mergeMainThreadRootTimer(TimerImpl toBeMergedRootTimer) {
mergeRootTimer(toBeMergedRootTimer, mainThreadRootTimers);
}
void mergeAuxThreadRootTimer(TimerImpl toBeMergedRootTimer) {
mergeRootTimer(toBeMergedRootTimer, auxThreadRootTimers);
}
void mergeAsyncRootTimer(CommonTimerImpl toBeMergedRootTimer) {
mergeRootTimer(toBeMergedRootTimer, asyncRootTimers);
}
void mergeMainThreadProfile(Profile toBeMergedProfile) {
if (mainThreadProfile == null) {
mainThreadProfile = new MutableProfile();
}
toBeMergedProfile.mergeIntoProfile(mainThreadProfile);
}
void mergeAuxThreadProfile(Profile toBeMergedProfile) {
if (auxThreadProfile == null) {
auxThreadProfile = new MutableProfile();
}
toBeMergedProfile.mergeIntoProfile(auxThreadProfile);
}
QueryCollector getQueryCollector() {
if (queries == null) {
int queriesHardLimitMultiplierWhileBuilding = transactionName == null
? AdvancedConfig.OVERALL_AGGREGATE_QUERIES_HARD_LIMIT_MULTIPLIER
: AdvancedConfig.TRANSACTION_AGGREGATE_QUERIES_HARD_LIMIT_MULTIPLIER;
queries = new QueryCollector(maxAggregateQueriesPerType,
queriesHardLimitMultiplierWhileBuilding);
}
return queries;
}
ServiceCallCollector getServiceCallCollector() {
if (serviceCalls == null) {
int serviceCallsHardLimitMultiplierWhileBuilding = transactionName == null
? AdvancedConfig.OVERALL_AGGREGATE_SERVICE_CALLS_HARD_LIMIT_MULTIPLIER
: AdvancedConfig.TRANSACTION_AGGREGATE_SERVICE_CALLS_HARD_LIMIT_MULTIPLIER;
serviceCalls = new ServiceCallCollector(maxAggregateServiceCallsPerType,
serviceCallsHardLimitMultiplierWhileBuilding);
}
return serviceCalls;
}
Aggregate build(ScratchBuffer scratchBuffer) throws IOException {
Aggregate.Builder builder = Aggregate.newBuilder()
.setTotalDurationNanos(totalDurationNanos)
.setTransactionCount(transactionCount)
.setErrorCount(errorCount)
.setAsyncTransactions(asyncTransactions)
.addAllMainThreadRootTimer(getRootTimersProtobuf(mainThreadRootTimers))
.addAllAuxThreadRootTimer(getRootTimersProtobuf(auxThreadRootTimers))
.addAllAsyncRootTimer(getRootTimersProtobuf(asyncRootTimers))
.setDurationNanosHistogram(durationNanosHistogram.toProto(scratchBuffer));
if (!mainThreadStats.isNA()) {
builder.setMainThreadStats(mainThreadStats.toProto());
}
if (!auxThreadStats.isNA()) {
builder.setAuxThreadStats(auxThreadStats.toProto());
}
if (queries != null) {
builder.addAllQueriesByType(queries.toProto());
}
if (serviceCalls != null) {
builder.addAllServiceCallsByType(serviceCalls.toProto());
}
if (mainThreadProfile != null) {
builder.setMainThreadProfile(mainThreadProfile.toProto());
}
if (auxThreadProfile != null) {
builder.setAuxThreadProfile(auxThreadProfile.toProto());
}
return builder.build();
}
void mergeInOverallSummary(OverallSummaryCollector collector) {
collector.mergeSummary(totalDurationNanos, transactionCount, 0);
}
void mergeInTransactionSummaries(TransactionSummaryCollector collector) {
checkNotNull(transactionName);
collector.collect(transactionName, totalDurationNanos, transactionCount, 0);
}
void mergeInOverallErrorSummary(OverallErrorSummaryCollector collector) {
collector.mergeErrorSummary(errorCount, transactionCount, 0);
}
void mergeInTransactionErrorSummaries(TransactionErrorSummaryCollector collector) {
checkNotNull(transactionName);
if (errorCount != 0) {
collector.collect(transactionName, errorCount, transactionCount, 0);
}
}
OverviewAggregate getOverviewAggregate(long captureTime) {
ImmutableOverviewAggregate.Builder builder = ImmutableOverviewAggregate.builder()
.captureTime(captureTime)
.totalDurationNanos(totalDurationNanos)
.transactionCount(transactionCount)
.asyncTransactions(asyncTransactions)
.mainThreadRootTimers(getRootTimersProtobuf(mainThreadRootTimers))
.auxThreadRootTimers(getRootTimersProtobuf(auxThreadRootTimers))
.asyncRootTimers(getRootTimersProtobuf(asyncRootTimers));
if (!mainThreadStats.isNA()) {
builder.mainThreadStats(mainThreadStats.toProto());
}
if (!auxThreadStats.isNA()) {
builder.auxThreadStats(auxThreadStats.toProto());
}
return builder.build();
}
PercentileAggregate getPercentileAggregate(long captureTime) {
return ImmutablePercentileAggregate.builder()
.captureTime(captureTime)
.totalDurationNanos(totalDurationNanos)
.transactionCount(transactionCount)
.durationNanosHistogram(durationNanosHistogram.toProto(new ScratchBuffer()))
.build();
}
ThroughputAggregate getThroughputAggregate(long captureTime) {
return ImmutableThroughputAggregate.of(captureTime, transactionCount);
}
void mergeInQueries(QueryCollector collector) throws IOException {
if (queries != null) {
collector.mergeQueries(queries.toProto());
}
}
void mergeInServiceCalls(ServiceCallCollector collector) throws IOException {
if (serviceCalls != null) {
collector.mergeServiceCalls(serviceCalls.toProto());
}
}
void mergeInMainThreadProfiles(ProfileCollector collector) {
if (mainThreadProfile != null) {
collector.mergeProfile(mainThreadProfile.toProto());
}
}
void mergeInAuxThreadProfiles(ProfileCollector collector) {
if (auxThreadProfile != null) {
collector.mergeProfile(auxThreadProfile.toProto());
}
}
private static void mergeRootTimer(CommonTimerImpl toBeMergedRootTimer,
List rootTimers) {
for (MutableTimer rootTimer : rootTimers) {
if (toBeMergedRootTimer.getName().equals(rootTimer.getName())) {
rootTimer.merge(toBeMergedRootTimer);
return;
}
}
MutableTimer rootTimer = MutableTimer.createRootTimer(toBeMergedRootTimer.getName(),
toBeMergedRootTimer.isExtended());
rootTimer.merge(toBeMergedRootTimer);
rootTimers.add(rootTimer);
}
private static List getRootTimersProtobuf(List rootTimers) {
List protobufRootTimers =
Lists.newArrayListWithCapacity(rootTimers.size());
for (MutableTimer rootTimer : rootTimers) {
protobufRootTimers.add(rootTimer.toProto());
}
return protobufRootTimers;
}
private static class MutableThreadStats {
private double totalCpuNanos;
private double totalBlockedNanos;
private double totalWaitedNanos;
private double totalAllocatedBytes;
private boolean empty = true;
private void addThreadStats(ThreadStats threadStats) {
totalCpuNanos = NotAvailableAware.add(totalCpuNanos, threadStats.getTotalCpuNanos());
totalBlockedNanos = NotAvailableAware.addMillisToNanos(totalBlockedNanos,
threadStats.getTotalBlockedMillis());
totalWaitedNanos = NotAvailableAware.addMillisToNanos(totalWaitedNanos,
threadStats.getTotalWaitedMillis());
totalAllocatedBytes = NotAvailableAware.add(totalAllocatedBytes,
threadStats.getTotalAllocatedBytes());
empty = false;
}
private boolean isNA() {
if (empty) {
return true;
}
return NotAvailableAware.isNA(totalCpuNanos)
&& NotAvailableAware.isNA(totalBlockedNanos)
&& NotAvailableAware.isNA(totalWaitedNanos)
&& NotAvailableAware.isNA(totalAllocatedBytes);
}
public Aggregate.ThreadStats toProto() {
Aggregate.ThreadStats.Builder builder = Aggregate.ThreadStats.newBuilder();
if (!NotAvailableAware.isNA(totalCpuNanos)) {
builder.setTotalCpuNanos(toProto(totalCpuNanos));
}
if (!NotAvailableAware.isNA(totalBlockedNanos)) {
builder.setTotalBlockedNanos(toProto(totalBlockedNanos));
}
if (!NotAvailableAware.isNA(totalWaitedNanos)) {
builder.setTotalWaitedNanos(toProto(totalWaitedNanos));
}
if (!NotAvailableAware.isNA(totalAllocatedBytes)) {
builder.setTotalAllocatedBytes(toProto(totalAllocatedBytes));
}
return builder.build();
}
private static OptionalDouble toProto(double value) {
return OptionalDouble.newBuilder().setValue(value).build();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy