org.glowroot.agent.model.ServiceCallCollector 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 2016-2018 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.model;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import org.glowroot.agent.shaded.org.glowroot.agent.it.harness.shaded.com.google.common.collect.Lists;
import org.glowroot.agent.shaded.org.glowroot.agent.it.harness.shaded.com.google.common.collect.Maps;
import org.glowroot.agent.shaded.org.glowroot.agent.it.harness.shaded.com.google.common.primitives.Doubles;
import org.glowroot.agent.shaded.org.glowroot.wire.api.model.AggregateOuterClass.Aggregate;
public class ServiceCallCollector {
private static final String LIMIT_EXCEEDED_BUCKET = "LIMIT EXCEEDED BUCKET";
// first key is the service call type, second key is the service call text
private final Map> serviceCalls = Maps.newHashMap();
private final Map limitExceededBuckets = Maps.newHashMap();
private final int limit;
private final int hardLimitMultiplierWhileBuilding;
private int serviceCallCount;
public ServiceCallCollector(int limit, int hardLimitMultiplierWhileBuilding) {
this.limit = limit;
this.hardLimitMultiplierWhileBuilding = hardLimitMultiplierWhileBuilding;
}
public List toAggregateProto() {
// " + serviceCalls.size()" is to cover the maximum number of limit exceeded buckets
List allServiceCalls = Lists
.newArrayListWithCapacity(Math.min(serviceCallCount, limit) + serviceCalls.size());
for (Map.Entry> outerEntry : serviceCalls
.entrySet()) {
for (Map.Entry innerEntry : outerEntry.getValue()
.entrySet()) {
allServiceCalls.add(innerEntry.getValue().toAggregateProto(outerEntry.getKey(),
innerEntry.getKey()));
}
}
if (allServiceCalls.size() <= limit) {
// there could be limit exceeded buckets if hardLimitMultiplierWhileBuilding is 1
for (Map.Entry entry : limitExceededBuckets.entrySet()) {
allServiceCalls.add(
entry.getValue().toAggregateProto(entry.getKey(), LIMIT_EXCEEDED_BUCKET));
}
sort(allServiceCalls);
return allServiceCalls;
}
sort(allServiceCalls);
List exceededServiceCalls =
allServiceCalls.subList(limit, allServiceCalls.size());
allServiceCalls = Lists.newArrayList(allServiceCalls.subList(0, limit));
// do not modify original limit exceeded buckets since adding exceeded queries below
Map limitExceededBuckets = copyLimitExceededBuckets();
for (Aggregate.ServiceCall exceededServiceCall : exceededServiceCalls) {
String queryType = exceededServiceCall.getType();
MutableServiceCall limitExceededBucket = limitExceededBuckets.get(queryType);
if (limitExceededBucket == null) {
limitExceededBucket = new MutableServiceCall();
limitExceededBuckets.put(queryType, limitExceededBucket);
}
limitExceededBucket.add(exceededServiceCall);
}
for (Map.Entry entry : limitExceededBuckets.entrySet()) {
allServiceCalls
.add(entry.getValue().toAggregateProto(entry.getKey(), LIMIT_EXCEEDED_BUCKET));
}
// need to re-sort now including limit exceeded bucket
sort(allServiceCalls);
return allServiceCalls;
}
public void mergeServiceCall(String serviceCallType, String serviceCallText,
double totalDurationNanos, long executionCount) {
Map serviceCallsForType = serviceCalls.get(serviceCallType);
if (serviceCallsForType == null) {
serviceCallsForType = Maps.newHashMap();
serviceCalls.put(serviceCallType, serviceCallsForType);
}
MutableServiceCall aggregateServiceCall = serviceCallsForType.get(serviceCallText);
if (aggregateServiceCall == null) {
if (serviceCallCount < limit * hardLimitMultiplierWhileBuilding) {
aggregateServiceCall = new MutableServiceCall();
serviceCallsForType.put(serviceCallText, aggregateServiceCall);
serviceCallCount++;
} else {
aggregateServiceCall = getOrCreateLimitExceededBucket(serviceCallType);
}
}
aggregateServiceCall.addToTotalDurationNanos(totalDurationNanos);
aggregateServiceCall.addToExecutionCount(executionCount);
}
public void mergeServiceCallsInto(ServiceCallCollector collector) {
for (Map.Entry> outerEntry : serviceCalls
.entrySet()) {
for (Map.Entry entry : outerEntry.getValue().entrySet()) {
MutableServiceCall serviceCall = entry.getValue();
collector.mergeServiceCall(outerEntry.getKey(), entry.getKey(),
serviceCall.getTotalDurationNanos(), serviceCall.getExecutionCount());
}
}
for (Map.Entry limitExceededBucket : limitExceededBuckets
.entrySet()) {
collector.mergeLimitExceededBucket(limitExceededBucket.getKey(),
limitExceededBucket.getValue());
}
}
public void mergeServiceCallsInto(org.glowroot.agent.shaded.org.glowroot.common.model.ServiceCallCollector collector) {
for (Map.Entry> outerEntry : serviceCalls
.entrySet()) {
for (Map.Entry entry : outerEntry.getValue().entrySet()) {
MutableServiceCall serviceCall = entry.getValue();
collector.mergeServiceCall(outerEntry.getKey(), entry.getKey(),
serviceCall.getTotalDurationNanos(), serviceCall.getExecutionCount());
}
}
for (Map.Entry limitExceededBucket : limitExceededBuckets
.entrySet()) {
MutableServiceCall serviceCall = limitExceededBucket.getValue();
collector.mergeServiceCall(limitExceededBucket.getKey(), LIMIT_EXCEEDED_BUCKET,
serviceCall.getTotalDurationNanos(), serviceCall.getExecutionCount());
}
}
private void mergeLimitExceededBucket(String serviceCallType,
MutableServiceCall limitExceededBucket) {
MutableServiceCall serviceCall = getOrCreateLimitExceededBucket(serviceCallType);
serviceCall.add(limitExceededBucket);
}
private MutableServiceCall getOrCreateLimitExceededBucket(String serviceCallType) {
MutableServiceCall serviceCall = limitExceededBuckets.get(serviceCallType);
if (serviceCall == null) {
serviceCall = new MutableServiceCall();
limitExceededBuckets.put(serviceCallType, serviceCall);
}
return serviceCall;
}
private Map copyLimitExceededBuckets() {
Map copies = Maps.newHashMap();
for (Map.Entry entry : limitExceededBuckets.entrySet()) {
String serviceCallType = entry.getKey();
MutableServiceCall limitExceededBucket = entry.getValue();
MutableServiceCall copy = new MutableServiceCall();
copy.add(limitExceededBucket);
copies.put(serviceCallType, copy);
}
return copies;
}
private static void sort(List serviceCalls) {
// reverse sort by total
Collections.sort(serviceCalls, new Comparator() {
@Override
public int compare(Aggregate.ServiceCall left, Aggregate.ServiceCall right) {
return Doubles.compare(right.getTotalDurationNanos(), left.getTotalDurationNanos());
}
});
}
}