diff --git a/x-pack/plugin/profiling/src/internalClusterTest/java/org/elasticsearch/xpack/profiling/GetFlameGraphActionIT.java b/x-pack/plugin/profiling/src/internalClusterTest/java/org/elasticsearch/xpack/profiling/GetFlameGraphActionIT.java index 4ce441285d432..8553574d39646 100644 --- a/x-pack/plugin/profiling/src/internalClusterTest/java/org/elasticsearch/xpack/profiling/GetFlameGraphActionIT.java +++ b/x-pack/plugin/profiling/src/internalClusterTest/java/org/elasticsearch/xpack/profiling/GetFlameGraphActionIT.java @@ -14,8 +14,12 @@ public void testGetStackTracesUnfiltered() throws Exception { // only spot-check top level properties - detailed tests are done in unit tests assertEquals(994, response.getSize()); assertEquals(1.0d, response.getSamplingRate(), 0.001d); - assertEquals(44, response.getSelfCPU()); - assertEquals(1865, response.getTotalCPU()); - assertEquals(44, response.getTotalSamples()); + assertEquals(46, response.getSelfCPU()); + assertEquals(1903, response.getTotalCPU()); + assertEquals(46, response.getTotalSamples()); + + // The root node's values are the same as the top-level values. + assertEquals("", response.getFileIds().get(0)); + assertEquals(response.getSelfCPU(), response.getCountInclusive().get(0).longValue()); } } diff --git a/x-pack/plugin/profiling/src/internalClusterTest/java/org/elasticsearch/xpack/profiling/GetStackTracesActionIT.java b/x-pack/plugin/profiling/src/internalClusterTest/java/org/elasticsearch/xpack/profiling/GetStackTracesActionIT.java index a5efa24da5397..289f6896ed698 100644 --- a/x-pack/plugin/profiling/src/internalClusterTest/java/org/elasticsearch/xpack/profiling/GetStackTracesActionIT.java +++ b/x-pack/plugin/profiling/src/internalClusterTest/java/org/elasticsearch/xpack/profiling/GetStackTracesActionIT.java @@ -14,14 +14,14 @@ public class GetStackTracesActionIT extends ProfilingTestCase { public void testGetStackTracesUnfiltered() throws Exception { - GetStackTracesRequest request = new GetStackTracesRequest(10, 1.0d, 1.0d, null, null, null, null, null, null, null, null); + GetStackTracesRequest request = new GetStackTracesRequest(1000, 600.0d, 1.0d, null, null, null, null, null, null, null, null); request.setAdjustSampleCount(true); GetStackTracesResponse response = client().execute(GetStackTracesAction.INSTANCE, request).get(); - assertEquals(40, response.getTotalSamples()); - assertEquals(473, response.getTotalFrames()); + assertEquals(46, response.getTotalSamples()); + assertEquals(1821, response.getTotalFrames()); assertNotNull(response.getStackTraceEvents()); - assertEquals(4L, response.getStackTraceEvents().get("L7kj7UvlKbT-vN73el4faQ").count); + assertEquals(3L, response.getStackTraceEvents().get("L7kj7UvlKbT-vN73el4faQ").count); assertNotNull(response.getStackTraces()); // just do a high-level spot check. Decoding is tested in unit-tests @@ -30,8 +30,8 @@ public void testGetStackTracesUnfiltered() throws Exception { assertEquals(18, stackTrace.fileIds.size()); assertEquals(18, stackTrace.frameIds.size()); assertEquals(18, stackTrace.typeIds.size()); - assertEquals(0.007903d, stackTrace.annualCO2Tons, 0.000001d); - assertEquals(74.46d, stackTrace.annualCostsUSD, 0.01d); + assertEquals(0.0000098789d, stackTrace.annualCO2Tons, 0.0000000001d); + assertEquals(0.093075d, stackTrace.annualCostsUSD, 0.000001d); assertNotNull(response.getStackFrames()); StackFrame stackFrame = response.getStackFrames().get("8NlMClggx8jaziUTJXlmWAAAAAAAAIYI"); @@ -58,7 +58,7 @@ public void testGetStackTracesFromAPMWithMatch() throws Exception { null ); GetStackTracesResponse response = client().execute(GetStackTracesAction.INSTANCE, request).get(); - assertEquals(43, response.getTotalFrames()); + assertEquals(49, response.getTotalFrames()); assertNotNull(response.getStackTraceEvents()); assertEquals(3L, response.getStackTraceEvents().get("Ce77w10WeIDow3kd1jowlA").count); diff --git a/x-pack/plugin/profiling/src/internalClusterTest/resources/data/profiling-events-all.ndjson b/x-pack/plugin/profiling/src/internalClusterTest/resources/data/profiling-events-all.ndjson index 6964368e534c7..502494f05c62c 100644 --- a/x-pack/plugin/profiling/src/internalClusterTest/resources/data/profiling-events-all.ndjson +++ b/x-pack/plugin/profiling/src/internalClusterTest/resources/data/profiling-events-all.ndjson @@ -71,6 +71,8 @@ {"create": {"_index": "profiling-events-all"}} {"Stacktrace.count": [1], "profiling.project.id": ["100"], "os.kernel": ["9.9.9-0"], "tags": ["environment:qa", "region:eu-west-1"], "host.ip": ["192.168.1.2"], "@timestamp": ["1698624000"], "container.name": ["instance-0000000010"], "ecs.version": ["1.12.0"], "Stacktrace.id": ["XF9MchOwpePfa6_hYy-vZQ"], "agent.version": ["head-be593ef3-1688111067"], "host.name": ["ip-192-168-1-2"], "host.id": ["8457605156473051743"], "process.thread.name": ["497295213074376"]} {"create": {"_index": "profiling-events-all"}} +{"Stacktrace.count": [2], "profiling.project.id": ["100"], "os.kernel": ["9.9.9-0"], "tags": ["environment:qa", "region:eu-west-1"], "host.ip": ["192.168.1.2"], "@timestamp": ["1698624000"], "container.name": ["instance-0000000010"], "ecs.version": ["1.12.0"], "Stacktrace.id": ["L7kj7UvlKbT-vN73el4faQ"], "agent.version": ["head-be593ef3-1688111067"], "host.name": ["ip-192-168-1-2"], "host.id": ["8457605156473051743"], "process.thread.name": ["497295213074376"]} +{"create": {"_index": "profiling-events-all"}} {"Stacktrace.count": [1], "profiling.project.id": ["100"], "os.kernel": ["9.9.9-0"], "tags": ["environment:qa", "region:eu-west-1"], "host.ip": ["192.168.1.2"], "@timestamp": ["1698624000"], "container.name": ["instance-0000000010"], "ecs.version": ["1.12.0"], "Stacktrace.id": ["L7kj7UvlKbT-vN73el4faQ"], "agent.version": ["head-be593ef3-1688111067"], "host.name": ["ip-192-168-1-2"], "host.id": ["8457605156473051743"], "process.thread.name": ["497295213074376"]} {"create": {"_index": "profiling-events-all"}} {"Stacktrace.count": [1], "profiling.project.id": ["100"], "os.kernel": ["9.9.9-0"], "tags": ["environment:qa", "region:eu-west-1"], "host.ip": ["192.168.1.2"], "@timestamp": ["1698624000"], "container.name": ["instance-0000000010"], "ecs.version": ["1.12.0"], "Stacktrace.id": ["hRqQI2CBPiapzgFG9jrmDA"], "agent.version": ["head-be593ef3-1688111067"], "host.name": ["ip-192-168-1-2"], "host.id": ["8457605156473051743"], "process.thread.name": ["599103450330106"]} diff --git a/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/GetFlamegraphResponse.java b/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/GetFlamegraphResponse.java index 211b6d76f8caa..457faecf4ad54 100644 --- a/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/GetFlamegraphResponse.java +++ b/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/GetFlamegraphResponse.java @@ -194,6 +194,14 @@ public List getSourceLines() { return sourceLines; } + public List getAnnualCO2TonsInclusive() { + return annualCO2TonsInclusive; + } + + public List getAnnualCostsUSDInclusive() { + return annualCostsUSDInclusive; + } + public long getSelfCPU() { return selfCPU; } diff --git a/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/GetStackTracesResponseBuilder.java b/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/GetStackTracesResponseBuilder.java index ccafe99c31d9a..ab98b1d4daa2a 100644 --- a/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/GetStackTracesResponseBuilder.java +++ b/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/GetStackTracesResponseBuilder.java @@ -54,6 +54,10 @@ public void setTotalFrames(int totalFrames) { this.totalFrames = totalFrames; } + public void addTotalFrames(int numFrames) { + this.totalFrames += numFrames; + } + public void setStackFrames(Map stackFrames) { this.stackFrames = stackFrames; } diff --git a/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/StackFrame.java b/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/StackFrame.java index 455b150b6ee76..35f5899536745 100644 --- a/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/StackFrame.java +++ b/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/StackFrame.java @@ -30,9 +30,20 @@ final class StackFrame implements ToXContentObject { this.lineNumber = listOf(lineNumber); } + public int size() { + return this.functionName.size(); // functionName is the only array that is always set + } + + /** + * Returns the number of inlined frames in this stack frame. + * @return the number of inlined frames in this stack frame. + */ + public int inlineFrameCount() { + return size() > 0 ? size() - 1 : 0; + } + public void forEach(Consumer action) { - int size = this.functionName.size(); // functionName is the only array that is always set - for (int i = 0; i < size; i++) { + for (int i = 0; i < size(); i++) { action.accept( new Frame( fileName.size() > i ? fileName.get(i) : "", @@ -40,7 +51,7 @@ public void forEach(Consumer action) { functionOffset.size() > i ? functionOffset.get(i) : 0, lineNumber.size() > i ? lineNumber.get(i) : 0, i > 0, - i == size - 1 + i == size() - 1 ) ); } @@ -67,7 +78,7 @@ public static StackFrame fromSource(Map source) { } public boolean isEmpty() { - return fileName.isEmpty() && functionName.isEmpty() && functionOffset.isEmpty() && lineNumber.isEmpty(); + return size() == 0; } @Override diff --git a/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/TransportGetStackTracesAction.java b/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/TransportGetStackTracesAction.java index 000b448696985..3fa47beebd70a 100644 --- a/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/TransportGetStackTracesAction.java +++ b/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/TransportGetStackTracesAction.java @@ -688,6 +688,7 @@ private static class DetailsHandler { private final Map executables; private final Map stackFrames; private final AtomicInteger expectedSlices; + private final AtomicInteger totalInlineFrames = new AtomicInteger(); private final StopWatch watch = new StopWatch("retrieveStackTraceDetails"); private DetailsHandler( @@ -718,7 +719,9 @@ public void onStackFramesResponse(MultiGetResponse multiGetItemResponses) { if (stackFrames.containsKey(frame.getId()) == false) { StackFrame stackFrame = StackFrame.fromSource(frame.getResponse().getSource()); if (stackFrame.isEmpty() == false) { - stackFrames.putIfAbsent(frame.getId(), stackFrame); + if (stackFrames.putIfAbsent(frame.getId(), stackFrame) == null) { + totalInlineFrames.addAndGet(stackFrame.inlineFrameCount()); + } } else { log.trace("Stack frame with id [{}] has no properties.", frame.getId()); } @@ -757,6 +760,7 @@ public void mayFinish() { if (expectedSlices.decrementAndGet() == 0) { builder.setExecutables(executables); builder.setStackFrames(stackFrames); + builder.addTotalFrames(totalInlineFrames.get()); log.debug("retrieveStackTraceDetails found [{}] stack frames, [{}] executables.", stackFrames.size(), executables.size()); log.debug(watch::report); submitListener.onResponse(builder.build());