Skip to content

Commit

Permalink
[#8843] Add time series Apdex score chart
Browse files Browse the repository at this point in the history
  • Loading branch information
donghun-cho committed May 12, 2022
1 parent 3d7cb17 commit e91a302
Show file tree
Hide file tree
Showing 18 changed files with 1,084 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,23 @@

package com.navercorp.pinpoint.web.applicationmap.histogram;

import com.navercorp.pinpoint.common.trace.ServiceType;
import com.navercorp.pinpoint.web.applicationmap.rawdata.AgentHistogram;
import com.navercorp.pinpoint.web.applicationmap.rawdata.AgentHistogramList;
import com.navercorp.pinpoint.web.util.TimeWindow;
import com.navercorp.pinpoint.web.view.AgentResponseTimeViewModel;
import com.navercorp.pinpoint.web.view.TimeViewModel;
import com.navercorp.pinpoint.web.vo.Application;
import com.navercorp.pinpoint.common.server.util.time.Range;

import com.navercorp.pinpoint.web.vo.stat.SampledApdexScore;
import com.navercorp.pinpoint.web.vo.stat.chart.agent.AgentStatPoint;
import com.navercorp.pinpoint.web.vo.stat.chart.application.DoubleApplicationStatPoint;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
Expand All @@ -36,6 +44,9 @@
*/
public class AgentTimeHistogram {

private static final Double DEFAULT_MIN_APDEX_SCORE = 2D;
private static final Double DEFAULT_MAX_APDEX_SCORE = -2D;
private static final String DEFAULT_AGENT_ID = "defaultAgentId";
private static final Comparator<AgentResponseTimeViewModel> AGENT_NAME_COMPARATOR
= Comparator.comparing(AgentResponseTimeViewModel::getAgentName);

Expand Down Expand Up @@ -83,4 +94,91 @@ private AgentResponseTimeViewModel createAgentResponseTimeViewModel(Application
private List<TimeViewModel> createResponseTimeViewModel(List<TimeHistogram> timeHistogramList, TimeHistogramFormat timeHistogramFormat) {
return new TimeViewModel.TimeViewModelBuilder(application, timeHistogramList).setTimeHistogramFormat(timeHistogramFormat).build();
}

public List<SampledApdexScore> getSampledAgentApdexScoreList(String agentName) {
AgentHistogram agentHistogram = selectAgentHistogram(agentName);
if (agentHistogram == null) {
return Collections.emptyList();
}

List<SampledApdexScore> result = new ArrayList<>();
for(TimeHistogram timeHistogram : agentHistogram.getTimeHistogram()) {
if (timeHistogram.getTotalCount() != 0) {
AgentStatPoint<Double> agentStatPoint = new AgentStatPoint(timeHistogram.getTimeStamp(), ApdexScore.toDoubleFromHistogram(timeHistogram));
result.add(new SampledApdexScore(agentStatPoint));
}
}
return result;
}

private AgentHistogram selectAgentHistogram(String agentName) {
for (AgentHistogram agentHistogram : agentHistogramList.getAgentHistogramList()) {
Application agentId = agentHistogram.getAgentId();
if (agentId.getName().equals(agentName)){
return agentHistogram;
}
}
return null;
}

public List<DoubleApplicationStatPoint> getApplicationApdexScoreList(TimeWindow window) {
int size = (int) window.getWindowRangeCount();
List<Double> min = new ArrayList<>(Arrays.asList(new Double[size]));
List<String> minAgentId = new ArrayList<>(Arrays.asList(new String[size]));
List<Double> max = new ArrayList<>(Arrays.asList(new Double[size]));
List<String> maxAgentId = new ArrayList<>(Arrays.asList(new String[size]));
Collections.fill(min, DEFAULT_MIN_APDEX_SCORE);
Collections.fill(minAgentId, DEFAULT_AGENT_ID);
Collections.fill(max, DEFAULT_MAX_APDEX_SCORE);
Collections.fill(maxAgentId, DEFAULT_AGENT_ID);
List<Histogram> sumHistogram = getDefaultHistograms(window, application.getServiceType());

for (AgentHistogram agentHistogram : agentHistogramList.getAgentHistogramList()) {
for (TimeHistogram timeHistogram: agentHistogram.getTimeHistogram()){
if (timeHistogram.getTotalCount() != 0){
int index = window.getWindowIndex(timeHistogram.getTimeStamp());
double apdex = ApdexScore.toDoubleFromHistogram(timeHistogram);
String agentId = agentHistogram.getId();

updateMinMaxValue(index, apdex, agentId, min, minAgentId, max, maxAgentId);
sumHistogram.get(index).add(timeHistogram);
}
}
}

return createDoubleApplicationStatPoints(window, min, minAgentId, max, maxAgentId, sumHistogram);
}

private void updateMinMaxValue(int index, double apdex, String agentId,
List<Double> min, List<String> minAgentId, List<Double> max, List<String> maxAgentId) {
if (min.get(index) > apdex) {
min.set(index, apdex);
minAgentId.set(index, agentId);
}
if (max.get(index) < apdex) {
max.set(index, apdex);
maxAgentId.set(index, agentId);
}
}

private List<DoubleApplicationStatPoint> createDoubleApplicationStatPoints(TimeWindow window, List<Double> min, List<String> minAgentId, List<Double> max, List<String> maxAgentId, List<Histogram> sumHistrogram) {
List<DoubleApplicationStatPoint> applicationStatPoints = new ArrayList<>();
for (long timestamp : window) {
int index = window.getWindowIndex(timestamp);
Histogram histogram = sumHistrogram.get(index);
if (histogram.getTotalCount() != 0){
double avg = ApdexScore.toDoubleFromHistogram(histogram);
applicationStatPoints.add(new DoubleApplicationStatPoint(timestamp, min.get(index), minAgentId.get(index), max.get(index), maxAgentId.get(index), avg));
}
}
return applicationStatPoints;
}

private List<Histogram> getDefaultHistograms(TimeWindow window, ServiceType serviceType) {
List<Histogram> sum = new ArrayList<>((int) window.getWindowRangeCount());
for (long timestamp : window){
sum.add(new TimeHistogram(serviceType, timestamp));
}
return sum;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ public AgentTimeHistogramBuilder(Application application, Range range) {
this.window = new TimeWindow(range, TimeWindowDownSampler.SAMPLER);
}

public AgentTimeHistogramBuilder(Application application, Range range, TimeWindow window) {
this.application = Objects.requireNonNull(application, "application");
this.range = Objects.requireNonNull(range, "range");
this.window = Objects.requireNonNull(window, "window");;
}

public AgentTimeHistogram build(List<ResponseTime> responseHistogramList) {
AgentHistogramList agentHistogramList = new AgentHistogramList(application, responseHistogramList);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ public class ApdexScore {

private final double apdexScore;

public static double toDoubleFromHistogram(Histogram histogram) {
Objects.requireNonNull(histogram, "histogram");
final long satisfiedCount = histogram.getFastCount();
final long toleratingCount = histogram.getNormalCount();
final long totalCount = histogram.getTotalCount();

return calculateApdexScore(satisfiedCount, toleratingCount, totalCount);
}

public static ApdexScore newApdexScore(Histogram histogram) {
Objects.requireNonNull(histogram, "histogram");
final long satisfiedCount = histogram.getFastCount();
Expand All @@ -28,7 +37,7 @@ public ApdexScore(long satisfiedCount, long toleratingCount, long totalSamples)
this.apdexScore = calculateApdexScore(satisfiedCount, toleratingCount, totalSamples);
}

private double calculateApdexScore(long satisfiedCount, long toleratingCount, long totalSamples) {
private static double calculateApdexScore(long satisfiedCount, long toleratingCount, long totalSamples) {
// divide by zero
if (totalSamples == 0) {
return 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package com.navercorp.pinpoint.web.controller;

import com.navercorp.pinpoint.common.server.util.time.Range;
import com.navercorp.pinpoint.web.applicationmap.histogram.ApdexScore;
import com.navercorp.pinpoint.web.service.ApdexScoreService;
import com.navercorp.pinpoint.web.service.ApplicationFactory;
import com.navercorp.pinpoint.web.util.TimeWindow;
import com.navercorp.pinpoint.web.util.TimeWindowSampler;
import com.navercorp.pinpoint.web.util.TimeWindowSlotCentricSampler;
import com.navercorp.pinpoint.web.view.InspectorView;
import com.navercorp.pinpoint.web.vo.Application;
import com.navercorp.pinpoint.web.vo.stat.chart.InspectorData;
import com.navercorp.pinpoint.web.vo.stat.chart.StatChart;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Objects;

@RestController
public class ApdexScoreController {
private final ApplicationFactory applicationFactory;
private final ApdexScoreService apdexScoreService;

public ApdexScoreController(ApplicationFactory applicationFactory, ApdexScoreService apdexScoreService) {
this.applicationFactory = Objects.requireNonNull(applicationFactory, "applicationFactory");
this.apdexScoreService = Objects.requireNonNull(apdexScoreService, "apdexScoreService");
}

@GetMapping(value = "/getApdexScore")
public ApdexScore getApdexScore(
@RequestParam("applicationName") String applicationName,
@RequestParam("serviceTypeCode") Short serviceTypeCode,
@RequestParam("from") long from,
@RequestParam("to") long to) {
final Range range = Range.between(from, to);

Application application = applicationFactory.createApplication(applicationName, serviceTypeCode);
final ApdexScore apdexScore = apdexScoreService.selectApdexScoreData(application, range);

return apdexScore;
}

@GetMapping(value = "/getApdexScore", params = "serviceTypeName")
public ApdexScore getApdexScore(
@RequestParam("applicationName") String applicationName,
@RequestParam("serviceTypeName") String serviceTypeName,
@RequestParam("from") long from,
@RequestParam("to") long to) {
final Range range = Range.between(from, to);

Application application = applicationFactory.createApplicationByTypeName(applicationName, serviceTypeName);
final ApdexScore apdexScore = apdexScoreService.selectApdexScoreData(application, range);

return apdexScore;
}

@GetMapping(value = "/getApplicaionStat/apdexScore/chart")
public StatChart getApplicationApdexScoreChart(
@RequestParam("applicationName") String applicationName,
@RequestParam("serviceTypeCode") Short serviceTypeCode,
@RequestParam("from") long from,
@RequestParam("to") long to) {
final Range range = Range.between(from, to);
TimeWindowSampler sampler = new TimeWindowSlotCentricSampler();
TimeWindow timeWindow = new TimeWindow(range, sampler);

Application application = applicationFactory.createApplication(applicationName, serviceTypeCode);

return apdexScoreService.selectApplicationChart(application, range, timeWindow);
}

@GetMapping(value = "/getApplicationStat/apdexScore/chart", params = "serviceTypeName")
public StatChart getAgentApdexScoreScoreChart(
@RequestParam("applicationName") String applicationName,
@RequestParam("serviceTypeName") String serviceTypeName,
@RequestParam("from") long from,
@RequestParam("to") long to) {
final Range range = Range.between(from, to);
TimeWindowSampler sampler = new TimeWindowSlotCentricSampler();
TimeWindow timeWindow = new TimeWindow(range, sampler);

Application application = applicationFactory.createApplicationByTypeName(applicationName, serviceTypeName);

return apdexScoreService.selectApplicationChart(application, range, timeWindow);
}

@GetMapping(value = "/getAgentStat/apdexScore/chart")
public StatChart getAgentApdexScoreChartData(
@RequestParam("applicationName") String applicationName,
@RequestParam("serviceTypeCode") Short serviceTypeCode,
@RequestParam("agentId") String agentId,
@RequestParam("from") long from,
@RequestParam("to") long to) {
final Range range = Range.between(from, to);
TimeWindowSampler sampler = new TimeWindowSlotCentricSampler();
TimeWindow timeWindow = new TimeWindow(range, sampler);

Application application = applicationFactory.createApplication(applicationName, serviceTypeCode);

return apdexScoreService.selectAgentChart(application, range, timeWindow, agentId);
}

@GetMapping(value = "/getAgentStat/apdexScore/chart", params = "serviceTypeName")
public StatChart getAgentApdexScoreChartData(
@RequestParam("applicationName") String applicationName,
@RequestParam("serviceTypeName") String serviceTypeName,
@RequestParam("agentId") String agentId,
@RequestParam("from") long from,
@RequestParam("to") long to) {
final Range range = Range.between(from, to);
TimeWindowSampler sampler = new TimeWindowSlotCentricSampler();
TimeWindow timeWindow = new TimeWindow(range, sampler);

Application application = applicationFactory.createApplicationByTypeName(applicationName, serviceTypeName);

return apdexScoreService.selectAgentChart(application, range, timeWindow, agentId);
}

@GetMapping(value = "/getApplicaionStat/apdexScore/inspectorView")
public InspectorView getApplicationApdexScoreView(
@RequestParam("applicationName") String applicationName,
@RequestParam("serviceTypeCode") Short serviceTypeCode,
@RequestParam("from") long from,
@RequestParam("to") long to) {
final Range range = Range.between(from, to);
TimeWindowSampler sampler = new TimeWindowSlotCentricSampler();
TimeWindow timeWindow = new TimeWindow(range, sampler);

Application application = applicationFactory.createApplication(applicationName, serviceTypeCode);

InspectorData inspectorData = apdexScoreService.selectApplicationInspectorData(application, range, timeWindow);
return new InspectorView(inspectorData);
}

@GetMapping(value = "/getApplicationStat/apdexScore/inspectorView", params = "serviceTypeName")
public InspectorView getApplicationApdexScoreView(
@RequestParam("applicationName") String applicationName,
@RequestParam("serviceTypeName") String serviceTypeName,
@RequestParam("from") long from,
@RequestParam("to") long to) {
final Range range = Range.between(from, to);
TimeWindowSampler sampler = new TimeWindowSlotCentricSampler();
TimeWindow timeWindow = new TimeWindow(range, sampler);

Application application = applicationFactory.createApplicationByTypeName(applicationName, serviceTypeName);

InspectorData inspectorData = apdexScoreService.selectApplicationInspectorData(application, range, timeWindow);
return new InspectorView(inspectorData);
}

@GetMapping(value = "/getAgentStat/apdexScore/inspectorView")
public InspectorView getAgentApdexScoreView(
@RequestParam("applicationName") String applicationName,
@RequestParam("serviceTypeCode") Short serviceTypeCode,
@RequestParam("agentId") String agentId,
@RequestParam("from") long from,
@RequestParam("to") long to) {
final Range range = Range.between(from, to);
TimeWindowSampler sampler = new TimeWindowSlotCentricSampler();
TimeWindow timeWindow = new TimeWindow(range, sampler);

Application application = applicationFactory.createApplication(applicationName, serviceTypeCode);

InspectorData inspectorData = apdexScoreService.selectAgentInspectorData(application, range, timeWindow, agentId);
return new InspectorView(inspectorData);
}

@GetMapping(value = "/getAgentStat/apdexScore/inspectorView", params = "serviceTypeName")
public InspectorView getAgentApdexScoreView(
@RequestParam("applicationName") String applicationName,
@RequestParam("serviceTypeName") String serviceTypeName,
@RequestParam("agentId") String agentId,
@RequestParam("from") long from,
@RequestParam("to") long to) {
final Range range = Range.between(from, to);
TimeWindowSampler sampler = new TimeWindowSlotCentricSampler();
TimeWindow timeWindow = new TimeWindow(range, sampler);

Application application = applicationFactory.createApplicationByTypeName(applicationName, serviceTypeName);

InspectorData inspectorData = apdexScoreService.selectAgentInspectorData(application, range, timeWindow, agentId);
return new InspectorView(inspectorData);
}
}
Loading

0 comments on commit e91a302

Please sign in to comment.