diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzer.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzer.java index 4ac45b381..4e8382c4f 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzer.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileAnalyzer.java @@ -25,9 +25,11 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.stream.Collectors; import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord; import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzation; +import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzeTimeRange; import org.apache.skywalking.oap.server.core.query.entity.ProfileStackTree; import org.apache.skywalking.oap.server.core.storage.StorageModule; import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO; @@ -62,17 +64,17 @@ public class ProfileAnalyzer { /** * search snapshots and analyze */ - public ProfileAnalyzation analyze(String segmentId, long start, long end) throws IOException { + public ProfileAnalyzation analyze(String segmentId, List timeRanges) throws IOException { ProfileAnalyzation analyzation = new ProfileAnalyzation(); // query sequence range list - SequenceSearch sequenceSearch = getAllSequenceRange(segmentId, start, end); + SequenceSearch sequenceSearch = getAllSequenceRange(segmentId, timeRanges); if (sequenceSearch == null) { analyzation.setTip("Data not found"); return analyzation; } - if (sequenceSearch.totalSequenceCount > analyzeSnapshotMaxSize) { - analyzation.setTip("Out of snapshot analyze limit, " + sequenceSearch.totalSequenceCount + " snapshots found, but analysis first " + analyzeSnapshotMaxSize + " snapshots only."); + if (sequenceSearch.getTotalSequenceCount() > analyzeSnapshotMaxSize) { + analyzation.setTip("Out of snapshot analyze limit, " + sequenceSearch.getTotalSequenceCount() + " snapshots found, but analysis first " + analyzeSnapshotMaxSize + " snapshots only."); } // query snapshots @@ -91,6 +93,17 @@ public class ProfileAnalyzer { return analyzation; } + protected SequenceSearch getAllSequenceRange(String segmentId, List timeRanges) throws IOException { + return timeRanges.parallelStream().map(r -> { + try { + return getAllSequenceRange(segmentId, r.getStart(), r.getEnd()); + } catch (IOException e) { + LOGGER.warn(e.getMessage(), e); + return null; + } + }).filter(Objects::nonNull).reduce(new SequenceSearch(0), SequenceSearch::combine); + } + protected SequenceSearch getAllSequenceRange(String segmentId, long start, long end) throws IOException { // query min and max sequence int minSequence = getProfileThreadSnapshotQueryDAO().queryMinSequence(segmentId, start, end); @@ -156,6 +169,12 @@ public class ProfileAnalyzer { public int getTotalSequenceCount() { return totalSequenceCount; } + + public SequenceSearch combine(SequenceSearch search) { + this.ranges.addAll(search.ranges); + this.totalSequenceCount += search.totalSequenceCount; + return this; + } } private static class SequenceRange { @@ -175,8 +194,5 @@ public class ProfileAnalyzer { return maxSequence; } - public void increaseMaxSequence() { - this.maxSequence++; - } } } diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProfileTaskQueryService.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProfileTaskQueryService.java index 7d02ef9e5..f1ae37c7f 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProfileTaskQueryService.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/ProfileTaskQueryService.java @@ -40,6 +40,7 @@ import org.apache.skywalking.oap.server.core.query.entity.BasicTrace; import org.apache.skywalking.oap.server.core.query.entity.KeyValue; import org.apache.skywalking.oap.server.core.query.entity.LogEntity; import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzation; +import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzeTimeRange; import org.apache.skywalking.oap.server.core.query.entity.ProfileTask; import org.apache.skywalking.oap.server.core.query.entity.ProfileTaskLog; import org.apache.skywalking.oap.server.core.query.entity.ProfiledSegment; @@ -198,8 +199,8 @@ public class ProfileTaskQueryService implements Service { return getProfileThreadSnapshotQueryDAO().queryProfiledSegments(taskId); } - public ProfileAnalyzation getProfileAnalyze(final String segmentId, final long start, final long end) throws IOException { - return profileAnalyzer.analyze(segmentId, start, end); + public ProfileAnalyzation getProfileAnalyze(final String segmentId, final List timeRanges) throws IOException { + return profileAnalyzer.analyze(segmentId, timeRanges); } public ProfiledSegment getProfiledSegment(String segmentId) throws IOException { diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileAnalyzeTimeRange.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileAnalyzeTimeRange.java new file mode 100644 index 000000000..81bcfe697 --- /dev/null +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/entity/ProfileAnalyzeTimeRange.java @@ -0,0 +1,31 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.apache.skywalking.oap.server.core.query.entity; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class ProfileAnalyzeTimeRange { + + private long start; + private long end; + +} diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackAnalyze.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackAnalyze.java index 7ceddb37b..59d7b8406 100644 --- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackAnalyze.java +++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/profile/analyze/ProfileStackAnalyze.java @@ -19,6 +19,7 @@ package org.apache.skywalking.oap.server.core.profile.analyze; import java.io.IOException; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -26,6 +27,7 @@ import lombok.Data; import org.apache.skywalking.oap.server.core.analysis.manual.segment.SegmentRecord; import org.apache.skywalking.oap.server.core.profile.ProfileThreadSnapshotRecord; import org.apache.skywalking.oap.server.core.query.entity.BasicTrace; +import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzeTimeRange; import org.apache.skywalking.oap.server.core.query.entity.ProfileStackTree; import org.apache.skywalking.oap.server.core.storage.profile.IProfileThreadSnapshotQueryDAO; @@ -41,7 +43,10 @@ public class ProfileStackAnalyze { public void analyzeAndAssert(int maxAnalyzeCount) throws IOException { List stacks = data.transform(); - List trees = buildAnalyzer(stacks, maxAnalyzeCount).analyze(null, 0, 0).getTrees(); + final ProfileAnalyzeTimeRange range = new ProfileAnalyzeTimeRange(); + range.setStart(0); + range.setEnd(0); + List trees = buildAnalyzer(stacks, maxAnalyzeCount).analyze(null, Collections.singletonList(range)).getTrees(); assertNotNull(trees); assertEquals(trees.size(), expected.size()); diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileQuery.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileQuery.java index 0f2dff9d9..650fac8ef 100644 --- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileQuery.java +++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/resolver/ProfileQuery.java @@ -23,6 +23,7 @@ import org.apache.skywalking.oap.server.core.CoreModule; import org.apache.skywalking.oap.server.core.query.ProfileTaskQueryService; import org.apache.skywalking.oap.server.core.query.entity.BasicTrace; import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzation; +import org.apache.skywalking.oap.server.core.query.entity.ProfileAnalyzeTimeRange; import org.apache.skywalking.oap.server.core.query.entity.ProfileTask; import org.apache.skywalking.oap.server.core.query.entity.ProfiledSegment; import org.apache.skywalking.oap.server.library.module.ModuleManager; @@ -63,9 +64,8 @@ public class ProfileQuery implements GraphQLQueryResolver { return getProfileTaskQueryService().getProfiledSegment(segmentId); } - public ProfileAnalyzation getProfileAnalyze(final String segmentId, final long start, - final long end) throws IOException { - return getProfileTaskQueryService().getProfileAnalyze(segmentId, start, end); + public ProfileAnalyzation getProfileAnalyze(final String segmentId, final List timeRanges) throws IOException { + return getProfileTaskQueryService().getProfileAnalyze(segmentId, timeRanges); } } diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol b/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol index 6b26ddad2..8c9a8c45b 160000 --- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol +++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/resources/query-protocol @@ -1 +1 @@ -Subproject commit 6b26ddad2099b8782b2e298fd0df02dfd1d6609f +Subproject commit 8c9a8c45b9dbe954efa6de50202d05b1ef8e6be2 diff --git a/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/resources/getProfileAnalyzation.gql b/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/resources/getProfileAnalyzation.gql index ab34431c4..afdeffe90 100644 --- a/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/resources/getProfileAnalyzation.gql +++ b/test/e2e/e2e-profile/e2e-profile-test-runner/src/main/resources/getProfileAnalyzation.gql @@ -15,8 +15,8 @@ # limitations under the License. { - "query":"query getProfileAnalyze($segmentId: String!, $start: Long!, $end: Long!) { - data: getProfileAnalyze(segmentId: $segmentId, start: $start, end: $end) { + "query":"query getProfileAnalyze($segmentId: String!, $timeRanges: [ProfileAnalyzeTimeRange!]!) { + data: getProfileAnalyze(segmentId: $segmentId, timeRanges: $timeRanges) { trees { elements { id @@ -31,7 +31,6 @@ }", "variables": { "segmentId": "{segmentId}", - "start": "{start}", - "end": "{end}" + "timeRanges": [{"start": "{start}", "end": "{end}"}] } }