-
Notifications
You must be signed in to change notification settings - Fork 181
Support profile options for PPL - Part I Implement phases level metrics. #4983
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
3851abd
edbb6e0
079072a
154a70d
53b7589
ee0d477
820d757
7ff2bb2
0da0c4b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.monitor.profile; | ||
|
|
||
| import java.util.concurrent.atomic.LongAdder; | ||
|
|
||
| /** Concrete metric backed by {@link LongAdder}. */ | ||
| final class DefaultMetricImpl implements ProfileMetric { | ||
|
|
||
| private final String name; | ||
| private long value = 0; | ||
|
||
|
|
||
| /** | ||
| * Construct a metric with the provided name. | ||
| * | ||
| * @param name metric name | ||
| */ | ||
| DefaultMetricImpl(String name) { | ||
| this.name = name; | ||
| } | ||
|
|
||
| @Override | ||
| public String name() { | ||
| return name; | ||
| } | ||
|
|
||
| @Override | ||
| public long value() { | ||
| return value; | ||
| } | ||
|
|
||
| @Override | ||
| public void add(long delta) { | ||
| value += delta; | ||
| } | ||
|
|
||
| @Override | ||
| public void set(long value) { | ||
| this.value = 0; | ||
| add(value); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.monitor.profile; | ||
|
|
||
| import java.util.LinkedHashMap; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
|
|
||
| /** Default implementation that records profiling metrics. */ | ||
| public class DefaultProfileContext implements ProfileContext { | ||
|
|
||
| private final long startNanos = System.nanoTime(); | ||
| private boolean finished; | ||
| private final Map<MetricName, DefaultMetricImpl> metrics = new ConcurrentHashMap<>(); | ||
| private QueryProfile profile; | ||
|
|
||
| public DefaultProfileContext() {} | ||
penghuo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| public ProfileMetric getOrCreateMetric(MetricName name) { | ||
| Objects.requireNonNull(name, "name"); | ||
| return metrics.computeIfAbsent(name, key -> new DefaultMetricImpl(key.name())); | ||
| } | ||
penghuo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| public synchronized QueryProfile finish() { | ||
| if (finished) { | ||
| return profile; | ||
| } | ||
| finished = true; | ||
| long endNanos = System.nanoTime(); | ||
| Map<MetricName, Double> snapshot = new LinkedHashMap<>(MetricName.values().length); | ||
| for (MetricName metricName : MetricName.values()) { | ||
| DefaultMetricImpl metric = metrics.get(metricName); | ||
| double millis = metric == null ? 0d : roundToMillis(metric.value()); | ||
| snapshot.put(metricName, millis); | ||
| } | ||
| double totalMillis = roundToMillis(endNanos - startNanos); | ||
| profile = new QueryProfile(totalMillis, snapshot); | ||
| return profile; | ||
| } | ||
penghuo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| private double roundToMillis(long nanos) { | ||
| return Math.round((nanos / 1_000_000.0d) * 100.0d) / 100.0d; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.monitor.profile; | ||
|
|
||
| /** Named metrics used by query profiling. */ | ||
| public enum MetricName { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need PARSE_TIME, though it should be tiny?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I ignore it for now, should be minial. |
||
| ANALYZE_TIME, | ||
| OPTIMIZE_TIME, | ||
| OPENSEARCH_TIME, | ||
| POST_EXEC_TIME, | ||
| FORMAT_TIME | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.monitor.profile; | ||
|
|
||
| import java.util.Objects; | ||
|
|
||
| /** Disabled profiling context. */ | ||
| public final class NoopProfileContext implements ProfileContext { | ||
|
|
||
| public static final NoopProfileContext INSTANCE = new NoopProfileContext(); | ||
|
|
||
| private NoopProfileContext() {} | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| public ProfileMetric getOrCreateMetric(MetricName name) { | ||
| Objects.requireNonNull(name, "name"); | ||
| return NoopProfileMetric.INSTANCE; | ||
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| public QueryProfile finish() { | ||
| return null; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.monitor.profile; | ||
|
|
||
| /** No-op metric implementation. */ | ||
| final class NoopProfileMetric implements ProfileMetric { | ||
|
|
||
| static final NoopProfileMetric INSTANCE = new NoopProfileMetric(); | ||
|
|
||
| private NoopProfileMetric() {} | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| public String name() { | ||
| return ""; | ||
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| public long value() { | ||
| return 0; | ||
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| public void add(long delta) {} | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override | ||
| public void set(long value) {} | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.monitor.profile; | ||
|
|
||
| /** Context for collecting profiling metrics during query execution. */ | ||
| public interface ProfileContext { | ||
| /** | ||
| * Obtain or create a metric with the provided name. | ||
| * | ||
| * @param name fully qualified metric name | ||
| * @return metric instance | ||
| */ | ||
| ProfileMetric getOrCreateMetric(MetricName name); | ||
|
|
||
| /** | ||
| * Finalize profiling and return a snapshot. | ||
| * | ||
| * @return immutable query profile snapshot | ||
| */ | ||
| QueryProfile finish(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.monitor.profile; | ||
|
|
||
| /** Metric for query profiling. */ | ||
| public interface ProfileMetric { | ||
| /** | ||
| * @return metric name. | ||
| */ | ||
| String name(); | ||
|
|
||
| /** | ||
| * @return current metric value. | ||
| */ | ||
| long value(); | ||
|
|
||
| /** | ||
| * Increment the metric by the given delta. | ||
| * | ||
| * @param delta amount to add | ||
| */ | ||
| void add(long delta); | ||
|
|
||
| /** | ||
| * Set the metric to the provided value. | ||
| * | ||
| * @param value new metric value | ||
| */ | ||
| void set(long value); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.monitor.profile; | ||
|
|
||
| import com.google.gson.annotations.SerializedName; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import lombok.Getter; | ||
|
|
||
| /** Immutable snapshot of query profiling metrics. */ | ||
| @Getter | ||
| public final class QueryProfile { | ||
|
|
||
| /** Total elapsed milliseconds for the profiled query (rounded to two decimals). */ | ||
| @SerializedName("total_ms") | ||
| private final double totalMillis; | ||
|
|
||
| /** Immutable metric values keyed by metric name in milliseconds (rounded to two decimals). */ | ||
| private final Map<String, Double> metrics; | ||
|
|
||
| /** | ||
| * Create a new query profile snapshot. | ||
| * | ||
| * @param totalMillis total elapsed milliseconds for the query (rounded to two decimals) | ||
| * @param metrics metric values keyed by {@link MetricName} | ||
| */ | ||
| public QueryProfile(double totalMillis, Map<MetricName, Double> metrics) { | ||
| this.totalMillis = totalMillis; | ||
| this.metrics = buildMetrics(metrics); | ||
| } | ||
|
|
||
| private Map<String, Double> buildMetrics(Map<MetricName, Double> metrics) { | ||
| Objects.requireNonNull(metrics, "metrics"); | ||
| Map<String, Double> ordered = new java.util.LinkedHashMap<>(metrics.size()); | ||
| for (MetricName metricName : MetricName.values()) { | ||
| Double value = metrics.getOrDefault(metricName, 0d); | ||
| ordered.put(metricName.name() + "_MS", value); | ||
| } | ||
| return ordered; | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.