/*
* Copyright 2017 NAVER Corp.
*
* 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 com.navercorp.pinpoint.profiler.monitor.metric.rpc;
import com.navercorp.pinpoint.common.trace.BaseHistogramSchema;
import com.navercorp.pinpoint.common.trace.ServiceTypeCategory;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @author emeroad
*/
public class DefaultAcceptHistogram implements AcceptHistogram {
private final ConcurrentMap<ResponseKey, Histogram> map;
public DefaultAcceptHistogram() {
this.map = new ConcurrentHashMap<ResponseKey, Histogram>();
}
@Override
public boolean addResponseTime(String parentApplicationName, short serviceTypeCode, int millis, boolean error) {
if (parentApplicationName == null) {
throw new NullPointerException("parentApplicationName must not be null");
}
// Cannot compare by ServiceType value because it could be incompatible if new service type is added.
if (!ServiceTypeCategory.SERVER.contains(serviceTypeCode)) {
return false;
}
// TODO As already explained, ServiceType.UNDEFINED is returned if serviceTypeCode is of new service type which is added to newer version.
// How to handle this situation?
// We can infer if we know the type of histogramSchema. Server can determine the server type with code + schemaType.
final ResponseKey responseKey = new ResponseKey(parentApplicationName, serviceTypeCode);
final Histogram histogram = getHistogram(responseKey);
histogram.addResponseTime(millis, error);
return true;
}
private Histogram getHistogram(ResponseKey responseKey) {
final Histogram hit = map.get(responseKey);
if (hit != null) {
return hit;
}
final Histogram histogram = new LongAdderHistogram(responseKey.getServiceType(), BaseHistogramSchema.NORMAL_SCHEMA);
final Histogram old = map.putIfAbsent(responseKey, histogram);
if (old != null) {
return old;
}
return histogram;
}
private static final class ResponseKey {
private final short serviceType;
private final String parentApplicationName;
private ResponseKey(String parentApplicationName, short serviceType) {
if (parentApplicationName == null) {
throw new NullPointerException("parentApplicationName must not be null");
}
this.parentApplicationName = parentApplicationName;
this.serviceType = serviceType;
}
public String getParentApplicationName() {
return parentApplicationName;
}
public short getServiceType() {
return serviceType;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ResponseKey that = (ResponseKey) o;
if (!parentApplicationName.equals(that.parentApplicationName)) return false;
if (serviceType != that.serviceType) return false;
return true;
}
@Override
public int hashCode() {
int result = (int) serviceType;
result = 31 * result + parentApplicationName.hashCode();
return result;
}
}
}