diff --git a/pom.xml b/pom.xml
index 1bd18678fe89c..3be9e470bc4fd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,7 +49,7 @@
0.38
0.6
1.12.560
- 3.9.0
+ 4.12.0
3.4.0
19.3.0.0
1.40
@@ -105,6 +105,9 @@
1.68.0
-missing
+ 1.38.0
+ 1.38.0-alpha
+ 1.9.10
@@ -2329,19 +2332,19 @@
io.opentelemetry
opentelemetry-api
- 1.19.0
+ ${opentelemetry.version}
io.opentelemetry
opentelemetry-context
- 1.19.0
+ ${opentelemetry.version}
io.opentelemetry
opentelemetry-exporter-otlp
- 1.19.0
+ ${opentelemetry.version}
com.squareup.okhttp3
@@ -2353,31 +2356,37 @@
io.opentelemetry
opentelemetry-extension-trace-propagators
- 1.19.0
+ ${opentelemetry.version}
io.opentelemetry
opentelemetry-sdk
- 1.19.0
+ ${opentelemetry.version}
+
+
+
+ io.opentelemetry
+ opentelemetry-sdk-testing
+ ${opentelemetry.version}
io.opentelemetry
opentelemetry-sdk-common
- 1.19.0
+ ${opentelemetry.version}
io.opentelemetry
opentelemetry-sdk-trace
- 1.19.0
+ ${opentelemetry.version}
io.opentelemetry
opentelemetry-semconv
- 1.19.0-alpha
+ ${opentelemetry-alpha.version}
@@ -2475,7 +2484,12 @@
flight-core
${dep.arrow.version}
-
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+ ${kotlin-stdlib-jdk8.version}
+
diff --git a/presto-benchmark-driver/src/main/java/com/facebook/presto/benchmark/driver/BenchmarkDriverOptions.java b/presto-benchmark-driver/src/main/java/com/facebook/presto/benchmark/driver/BenchmarkDriverOptions.java
index 08e3b79b6b3a6..16c2f02905c01 100644
--- a/presto-benchmark-driver/src/main/java/com/facebook/presto/benchmark/driver/BenchmarkDriverOptions.java
+++ b/presto-benchmark-driver/src/main/java/com/facebook/presto/benchmark/driver/BenchmarkDriverOptions.java
@@ -94,7 +94,6 @@ public ClientSession getClientSession()
parseServer(server),
user,
"presto-benchmark",
- Optional.empty(),
ImmutableSet.of(),
null,
catalog,
diff --git a/presto-cassandra/src/test/java/com/facebook/presto/cassandra/TestCassandraConnector.java b/presto-cassandra/src/test/java/com/facebook/presto/cassandra/TestCassandraConnector.java
index 3fe4f25c6cca0..799335ab43317 100644
--- a/presto-cassandra/src/test/java/com/facebook/presto/cassandra/TestCassandraConnector.java
+++ b/presto-cassandra/src/test/java/com/facebook/presto/cassandra/TestCassandraConnector.java
@@ -82,7 +82,6 @@ public class TestCassandraConnector
"user",
new ConnectorIdentity("user", Optional.empty(), Optional.empty()),
Optional.of("test"),
- Optional.empty(),
UTC_KEY,
ENGLISH,
System.currentTimeMillis(),
diff --git a/presto-cli/src/main/java/com/facebook/presto/cli/ClientOptions.java b/presto-cli/src/main/java/com/facebook/presto/cli/ClientOptions.java
index 6a05483e1e511..a2edcafbe16e4 100644
--- a/presto-cli/src/main/java/com/facebook/presto/cli/ClientOptions.java
+++ b/presto-cli/src/main/java/com/facebook/presto/cli/ClientOptions.java
@@ -180,7 +180,6 @@ public ClientSession toClientSession()
parseServer(server),
user,
source,
- Optional.empty(),
parseClientTags(clientTags),
clientInfo,
catalog,
diff --git a/presto-cli/src/test/java/com/facebook/presto/cli/AbstractCliTest.java b/presto-cli/src/test/java/com/facebook/presto/cli/AbstractCliTest.java
index eb2267e1bd797..8d74528484da3 100644
--- a/presto-cli/src/test/java/com/facebook/presto/cli/AbstractCliTest.java
+++ b/presto-cli/src/test/java/com/facebook/presto/cli/AbstractCliTest.java
@@ -68,7 +68,6 @@ protected ClientSession createMockClientSession()
server.url("/").uri(),
"user",
"source",
- Optional.empty(),
ImmutableSet.of(),
"clientInfo",
"catalog",
diff --git a/presto-client/src/main/java/com/facebook/presto/client/ClientSession.java b/presto-client/src/main/java/com/facebook/presto/client/ClientSession.java
index 5896a3c6f2d3c..994dea03217f8 100644
--- a/presto-client/src/main/java/com/facebook/presto/client/ClientSession.java
+++ b/presto-client/src/main/java/com/facebook/presto/client/ClientSession.java
@@ -24,7 +24,6 @@
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Optional;
import java.util.Set;
import static com.google.common.base.MoreObjects.toStringHelper;
@@ -37,7 +36,6 @@ public class ClientSession
private final URI server;
private final String user;
private final String source;
- private final Optional traceToken;
private final Set clientTags;
private final String clientInfo;
private final String catalog;
@@ -72,7 +70,6 @@ public ClientSession(
URI server,
String user,
String source,
- Optional traceToken,
Set clientTags,
String clientInfo,
String catalog,
@@ -94,7 +91,6 @@ public ClientSession(
this.server = requireNonNull(server, "server is null");
this.user = user;
this.source = source;
- this.traceToken = requireNonNull(traceToken, "traceToken is null");
this.clientTags = ImmutableSet.copyOf(requireNonNull(clientTags, "clientTags is null"));
this.clientInfo = clientInfo;
this.catalog = catalog;
@@ -165,11 +161,6 @@ public String getSource()
return source;
}
- public Optional getTraceToken()
- {
- return traceToken;
- }
-
public Set getClientTags()
{
return clientTags;
@@ -273,7 +264,6 @@ public String toString()
.add("clientInfo", clientInfo)
.add("catalog", catalog)
.add("schema", schema)
- .add("traceToken", traceToken.orElse(null))
.add("timeZone", timeZone)
.add("locale", locale)
.add("properties", properties)
@@ -287,7 +277,6 @@ public static final class Builder
private URI server;
private String user;
private String source;
- private Optional traceToken;
private Set clientTags;
private String clientInfo;
private String catalog;
@@ -312,7 +301,6 @@ private Builder(ClientSession clientSession)
server = clientSession.getServer();
user = clientSession.getUser();
source = clientSession.getSource();
- traceToken = clientSession.getTraceToken();
clientTags = clientSession.getClientTags();
clientInfo = clientSession.getClientInfo();
catalog = clientSession.getCatalog();
@@ -410,7 +398,6 @@ public ClientSession build()
server,
user,
source,
- traceToken,
clientTags,
clientInfo,
catalog,
diff --git a/presto-client/src/main/java/com/facebook/presto/client/OkHttpUtil.java b/presto-client/src/main/java/com/facebook/presto/client/OkHttpUtil.java
index 50f7d202cad7b..73039a29a4e16 100644
--- a/presto-client/src/main/java/com/facebook/presto/client/OkHttpUtil.java
+++ b/presto-client/src/main/java/com/facebook/presto/client/OkHttpUtil.java
@@ -14,6 +14,7 @@
package com.facebook.presto.client;
import com.facebook.airlift.security.pem.PemReader;
+import com.facebook.presto.client.okhttp3.internal.tls.LegacyHostnameVerifier;
import com.google.common.base.CharMatcher;
import com.google.common.net.HostAndPort;
import okhttp3.Call;
@@ -237,6 +238,7 @@ public static void setupSsl(
sslContext.init(keyManagers, new TrustManager[] {trustManager}, null);
clientBuilder.sslSocketFactory(sslContext.getSocketFactory(), trustManager);
+ clientBuilder.hostnameVerifier(LegacyHostnameVerifier.INSTANCE);
}
catch (GeneralSecurityException | IOException e) {
throw new ClientException("Error setting up SSL: " + e.getMessage(), e);
diff --git a/presto-client/src/main/java/com/facebook/presto/client/PrestoHeaders.java b/presto-client/src/main/java/com/facebook/presto/client/PrestoHeaders.java
index 3be0b241ee0b2..9f83194cad39f 100644
--- a/presto-client/src/main/java/com/facebook/presto/client/PrestoHeaders.java
+++ b/presto-client/src/main/java/com/facebook/presto/client/PrestoHeaders.java
@@ -21,7 +21,6 @@ public final class PrestoHeaders
public static final String PRESTO_SCHEMA = "X-Presto-Schema";
public static final String PRESTO_TIME_ZONE = "X-Presto-Time-Zone";
public static final String PRESTO_LANGUAGE = "X-Presto-Language";
- public static final String PRESTO_TRACE_TOKEN = "X-Presto-Trace-Token";
public static final String PRESTO_SESSION = "X-Presto-Session";
public static final String PRESTO_SET_CATALOG = "X-Presto-Set-Catalog";
public static final String PRESTO_SET_SCHEMA = "X-Presto-Set-Schema";
diff --git a/presto-client/src/main/java/com/facebook/presto/client/StatementClientV1.java b/presto-client/src/main/java/com/facebook/presto/client/StatementClientV1.java
index 9268195710af3..67c64171634d6 100644
--- a/presto-client/src/main/java/com/facebook/presto/client/StatementClientV1.java
+++ b/presto-client/src/main/java/com/facebook/presto/client/StatementClientV1.java
@@ -69,7 +69,6 @@
import static com.facebook.presto.client.PrestoHeaders.PRESTO_SOURCE;
import static com.facebook.presto.client.PrestoHeaders.PRESTO_STARTED_TRANSACTION_ID;
import static com.facebook.presto.client.PrestoHeaders.PRESTO_TIME_ZONE;
-import static com.facebook.presto.client.PrestoHeaders.PRESTO_TRACE_TOKEN;
import static com.facebook.presto.client.PrestoHeaders.PRESTO_TRANSACTION_ID;
import static com.facebook.presto.client.PrestoHeaders.PRESTO_USER;
import static com.google.common.base.MoreObjects.firstNonNull;
@@ -163,8 +162,6 @@ private Request buildQueryRequest(ClientSession session, String query)
builder.addHeader(PRESTO_SOURCE, session.getSource());
}
- session.getTraceToken().ifPresent(token -> builder.addHeader(PRESTO_TRACE_TOKEN, token));
-
if (session.getClientTags() != null && !session.getClientTags().isEmpty()) {
builder.addHeader(PRESTO_CLIENT_TAGS, Joiner.on(",").join(session.getClientTags()));
}
diff --git a/presto-client/src/main/java/com/facebook/presto/client/okhttp3/internal/tls/DistinguishedNameParser.java b/presto-client/src/main/java/com/facebook/presto/client/okhttp3/internal/tls/DistinguishedNameParser.java
new file mode 100644
index 0000000000000..65bd1faf03840
--- /dev/null
+++ b/presto-client/src/main/java/com/facebook/presto/client/okhttp3/internal/tls/DistinguishedNameParser.java
@@ -0,0 +1,422 @@
+/*
+ * 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.facebook.presto.client.okhttp3.internal.tls;
+
+import javax.security.auth.x500.X500Principal;
+
+/**
+ * A distinguished name (DN) parser. This parser only supports extracting a string value from a DN.
+ * It doesn't support values in the hex-string style.
+ */
+final class DistinguishedNameParser
+{
+ private final String dn;
+ private final int length;
+ private int pos;
+ private int beg;
+ private int end;
+
+ /**
+ * Temporary variable to store positions of the currently parsed item.
+ */
+ private int cur;
+
+ /**
+ * Distinguished name characters.
+ */
+ private char[] chars;
+
+ DistinguishedNameParser(X500Principal principal)
+ {
+ // RFC2253 is used to ensure we get attributes in the reverse
+ // order of the underlying ASN.1 encoding, so that the most
+ // significant values of repeated attributes occur first.
+ this.dn = principal.getName(X500Principal.RFC2253);
+ this.length = this.dn.length();
+ }
+
+ // gets next attribute type: (ALPHA 1*keychar) / oid
+ private String nextAT()
+ {
+ for (; pos < length && chars[pos] == ' '; pos++) {
+ // skip preceding space chars, they can present after
+ // comma or semicolon (compatibility with RFC 1779)
+ }
+ if (pos == length) {
+ return null; // reached the end of DN
+ }
+
+ // mark the beginning of attribute type
+ beg = pos;
+
+ // attribute type chars
+ pos++;
+ for (; pos < length && chars[pos] != '=' && chars[pos] != ' '; pos++) {
+ // we don't follow exact BNF syntax here:
+ // accept any char except space and '='
+ }
+ if (pos >= length) {
+ throw new IllegalStateException("Unexpected end of DN: " + dn);
+ }
+
+ // mark the end of attribute type
+ end = pos;
+
+ if (chars[pos] == ' ') {
+ for (; pos < length && chars[pos] != '=' && chars[pos] == ' '; pos++) {
+ // skip trailing space chars between attribute type and '='
+ // (compatibility with RFC 1779)
+ }
+
+ if (chars[pos] != '=' || pos == length) {
+ throw new IllegalStateException("Unexpected end of DN: " + dn);
+ }
+ }
+
+ pos++; //skip '=' char
+
+ for (; pos < length && chars[pos] == ' '; pos++) {
+ // skip space chars between '=' and attribute value
+ // (compatibility with RFC 1779)
+ }
+
+ // in case of oid attribute type skip its prefix: "oid." or "OID."
+ // (compatibility with RFC 1779)
+ if ((end - beg > 4) && (chars[beg + 3] == '.')
+ && (chars[beg] == 'O' || chars[beg] == 'o')
+ && (chars[beg + 1] == 'I' || chars[beg + 1] == 'i')
+ && (chars[beg + 2] == 'D' || chars[beg + 2] == 'd')) {
+ beg += 4;
+ }
+
+ return new String(chars, beg, end - beg);
+ }
+
+ // gets quoted attribute value: QUOTATION *( quotechar / pair ) QUOTATION
+ private String quotedAV()
+ {
+ pos++;
+ beg = pos;
+ end = beg;
+ while (true) {
+ if (pos == length) {
+ throw new IllegalStateException("Unexpected end of DN: " + dn);
+ }
+
+ if (chars[pos] == '"') {
+ // enclosing quotation was found
+ pos++;
+ break;
+ }
+ else if (chars[pos] == '\\') {
+ chars[end] = getEscaped();
+ }
+ else {
+ // shift char: required for string with escaped chars
+ chars[end] = chars[pos];
+ }
+ pos++;
+ end++;
+ }
+
+ for (; pos < length && chars[pos] == ' '; pos++) {
+ // skip trailing space chars before comma or semicolon.
+ // (compatibility with RFC 1779)
+ }
+
+ return new String(chars, beg, end - beg);
+ }
+
+ // gets hex string attribute value: "#" hexstring
+ private String hexAV()
+ {
+ if (pos + 4 >= length) {
+ // encoded byte array must be not less then 4 c
+ throw new IllegalStateException("Unexpected end of DN: " + dn);
+ }
+
+ beg = pos; // store '#' position
+ pos++;
+ while (true) {
+ // check for end of attribute value
+ // looks for space and component separators
+ if (pos == length || chars[pos] == '+' || chars[pos] == ','
+ || chars[pos] == ';') {
+ end = pos;
+ break;
+ }
+
+ if (chars[pos] == ' ') {
+ end = pos;
+ pos++;
+ for (; pos < length && chars[pos] == ' '; pos++) {
+ // skip trailing space chars before comma or semicolon.
+ // (compatibility with RFC 1779)
+ }
+ break;
+ }
+ else if (chars[pos] >= 'A' && chars[pos] <= 'F') {
+ chars[pos] += 32; //to low case
+ }
+
+ pos++;
+ }
+
+ // verify length of hex string
+ // encoded byte array must be not less then 4 and must be even number
+ int hexLen = end - beg; // skip first '#' char
+ if (hexLen < 5 || (hexLen & 1) == 0) {
+ throw new IllegalStateException("Unexpected end of DN: " + dn);
+ }
+
+ // get byte encoding from string representation
+ byte[] encoded = new byte[hexLen / 2];
+ for (int i = 0, p = beg + 1; i < encoded.length; p += 2, i++) {
+ encoded[i] = (byte) getByte(p);
+ }
+ return new String(chars, beg, hexLen);
+ }
+ // gets string attribute value: *( stringchar / pair)
+ private String escapedAV()
+ {
+ beg = pos;
+ end = pos;
+ while (true) {
+ if (pos >= length) {
+ // the end of DN has been found
+ return new String(chars, beg, end - beg);
+ }
+
+ switch (chars[pos]) {
+ case '+':
+ case ',':
+ case ';':
+ // separator char has been found
+ return new String(chars, beg, end - beg);
+ case '\\':
+ // escaped char
+ chars[end++] = getEscaped();
+ pos++;
+ break;
+ case ' ':
+ // need to figure out whether space defines
+ // the end of attribute value or not
+ cur = end;
+
+ pos++;
+ chars[end++] = ' ';
+
+ for (; pos < length && chars[pos] == ' '; pos++) {
+ chars[end++] = ' ';
+ }
+ if (pos == length || chars[pos] == ',' || chars[pos] == '+'
+ || chars[pos] == ';') {
+ // separator char or the end of DN has been found
+ return new String(chars, beg, cur - beg);
+ }
+ break;
+ default:
+ chars[end++] = chars[pos];
+ pos++;
+ }
+ }
+ }
+
+ // returns escaped char
+ private char getEscaped()
+ {
+ pos++;
+ if (pos == length) {
+ throw new IllegalStateException("Unexpected end of DN: " + dn);
+ }
+
+ switch (chars[pos]) {
+ case '"':
+ case '\\':
+ case ',':
+ case '=':
+ case '+':
+ case '<':
+ case '>':
+ case '#':
+ case ';':
+ case ' ':
+ case '*':
+ case '%':
+ case '_':
+ //FIXME: escaping is allowed only for leading or trailing space char
+ return chars[pos];
+ default:
+ // RFC doesn't explicitly say that escaped hex pair is
+ // interpreted as UTF-8 char. It only contains an example of such DN.
+ return getUTF8();
+ }
+ }
+
+ // decodes UTF-8 char
+ // see http://www.unicode.org for UTF-8 bit distribution table
+ private char getUTF8()
+ {
+ int res = getByte(pos);
+ pos++; //FIXME tmp
+
+ if (res < 128) { // one byte: 0-7F
+ return (char) res;
+ }
+ else if (res >= 192 && res <= 247) {
+ int count;
+ if (res <= 223) { // two bytes: C0-DF
+ count = 1;
+ res = res & 0x1F;
+ }
+ else if (res <= 239) { // three bytes: E0-EF
+ count = 2;
+ res = res & 0x0F;
+ }
+ else { // four bytes: F0-F7
+ count = 3;
+ res = res & 0x07;
+ }
+ int b;
+ for (int i = 0; i < count; i++) {
+ pos++;
+ if (pos == length || chars[pos] != '\\') {
+ return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
+ }
+ pos++;
+
+ b = getByte(pos);
+ pos++; //FIXME tmp
+ if ((b & 0xC0) != 0x80) {
+ return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
+ }
+
+ res = (res << 6) + (b & 0x3F);
+ }
+ return (char) res;
+ }
+ else {
+ return 0x3F; //FIXME failed to decode UTF-8 char - return '?'
+ }
+ }
+
+ // Returns byte representation of a char pair
+ // The char pair is composed of DN char in
+ // specified 'position' and the next char
+ // According to BNF syntax:
+ // hexchar = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
+ // / "a" / "b" / "c" / "d" / "e" / "f"
+ private int getByte(int position)
+ {
+ if (position + 1 >= length) {
+ throw new IllegalStateException("Malformed DN: " + dn);
+ }
+
+ int b1;
+ int b2;
+
+ b1 = chars[position];
+ if (b1 >= '0' && b1 <= '9') {
+ b1 = b1 - '0';
+ }
+ else if (b1 >= 'a' && b1 <= 'f') {
+ b1 = b1 - 87; // 87 = 'a' - 10
+ }
+ else if (b1 >= 'A' && b1 <= 'F') {
+ b1 = b1 - 55; // 55 = 'A' - 10
+ }
+ else {
+ throw new IllegalStateException("Malformed DN: " + dn);
+ }
+
+ b2 = chars[position + 1];
+ if (b2 >= '0' && b2 <= '9') {
+ b2 = b2 - '0';
+ }
+ else if (b2 >= 'a' && b2 <= 'f') {
+ b2 = b2 - 87; // 87 = 'a' - 10
+ }
+ else if (b2 >= 'A' && b2 <= 'F') {
+ b2 = b2 - 55; // 55 = 'A' - 10
+ }
+ else {
+ throw new IllegalStateException("Malformed DN: " + dn);
+ }
+ return (b1 << 4) + b2;
+ }
+
+ /**
+ * Parses the DN and returns the most significant attribute value for an attribute type, or null
+ * if none found.
+ *
+ * @param attributeType attribute type to look for (e.g. "ca")
+ */
+ public String findMostSpecific(String attributeType)
+ {
+ // Initialize internal state.
+ pos = 0;
+ beg = 0;
+ end = 0;
+ cur = 0;
+ chars = dn.toCharArray();
+
+ String attType = nextAT();
+ if (attType == null) {
+ return null;
+ }
+ while (true) {
+ String attValue = "";
+
+ if (pos == length) {
+ return null;
+ }
+ switch (chars[pos]) {
+ case '"':
+ attValue = quotedAV();
+ break;
+ case '#':
+ attValue = hexAV();
+ break;
+ case '+':
+ case ',':
+ case ';': // compatibility with RFC 1779: semicolon can separate RDNs
+ //empty attribute value
+ break;
+ default:
+ attValue = escapedAV();
+ }
+
+ // Values are ordered from most specific to least specific
+ // due to the RFC2253 formatting. So take the first match
+ // we see.
+ if (attributeType.equalsIgnoreCase(attType)) {
+ return attValue;
+ }
+
+ if (pos >= length) {
+ return null;
+ }
+ if (chars[pos] == ',' || chars[pos] == ';') {
+ //Do nothing
+ } else if (chars[pos] != '+') {
+ throw new IllegalStateException("Malformed DN: " + dn);
+ }
+ pos++;
+ attType = nextAT();
+ if (attType == null) {
+ throw new IllegalStateException("Malformed DN: " + dn);
+ }
+ }
+ }
+}
diff --git a/presto-client/src/main/java/com/facebook/presto/client/okhttp3/internal/tls/LegacyHostnameVerifier.java b/presto-client/src/main/java/com/facebook/presto/client/okhttp3/internal/tls/LegacyHostnameVerifier.java
new file mode 100644
index 0000000000000..79aa87506ec89
--- /dev/null
+++ b/presto-client/src/main/java/com/facebook/presto/client/okhttp3/internal/tls/LegacyHostnameVerifier.java
@@ -0,0 +1,262 @@
+/*
+ * 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.facebook.presto.client.okhttp3.internal.tls;
+
+import okhttp3.internal.tls.OkHostnameVerifier;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.security.auth.x500.X500Principal;
+
+import java.security.cert.Certificate;
+import java.security.cert.CertificateParsingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.regex.Pattern;
+
+public class LegacyHostnameVerifier
+ implements HostnameVerifier
+{
+ private static final int ALT_DNS_NAME = 2;
+ private static final int ALT_IPA_NAME = 7;
+ private static final Pattern VERIFY_AS_IP_ADDRESS = Pattern.compile(
+ "([0-9a-fA-F]*:[0-9a-fA-F:.]*)|([\\d.]+)");
+
+ public static final HostnameVerifier INSTANCE = new LegacyHostnameVerifier();
+
+ private LegacyHostnameVerifier()
+ {
+ }
+
+ @Override
+ public boolean verify(String host, SSLSession session)
+ {
+ if (OkHostnameVerifier.INSTANCE.verify(host, session)) {
+ return true;
+ }
+
+ // the CN cannot be used with IP addresses
+ if (verifyAsIpAddress(host)) {
+ return false;
+ }
+
+ // try to verify using the legacy CN rules
+ try {
+ Certificate[] certificates = session.getPeerCertificates();
+ X509Certificate certificate = (X509Certificate) certificates[0];
+
+ // only use CN if there are no alt names
+ if (!allSubjectAltNames(certificate).isEmpty()) {
+ return false;
+ }
+
+ X500Principal principal = certificate.getSubjectX500Principal();
+ // RFC 2818 advises using the most specific name for matching.
+ String cn = new DistinguishedNameParser(principal).findMostSpecific("cn");
+ if (cn != null) {
+ return verifyHostName(host, cn);
+ }
+
+ return false;
+ }
+ catch (SSLException e) {
+ return false;
+ }
+ }
+
+ static boolean verifyAsIpAddress(String host)
+ {
+ return VERIFY_AS_IP_ADDRESS.matcher(host).matches();
+ }
+
+ /**
+ * Returns true if {@code certificate} matches {@code ipAddress}.
+ */
+ private boolean verifyIpAddress(String ipAddress, X509Certificate certificate)
+ {
+ List altNames = getSubjectAltNames(certificate, ALT_IPA_NAME);
+ for (int i = 0, size = altNames.size(); i < size; i++) {
+ if (ipAddress.equalsIgnoreCase(altNames.get(i))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean verifyHostName(String hostName, X509Certificate certificate)
+ {
+ hostName = hostName.toLowerCase(Locale.US);
+ boolean hasDns = false;
+ List altNames = getSubjectAltNames(certificate, ALT_DNS_NAME);
+ for (int i = 0, size = altNames.size(); i < size; i++) {
+ hasDns = true;
+ if (verifyHostName(hostName, altNames.get(i))) {
+ return true;
+ }
+ }
+
+ if (!hasDns) {
+ X500Principal principal = certificate.getSubjectX500Principal();
+ // RFC 2818 advises using the most specific name for matching.
+ String cn = new DistinguishedNameParser(principal).findMostSpecific("cn");
+ if (cn != null) {
+ return verifyHostName(hostName, cn);
+ }
+ }
+
+ return false;
+ }
+
+ public static List allSubjectAltNames(X509Certificate certificate)
+ {
+ List altIpaNames = getSubjectAltNames(certificate, ALT_IPA_NAME);
+ List altDnsNames = getSubjectAltNames(certificate, ALT_DNS_NAME);
+ List result = new ArrayList<>(altIpaNames.size() + altDnsNames.size());
+ result.addAll(altIpaNames);
+ result.addAll(altDnsNames);
+ return result;
+ }
+
+ private static List getSubjectAltNames(X509Certificate certificate, int type)
+ {
+ List result = new ArrayList<>();
+ try {
+ Collection> subjectAltNames = certificate.getSubjectAlternativeNames();
+ if (subjectAltNames == null) {
+ return Collections.emptyList();
+ }
+ for (Object subjectAltName : subjectAltNames) {
+ List> entry = (List>) subjectAltName;
+ if (entry == null || entry.size() < 2) {
+ continue;
+ }
+ Integer altNameType = (Integer) entry.get(0);
+ if (altNameType == null) {
+ continue;
+ }
+ if (altNameType == type) {
+ String altName = (String) entry.get(1);
+ if (altName != null) {
+ result.add(altName);
+ }
+ }
+ }
+ return result;
+ }
+ catch (CertificateParsingException e) {
+ return Collections.emptyList();
+ }
+ }
+
+ /**
+ * Returns {@code true} iff {@code hostName} matches the domain name {@code pattern}.
+ *
+ * @param hostName lower-case host name.
+ * @param pattern domain name pattern from certificate. May be a wildcard pattern such as
+ * {@code *.android.com}.
+ */
+ private boolean verifyHostName(String hostName, String pattern)
+ {
+ // Basic sanity checks
+ // Check length == 0 instead of .isEmpty() to support Java 5.
+ if ((hostName == null) || (hostName.length() == 0) || (hostName.startsWith("."))
+ || (hostName.endsWith(".."))) {
+ // Invalid domain name
+ return false;
+ }
+ if ((pattern == null) || (pattern.length() == 0) || (pattern.startsWith("."))
+ || (pattern.endsWith(".."))) {
+ // Invalid pattern/domain name
+ return false;
+ }
+
+ // Normalize hostName and pattern by turning them into absolute domain names if they are not
+ // yet absolute. This is needed because server certificates do not normally contain absolute
+ // names or patterns, but they should be treated as absolute. At the same time, any hostName
+ // presented to this method should also be treated as absolute for the purposes of matching
+ // to the server certificate.
+ // www.android.com matches www.android.com
+ // www.android.com matches www.android.com.
+ // www.android.com. matches www.android.com.
+ // www.android.com. matches www.android.com
+ if (!hostName.endsWith(".")) {
+ hostName += '.';
+ }
+ if (!pattern.endsWith(".")) {
+ pattern += '.';
+ }
+ // hostName and pattern are now absolute domain names.
+
+ pattern = pattern.toLowerCase(Locale.US);
+ // hostName and pattern are now in lower case -- domain names are case-insensitive.
+
+ if (!pattern.contains("*")) {
+ // Not a wildcard pattern -- hostName and pattern must match exactly.
+ return hostName.equals(pattern);
+ }
+ // Wildcard pattern
+
+ // WILDCARD PATTERN RULES:
+ // 1. Asterisk (*) is only permitted in the left-most domain name label and must be the
+ // only character in that label (i.e., must match the whole left-most label).
+ // For example, *.example.com is permitted, while *a.example.com, a*.example.com,
+ // a*b.example.com, a.*.example.com are not permitted.
+ // 2. Asterisk (*) cannot match across domain name labels.
+ // For example, *.example.com matches test.example.com but does not match
+ // sub.test.example.com.
+ // 3. Wildcard patterns for single-label domain names are not permitted.
+
+ if ((!pattern.startsWith("*.")) || (pattern.indexOf('*', 1) != -1)) {
+ // Asterisk (*) is only permitted in the left-most domain name label and must be the only
+ // character in that label
+ return false;
+ }
+
+ // Optimization: check whether hostName is too short to match the pattern. hostName must be at
+ // least as long as the pattern because asterisk must match the whole left-most label and
+ // hostName starts with a non-empty label. Thus, asterisk has to match one or more characters.
+ if (hostName.length() < pattern.length()) {
+ // hostName too short to match the pattern.
+ return false;
+ }
+
+ if ("*.".equals(pattern)) {
+ // Wildcard pattern for single-label domain name -- not permitted.
+ return false;
+ }
+
+ // hostName must end with the region of pattern following the asterisk.
+ String suffix = pattern.substring(1);
+ if (!hostName.endsWith(suffix)) {
+ // hostName does not end with the suffix
+ return false;
+ }
+
+ // Check that asterisk did not match across domain name labels.
+ int suffixStartIndexInHostName = hostName.length() - suffix.length();
+ if ((suffixStartIndexInHostName > 0)
+ && (hostName.lastIndexOf('.', suffixStartIndexInHostName - 1) != -1)) {
+ // Asterisk is matching across domain name labels -- not permitted.
+ return false;
+ }
+
+ // hostName matches pattern
+ return true;
+ }
+}
diff --git a/presto-common/src/main/java/com/facebook/presto/common/TelemetryConfig.java b/presto-common/src/main/java/com/facebook/presto/common/TelemetryConfig.java
new file mode 100644
index 0000000000000..bab321feb769d
--- /dev/null
+++ b/presto-common/src/main/java/com/facebook/presto/common/TelemetryConfig.java
@@ -0,0 +1,183 @@
+/*
+ * 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.facebook.presto.common;
+
+import java.util.Map;
+
+import static java.util.Objects.nonNull;
+import static java.util.Objects.requireNonNull;
+
+/**
+ * The type TelemetryConfig to store all the values in telemetry.properties.
+ */
+public class TelemetryConfig
+{
+ private static TelemetryConfig telemetryConfig;
+
+ private String tracingBackendUrl;
+ private Integer maxExporterBatchSize;
+ private Integer maxQueueSize;
+ private Integer exporterTimeout;
+ private Integer scheduleDelay;
+ private Double samplingRatio;
+ private Boolean tracingEnabled = false;
+ private Boolean spanSampling = false;
+
+ /**
+ * The type Telemetry config constants.
+ */
+ public static class TelemetryConfigConstants
+ {
+ private static final String TRACING_ENABLED = "tracing-enabled";
+ private static final String TRACING_BACKEND_URL = "tracing-backend-url";
+ private static final String MAX_EXPORTER_BATCH_SIZE = "max-exporter-batch-size";
+ private static final String MAX_QUEUE_SIZE = "max-queue-size";
+ private static final String SCHEDULE_DELAY = "schedule-delay";
+ private static final String EXPORTER_TIMEOUT = "exporter-timeout";
+ private static final String TRACE_SAMPLING_RATIO = "trace-sampling-ratio";
+ private static final String SPAN_SAMPLING = "span-sampling";
+ }
+
+ private TelemetryConfig()
+ {
+ }
+
+ /**
+ * Gets telemetry config.
+ *
+ * @return the telemetry config
+ */
+ public static TelemetryConfig getTelemetryConfig()
+ { // prevent multiple instance creation
+ telemetryConfig = nonNull(telemetryConfig) ? telemetryConfig : new TelemetryConfig();
+ return telemetryConfig;
+ }
+
+ /**
+ * Sets telemetry properties.
+ *
+ * @param telemetryProperties the telemetry properties
+ */
+ public void setTelemetryProperties(Map telemetryProperties)
+ {
+ tracingBackendUrl = requireNonNull(telemetryProperties.get(TelemetryConfigConstants.TRACING_BACKEND_URL), "exporter endpoint cant be null");
+ maxQueueSize = Integer.valueOf(requireNonNull(telemetryProperties.get(TelemetryConfigConstants.MAX_QUEUE_SIZE), "max queue size cant be null"));
+ maxExporterBatchSize = Integer.valueOf(requireNonNull(telemetryProperties.get(TelemetryConfigConstants.MAX_EXPORTER_BATCH_SIZE), "max exporter batch size cant be null"));
+ exporterTimeout = Integer.valueOf(requireNonNull(telemetryProperties.get(TelemetryConfigConstants.EXPORTER_TIMEOUT), "exporter timeout cant be null"));
+ tracingEnabled = Boolean.valueOf(requireNonNull(telemetryProperties.get(TelemetryConfigConstants.TRACING_ENABLED), "trace enabled cant be null"));
+ scheduleDelay = Integer.valueOf(requireNonNull(telemetryProperties.get(TelemetryConfigConstants.SCHEDULE_DELAY), "schedule delay cant be null"));
+ samplingRatio = Double.valueOf(requireNonNull(telemetryProperties.get(TelemetryConfigConstants.TRACE_SAMPLING_RATIO), "sampling ratio cant be null"));
+ spanSampling = Boolean.valueOf(requireNonNull(telemetryProperties.get(TelemetryConfigConstants.SPAN_SAMPLING), "span sampling must be provided"));
+ }
+
+ /**
+ * Sets tracing enabled. For dynamically enable/disable from /v1/telemetry/config endpoint
+ *
+ * @param tracingEnabled the tracing enabled
+ */
+ public void setTracingEnabled(Boolean tracingEnabled)
+ {
+ getTelemetryConfig().tracingEnabled = tracingEnabled;
+ }
+
+ /**
+ * Sets span sampling.
+ *
+ * @param spanSampling the span sampling
+ */
+ public void setSpanSampling(Boolean spanSampling)
+ {
+ getTelemetryConfig().spanSampling = spanSampling;
+ }
+
+ /**
+ * Gets exporter endpoint.
+ *
+ * @return the exporter endpoint
+ */
+ public String getTracingBackendUrl()
+ {
+ return this.tracingBackendUrl;
+ }
+
+ /**
+ * Gets max exporter batch size.
+ *
+ * @return the max exporter batch size
+ */
+ public Integer getMaxExporterBatchSize()
+ {
+ return this.maxExporterBatchSize;
+ }
+
+ /**
+ * Gets max queue size.
+ *
+ * @return the max queue size
+ */
+ public Integer getMaxQueueSize()
+ {
+ return this.maxQueueSize;
+ }
+
+ /**
+ * Gets exporter timeout.
+ *
+ * @return the exporter timeout
+ */
+ public Integer getExporterTimeout()
+ {
+ return this.exporterTimeout;
+ }
+
+ /**
+ * Gets schedule delay.
+ *
+ * @return the schedule delay
+ */
+ public Integer getScheduleDelay()
+ {
+ return this.scheduleDelay;
+ }
+
+ /**
+ * Gets sampling ratio.
+ *
+ * @return the sampling ratio
+ */
+ public Double getSamplingRatio()
+ {
+ return this.samplingRatio;
+ }
+
+ /**
+ * Gets tracing enabled.
+ *
+ * @return the tracing enabled
+ */
+ public static Boolean getTracingEnabled()
+ {
+ return getTelemetryConfig().tracingEnabled;
+ }
+
+ /**
+ * Gets span sampling.
+ *
+ * @return the span sampling
+ */
+ public static Boolean getSpanSampling()
+ {
+ return getTelemetryConfig().spanSampling;
+ }
+}
diff --git a/presto-common/src/main/java/com/facebook/presto/common/TracingConfig.java b/presto-common/src/main/java/com/facebook/presto/common/TracingConfig.java
new file mode 100644
index 0000000000000..f05834e52adbc
--- /dev/null
+++ b/presto-common/src/main/java/com/facebook/presto/common/TracingConfig.java
@@ -0,0 +1,51 @@
+/*
+ * 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.facebook.presto.common;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import javax.annotation.concurrent.Immutable;
+
+/**
+ * The type Tracing config.
+ */
+@Immutable
+public class TracingConfig
+{
+ private boolean tracingEnabled;
+
+ /**
+ * Instantiates a new Tracing config.
+ *
+ * @param tracingEnabled the tracing enabled
+ */
+ @JsonCreator
+ public TracingConfig(
+ @JsonProperty("tracingEnabled") boolean tracingEnabled)
+ {
+ this.tracingEnabled = tracingEnabled;
+ }
+
+ /**
+ * Is tracing enabled boolean.
+ *
+ * @return the boolean
+ */
+ @JsonProperty
+ public boolean isTracingEnabled()
+ {
+ return tracingEnabled;
+ }
+}
diff --git a/presto-common/src/main/java/com/facebook/presto/common/telemetry/tracing/TracingEnum.java b/presto-common/src/main/java/com/facebook/presto/common/telemetry/tracing/TracingEnum.java
new file mode 100644
index 0000000000000..100774a3aa32a
--- /dev/null
+++ b/presto-common/src/main/java/com/facebook/presto/common/telemetry/tracing/TracingEnum.java
@@ -0,0 +1,206 @@
+/*
+ * 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.facebook.presto.common.telemetry.tracing;
+
+public enum TracingEnum
+{
+ ROOT("POST /v1/statement", ""),
+ QUERY("query", ""),
+ DISPATCH("dispatch", ""),
+ ANALYZER("analyzer", ""),
+ ANALYZE("analyze", ""),
+ PLANNER("planner", ""),
+ SCHEDULER("scheduler", ""),
+ QUERY_START("query_start", ""),
+ TASK("task", ""),
+ SPLIT("split", ""),
+ PIPELINE("pipeline", ""),
+ REMOTE_TASK("remote-task", ""),
+ LIST_SCHEMA_NAMES("listSchemaNames", ""),
+ GET_TABLE_HANDLE_FOR_STATISTICS_COLLECTION("getTableHandleForStatisticsCollection", ""),
+ GET_HANDLE_VERSION("getHandleVersion", ""),
+ GET_SYSTEM_TABLE("getSystemTable", ""),
+ GET_LAYOUT("getLayout", ""),
+ GET_ALTERNATE_TABLE_HANDLE("getAlternativeTableHandle", ""),
+ IS_LEGACY_GET_LAYOUT_SUPPORTED("isLegacyGetLayoutSupported", ""),
+ GET_COMMON_PARTITIONING("getCommonPartitioning", ""),
+ IS_REFINED_PARTITIONING_OVER("isRefinedPartitioningOver", ""),
+ GET_PARTITIONING_HANDLE("getPartitioningHandleForExchange", ""),
+ GET_PARTITIONING_HANDLE_CTE("getPartitioningHandleForCteMaterialization", ""),
+ GET_INFO("getInfo", ""),
+ CHECK_CAN_ADD_COLUMNS("checkCanAddColumns", ""),
+ GET_TABLE_METADATA("getTableMetadata", ""),
+ GET_TABLE_STATISTICS("getTableStatistics", ""),
+ GET_COLUMN_HANDLES("getColumnHandles", ""),
+ GET_COLUMN_METADATA("getColumnMetadata", ""),
+ EXPLAIN_IO_CONSTRAINTS("toExplainIOConstraints", ""),
+ LIST_TABLES("Metadata.listTables", ""),
+ LIST_TABLE_COLUMNS("Metadata.listTableColumns", ""),
+ CREATE_SCHEMA("createSchema", ""),
+ DROP_SCHEMA("Metadata.dropSchema", ""),
+ RENAME_SCHEMA("Metadata.renameSchema", ""),
+ CREATE_TABLE("Metadata.createTable", ""),
+ CREATE_TEMPORARY_TABLE("Metadata.createTemporaryTable", ""),
+ CREATE_CONNECTOR_PARTITIONING_METADATA("createConnectorPartitioningMetadata", ""),
+ RENAME_TABLE("Metadata.renameTable", ""),
+ RENAME_COLUMN("renameColumn", ""),
+ ADD_COLUMN("addColumn", ""),
+ DROP_COLUMN("dropColumn", ""),
+ SET_COLUMN_TYPE("setColumnType", ""),
+ DROP_TABLE("dropTable", ""),
+ TRUNCATE_TABLE("truncateTable", ""),
+ GET_INSERT_LAYOUT("getInsertLayout", ""),
+ GET_PREFERRED_SHUFFLED_LAYOUT_FOR_INSERT("getPreferredShuffleLayoutForInsert", ""),
+ GET_STATISTICS_COLLECTION_METADATA_FOR_WRITE("Metadata.getStatisticsCollectionMetadataForWrite", ""),
+ GET_STATISTICS_COLLECTION_METADATA("Metadata.getStatisticsCollectionMetadata", ""),
+ BEGIN_STATISTICS_COLLECTION("beginStatisticsCollection", ""),
+ FINISH_STATISTICS_COLLECTION("finishStatisticsCollection", ""),
+ GET_NEW_TABLE_LAYOUT("getNewTableLayout", ""),
+ GET_PREFERRED_SHUFFLE_LAYOUT_FOR_NEW_TABLE("getPreferredShuffleLayoutForNewTable", ""),
+ BEGIN_QUERY("beginQuery", ""),
+ REGISTER_CATALOG_FOR_QUERY_ID("registerCatalogForQueryId", ""),
+ CLEAN_UP_QUERY("cleanupQuery", ""),
+ BEGIN_CREATE_TABLE("Metadata.beginCreateTable", ""),
+ FINISH_CREATE_TABLE("finishCreateTable", ""),
+ BEGIN_INSERT("beginInsert", ""),
+ FINISH_INSERT("finishInsert", ""),
+ GET_DELETE_ROW_ID_COLUMN_HANDLE("getDeleteRowIdColumnHandle", ""),
+ GET_UPDATE_ROW_ID_COLUMN_HANDLE("getUpdateRowIdColumnHandle", ""),
+ SUPPORTS_METADATA_DELETE("supportsMetadataDelete", ""),
+ METADATA_DELETE("metadataDelete", ""),
+ BEGIN_DELETE("beginDelete", ""),
+ FINISH_DELETE("finishDelete", ""),
+ BEGIN_UPDATE("beginUpdate", ""),
+ FINISH_UPDATE("finishUpdate", ""),
+ GET_CATALOG_HANDLE("Metadata.getCatalogHandle", ""),
+ GET_CATALOG_NAMES("getCatalogNames", ""),
+ LIST_VIEWS("Metadata.listViews", ""),
+ GET_VIEWS("Metadata.getViews", ""),
+ CREATE_VIEW("Metadata.createView", ""),
+ DROP_VIEW("Metadata.dropView", ""),
+ RENAME_VIEW("renameView", ""),
+ CREATE_MATERIALIZED_VIEW("Metadata.createMaterializedView", ""),
+ DROP_MATERIALIZED_VIEW("Metadata.dropMaterializedView", ""),
+ GET_MATERIALIZED_VIEW_STATUS("Metadata.getMaterializedViewStatus", ""),
+ BEGIN_REFRESH_MATERIALIZED_VIEW("beginRefreshMaterializedView", ""),
+ FINISH_REFRESH_MATERIALIZED_VIEW("finishRefreshMaterializedView", ""),
+ GET_REFERENCED_MATERIALIZED_VIEWS("Metadata.getReferencedMaterializedViews", ""),
+ RESOLVE_INDEX("resolveIndex", ""),
+ CREATE_ROLE("createRole", ""),
+ DROP_ROLE("dropRole", ""),
+ LIST_ROLES("listRoles", ""),
+ LIST_ROLE_GRANTS("listRoleGrants", ""),
+ GRANT_ROLES("grantRoles", ""),
+ REVOKE_ROLES("revokeRoles", ""),
+ LIST_APPLICABLE_ROLES("listApplicableRoles", ""),
+ LIST_ENABLED_ROLES("listEnabledRoles", ""),
+ GRANT_TABLE_PRIVILEGES("Metadata.grantTablePrivileges", ""),
+ REVOKE_TABLE_PRIVILEGES("Metadata.revokeTablePrivileges", ""),
+ LIST_TABLE_PRIVILEGES("Metadata.listTablePrivileges", ""),
+ COMMIT_PAGE_SINK_ASYNC("commitPageSinkAsync", ""),
+ GET_METADATA_UPDATE_RESULTS("getMetadataUpdateResults", ""),
+ GET_METADATA_RESOLVER("getMetadataResolver", ""),
+ CATALOG_EXISTS("Metadata.catalogExists", ""),
+ SCHEMA_EXISTS("Metadata.schemaExists", ""),
+ TABLE_EXISTS("Metadata.tableExists", ""),
+ GET_TABLE_HANDLE("Metadata.getTableHandle", ""),
+ GET_COLUMNS("getColumns", ""),
+ GET_VIEW("Metadata.getView", ""),
+ GET_MATERIALIZED_VIEW("Metadata.getMaterializedView", ""),
+ GET_CONNECTOR_CAPABILITIES("getConnectorCapabilities", ""),
+ GET_TABLE_LAYOUT_FILTER_COVERAGE("getTableLayoutFilterCoverage", ""),
+ DROP_CONSTRAINT("dropConstraint", ""),
+ ADD_CONSTRAINT("addConstraint", ""),
+ DESERIALIZE_VIEW("deserializeView", ""),
+ GET_CATALOG_METADATA("getCatalogMetadata", ""),
+ GET_CATALOG_METADATA_FOR_WRITE("Metadata.getCatalogMetadataForWrite", ""),
+ GET_METADATA("getMetadata", ""),
+ GET_METADATA_FOR_WRITE("getMetadataForWrite", ""),
+ CAN_RESOLVE_OPERATOR("canResolveOperator", ""),
+ RESOLVE_TABLE_LAYOUT("resolveTableLayout", ""),
+ GET_CATALOGS_BY_QUERY_ID("getCatalogsByQueryId", ""),
+ ADD_SYSTEM_ACCESS_CONTROL_FACTORY("addSystemAccessControlFactory", ""),
+ ADD_CATALOG_ACCESS_CONTROL("addCatalogAccessControl", ""),
+ REMOVE_CATALOG_ACCESS_CONTROL("removeCatalogAccessControl", ""),
+ LOAD_CATALOG_ACCESS_CONTROL("loadSystemAccessControl", ""),
+ STAGE("stage", ""),
+ LOAD_SYSTEM_ACCESS_CONTROL("loadSystemAccessControl", ""),
+ SET_SYSTEM_ACCESS_CONTROL("setSystemAccessControl", ""),
+ CHECK_CAN_SET_USER("checkCanSetUser", ""),
+ SELECT_AUTHORIZED_IDENTITY("selectAuthorizedIdentity", ""),
+ CHECK_QUERY_INTEGRITY("checkQueryIntegrity", ""),
+ FILTER_CATALOGS("filterCatalogs", ""),
+ CHECK_CAN_ACCESS_CATALOG("checkCanAccessCatalog", ""),
+ CHECK_CAN_CREATE_SCHEMA("checkCanCreateSchema", ""),
+ CHECK_CAN_DROP_SCHEMA("checkCanDropSchema", ""),
+ CHECK_CAN_RENAME_SCHEMA("checkCanRenameSchema", ""),
+ CHECK_CAN_SHOW_SCHEMAS("checkCanShowSchemas", ""),
+ FILTER_SCHEMAS("filterSchemas", ""),
+ CHECK_CAN_SHOW_CREATE_TABLE("checkCanShowCreateTable", ""),
+ CHECK_CAN_CREATE_TABLE("checkCanCreateTable", ""),
+ CHECK_CAN_DROP_TABLE("checkCanDropTable", ""),
+ CHECK_CAN_RENAME_TABLE("checkCanRenameTable", ""),
+ CHECK_CAN_SHOW_TABLES_METADATA("checkCanShowTablesMetadata", ""),
+ FILTER_TABLES("filterTables", ""),
+ CHECK_CAN_SHOW_COLUMNS_METADATA("checkCanShowColumnsMetadata", ""),
+ FILTER_COLUMNS("filterColumns", ""),
+ CHECK_CAN_ALTER_COLUMN("checkCanAlterColumn", ""),
+ CHECK_CAN_DROP_COLUMN("checkCanDropColumn", ""),
+ CHECK_CAN_INSERT_INTO_TABLE("checkCanInsertIntoTable", ""),
+ CHECK_CAN_RENAME_COLUMN("checkCanRenameColumn", ""),
+ CHECK_CAN_DELETE_FROM_TABLE("checkCanDeleteFromTable", ""),
+ CHECK_CAN_TRUNCATE_TABLE("checkCanTruncateTable", ""),
+ CHECK_CAN_UPDATE_TABLE_COLUMNS("checkCanUpdateTableColumns", ""),
+ CHECK_CAN_CREATE_VIEW("checkCanCreateView", ""),
+ CHECK_CAN_DROP_VIEW("checkCanDropView", ""),
+ CHECK_CAN_RENAME_VIEW("checkCanRenameView", ""),
+ CHECK_CAN_CREATE_VIEW_WITH_SELECT_FROM_COLUMNS("checkCanCreateViewWithSelectFromColumns", ""),
+ CHECK_CAN_GRANT_TABLE_PRIVILEGE("checkCanGrantTablePrivilege", ""),
+ CHECK_CAN_REVOKE_TABLE_PRIVILEGE("checkCanRevokeTablePrivilege", ""),
+ CHECK_CAN_SET_SYSTEM_SESSION_PROPERTY("checkCanSetSystemSessionProperty", ""),
+ CHECK_CAN_SET_CATALOG_SESSION_PROPERTY("checkCanSetCatalogSessionProperty", ""),
+ CHECK_CAN_SELECT_FROM_COLUMNS("checkCanSelectFromColumns", ""),
+ CHECK_CAN_CREATE_ROLE("checkCanCreateRole", ""),
+ CHECK_CAN_DROP_ROLE("checkCanDropRole", ""),
+ CHECK_CAN_GRANT_ROLES("checkCanGrantRoles", ""),
+ CHECK_CAN_REVOKE_ROLES("checkCanRevokeRoles", ""),
+ CHECK_CAN_SET_ROLE("checkCanSetRole", ""),
+ CHECK_CAN_SHOW_ROLES("checkCanShowRoles", ""),
+ CHECK_CAN_SHOW_CURRENT_ROLES("checkCanShowCurrentRoles", ""),
+ CHECK_CAN_SHOW_ROLE_GRANTS("checkCanShowRoleGrants", ""),
+ GET_ROW_FILTERS("getRowFilters", ""),
+ GET_COLUMN_MASKS("getColumnMasks", ""),
+ CHECK_CAN_DROP_CONSTRAINT("checkCanDropConstraint", ""),
+ CHECK_CAN_ADD_CONSTRAINTS("checkCanAddConstraints", ""),
+ GET_CONNECTOR_ACCESS_CONTROL("getConnectorAccessControl", "");
+
+ private final String name;
+ private final String description;
+
+ TracingEnum(String name, String description)
+ {
+ this.name = name;
+ this.description = description;
+ }
+
+ public String getName()
+ {
+ return this.name;
+ }
+
+ public String getDescription()
+ {
+ return this.description;
+ }
+}
diff --git a/presto-common/src/test/java/com/facebook/presto/common/TestTelemetryConfig.java b/presto-common/src/test/java/com/facebook/presto/common/TestTelemetryConfig.java
new file mode 100644
index 0000000000000..ac86f360a7fd7
--- /dev/null
+++ b/presto-common/src/test/java/com/facebook/presto/common/TestTelemetryConfig.java
@@ -0,0 +1,51 @@
+/*
+ * 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.facebook.presto.common;
+
+import com.google.common.collect.ImmutableMap;
+import org.testng.annotations.Test;
+
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+
+public class TestTelemetryConfig
+{
+ @Test
+ public void testExplicitPropertyMappings()
+ {
+ Map properties = new ImmutableMap.Builder()
+ .put("tracing-factory.name", "otltest")
+ .put("tracing-enabled", "false")
+ .put("tracing-backend-url", "http://0.0.0.0:123")
+ .put("max-exporter-batch-size", "123")
+ .put("max-queue-size", "1234")
+ .put("schedule-delay", "4567")
+ .put("exporter-timeout", "6789")
+ .put("trace-sampling-ratio", "2.0")
+ .put("span-sampling", "false")
+ .build();
+
+ TelemetryConfig.getTelemetryConfig().setTelemetryProperties(properties);
+ TelemetryConfig telemetryConfig = TelemetryConfig.getTelemetryConfig();
+ assertEquals(TelemetryConfig.getTracingEnabled(), false);
+ assertEquals(telemetryConfig.getTracingBackendUrl(), "http://0.0.0.0:123");
+ assertEquals(telemetryConfig.getMaxExporterBatchSize(), 123);
+ assertEquals(telemetryConfig.getMaxQueueSize(), 1234);
+ assertEquals(telemetryConfig.getScheduleDelay(), 4567);
+ assertEquals(telemetryConfig.getExporterTimeout(), 6789);
+ assertEquals(telemetryConfig.getSamplingRatio(), 2.0);
+ assertEquals(TelemetryConfig.getSpanSampling(), false);
+ }
+}
diff --git a/presto-docs/src/main/sphinx/plugin.rst b/presto-docs/src/main/sphinx/plugin.rst
index 7f4e7883028e4..888fb304a6e7a 100644
--- a/presto-docs/src/main/sphinx/plugin.rst
+++ b/presto-docs/src/main/sphinx/plugin.rst
@@ -8,4 +8,5 @@ This chapter outlines the plugins in Presto that are available for various use c
:maxdepth: 1
plugin/redis-hbo-provider
+ plugin/open-telemetry
diff --git a/presto-docs/src/main/sphinx/plugin/open-telemetry.rst b/presto-docs/src/main/sphinx/plugin/open-telemetry.rst
new file mode 100644
index 0000000000000..dc86b369cce52
--- /dev/null
+++ b/presto-docs/src/main/sphinx/plugin/open-telemetry.rst
@@ -0,0 +1,27 @@
+==============
+Open Telemetry
+==============
+OpenTelemetry is a powerful serviceability framework that helps us gain insights into the performance and behavior of the systems. It facilitates generation, collection, and management of telemetry data
+such as traces and metrics to observability dashboards.
+
+Configuration
+-------------
+
+To enable this feature set ``tracing-enabled`` to ``true`` and set the path for ``tracing-backend-url`` in ``etc/telemetry-tracing.properties`` .
+
+Configuration properties
+------------------------
+
+============================================ ================================================================================================ ==================
+Property Name Description Default Values
+============================================ ================================================================================================ ==================
+``tracing-factory.name`` Unique identifier for factory implementation to be registered. otel
+``tracing-enabled`` Boolean value controlling if tracing is on or off. false
+``tracing-backend-url`` URL of the backend for exporting telemetry data.
+``max-exporter-batch-size`` Maximum number of spans to export in one batch. 256
+``max-queue-size`` Maximum number of spans to queue before processing for export. 1024
+``schedule-delay`` Delay between batches of span export, controlling how frequently spans are exported. 1000
+``exporter-timeout`` How long the span exporter waits for a batch of spans to be successfully sent before timing out. 1024
+``trace-sampling-ratio`` Double between 0.0 and 1.0 to specify the percentage of queries to be traced. 1.0
+``span-sampling`` Boolean to enable/disable sampling. If enabled, spans are only generated for major operations. false
+============================================ ================================================================================================ ==================
\ No newline at end of file
diff --git a/presto-hive/src/test/java/com/facebook/presto/hive/AbstractTestHiveClient.java b/presto-hive/src/test/java/com/facebook/presto/hive/AbstractTestHiveClient.java
index 28c4fc5146388..2d58226629b02 100644
--- a/presto-hive/src/test/java/com/facebook/presto/hive/AbstractTestHiveClient.java
+++ b/presto-hive/src/test/java/com/facebook/presto/hive/AbstractTestHiveClient.java
@@ -1165,12 +1165,6 @@ public Locale getLocale()
return session.getLocale();
}
- @Override
- public Optional getTraceToken()
- {
- return session.getTraceToken();
- }
-
@Override
public Optional getClientInfo()
{
diff --git a/presto-hive/src/test/java/com/facebook/presto/hive/HiveQueryRunner.java b/presto-hive/src/test/java/com/facebook/presto/hive/HiveQueryRunner.java
index 8cf90df570ccb..afa6f0c0c3e24 100644
--- a/presto-hive/src/test/java/com/facebook/presto/hive/HiveQueryRunner.java
+++ b/presto-hive/src/test/java/com/facebook/presto/hive/HiveQueryRunner.java
@@ -193,8 +193,6 @@ public static DistributedQueryRunner createQueryRunner(
Map systemProperties = ImmutableMap.builder()
.put("task.writer-count", "2")
.put("task.partitioned-writer-count", "4")
- .put("tracing.tracer-type", "simple")
- .put("tracing.enable-distributed-tracing", "simple")
.putAll(extraProperties)
.build();
diff --git a/presto-jdbc/src/main/java/com/facebook/presto/jdbc/PrestoConnection.java b/presto-jdbc/src/main/java/com/facebook/presto/jdbc/PrestoConnection.java
index 1f3f760631850..14dc8f341bbaf 100644
--- a/presto-jdbc/src/main/java/com/facebook/presto/jdbc/PrestoConnection.java
+++ b/presto-jdbc/src/main/java/com/facebook/presto/jdbc/PrestoConnection.java
@@ -764,7 +764,6 @@ else if (applicationName != null) {
source = applicationName;
}
- Optional traceToken = Optional.ofNullable(clientInfo.get("TraceToken"));
Iterable clientTags = Splitter.on(',').trimResults().omitEmptyStrings()
.split(nullToEmpty(clientInfo.get("ClientTags")));
@@ -779,7 +778,6 @@ else if (applicationName != null) {
httpUri,
user,
source,
- traceToken,
ImmutableSet.copyOf(clientTags),
clientInfo.get("ClientInfo"),
catalog.get(),
diff --git a/presto-jdbc/src/test/java/com/facebook/presto/jdbc/TestPrestoDatabaseMetaData.java b/presto-jdbc/src/test/java/com/facebook/presto/jdbc/TestPrestoDatabaseMetaData.java
index 17e64f99121ab..a3c27a645c3fc 100644
--- a/presto-jdbc/src/test/java/com/facebook/presto/jdbc/TestPrestoDatabaseMetaData.java
+++ b/presto-jdbc/src/test/java/com/facebook/presto/jdbc/TestPrestoDatabaseMetaData.java
@@ -165,7 +165,6 @@ public void testGetClientInfoProperties()
assertEquals(resultSet.getString(4), "Comma-delimited string of tags for the session");
assertTrue(resultSet.next());
- assertEquals(resultSet.getString(1), "TraceToken");
assertEquals(resultSet.getInt(2), MAX_LENGTH);
assertNull(resultSet.getString(3));
assertEquals(resultSet.getString(4), "Sets the trace token of the session");
diff --git a/presto-main/etc/config.properties b/presto-main/etc/config.properties
index a120422c4b6f1..72f1ee017a711 100644
--- a/presto-main/etc/config.properties
+++ b/presto-main/etc/config.properties
@@ -51,7 +51,8 @@ plugin.bundles=\
../presto-node-ttl-fetchers/pom.xml,\
../presto-hive-function-namespace/pom.xml,\
../presto-delta/pom.xml,\
- ../presto-hudi/pom.xml
+ ../presto-hudi/pom.xml,\
+ ../presto-open-telemetry/pom.xml
presto.version=testversion
node-scheduler.include-coordinator=true
diff --git a/presto-main/etc/log.properties b/presto-main/etc/log.properties
index d9790f7ed5795..6c821bf33ab4b 100644
--- a/presto-main/etc/log.properties
+++ b/presto-main/etc/log.properties
@@ -9,3 +9,4 @@ com.facebook.presto=INFO
com.sun.jersey.guice.spi.container.GuiceComponentProviderFactory=WARN
com.ning.http.client=WARN
com.facebook.presto.server.PluginManager=DEBUG
+io.opentelemetry=DEBUG
\ No newline at end of file
diff --git a/presto-main/etc/telemetry-tracing.properties b/presto-main/etc/telemetry-tracing.properties
new file mode 100644
index 0000000000000..6f7b58c8fe01e
--- /dev/null
+++ b/presto-main/etc/telemetry-tracing.properties
@@ -0,0 +1,18 @@
+# unique identifier for factory implementation to be registered
+tracing-factory.name=otel
+# boolean value controlling if tracing is on or off
+tracing-enabled=false
+# points to backend for exporting telemetry data
+tracing-backend-url=http://localhost:4317
+# maximum number of spans that will be exported in one batch
+max-exporter-batch-size=256
+# maximum number of spans that can be queued before being processed for export
+max-queue-size=1024
+# delay between batches of span export, controlling how frequently spans are exported
+schedule-delay=1000
+# how long the span exporter will wait for a batch of spans to be successfully sent before timing out
+exporter-timeout=1024
+# double between 0.0 and 1.0 to specify the percentage of queries to be traced
+trace-sampling-ratio=1.0
+# boolean to enable/disable sampling. If enabled, spans are only generated for major operations
+span-sampling=false
\ No newline at end of file
diff --git a/presto-main/src/main/java/com/facebook/presto/FullConnectorSession.java b/presto-main/src/main/java/com/facebook/presto/FullConnectorSession.java
index 2ece57e7c1811..fd7898000dc2f 100644
--- a/presto-main/src/main/java/com/facebook/presto/FullConnectorSession.java
+++ b/presto-main/src/main/java/com/facebook/presto/FullConnectorSession.java
@@ -120,12 +120,6 @@ public long getStartTime()
return session.getStartTime();
}
- @Override
- public Optional getTraceToken()
- {
- return session.getTraceToken();
- }
-
@Override
public Optional getClientInfo()
{
@@ -179,7 +173,6 @@ public String toString()
.add("queryId", getQueryId())
.add("user", getUser())
.add("source", getSource().orElse(null))
- .add("traceToken", getTraceToken().orElse(null))
.add("timeZoneKey", getTimeZoneKey())
.add("locale", getLocale())
.add("startTime", getStartTime())
diff --git a/presto-main/src/main/java/com/facebook/presto/Session.java b/presto-main/src/main/java/com/facebook/presto/Session.java
index 8ccca2db4d3de..6349387ba0038 100644
--- a/presto-main/src/main/java/com/facebook/presto/Session.java
+++ b/presto-main/src/main/java/com/facebook/presto/Session.java
@@ -35,10 +35,11 @@
import com.facebook.presto.spi.security.SelectedRole;
import com.facebook.presto.spi.session.ResourceEstimates;
import com.facebook.presto.spi.session.SessionPropertyConfigurationManager.SystemSessionPropertyConfiguration;
-import com.facebook.presto.spi.tracing.Tracer;
+import com.facebook.presto.spi.telemetry.BaseSpan;
import com.facebook.presto.sql.analyzer.CTEInformationCollector;
import com.facebook.presto.sql.planner.optimizations.OptimizerInformationCollector;
import com.facebook.presto.sql.planner.optimizations.OptimizerResultCollector;
+import com.facebook.presto.telemetry.TracingManager;
import com.facebook.presto.transaction.TransactionManager;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -75,6 +76,8 @@
public final class Session
{
private final QueryId queryId;
+ private final BaseSpan querySpan;
+ private final BaseSpan rootSpan;
private final Optional transactionId;
private final boolean clientTransactionSupport;
private final Identity identity;
@@ -86,7 +89,6 @@ public final class Session
private final Optional remoteUserAddress;
private final Optional userAgent;
private final Optional clientInfo;
- private final Optional traceToken;
private final Set clientTags;
private final ResourceEstimates resourceEstimates;
private final long startTime;
@@ -97,7 +99,6 @@ public final class Session
private final Map preparedStatements;
private final Map sessionFunctions;
private final AccessControlContext context;
- private final Optional tracer;
private final WarningCollector warningCollector;
private final RuntimeStats runtimeStats;
private final Optional queryType;
@@ -110,13 +111,14 @@ public final class Session
public Session(
QueryId queryId,
+ BaseSpan querySpan,
+ BaseSpan rootSpan,
Optional transactionId,
boolean clientTransactionSupport,
Identity identity,
Optional source,
Optional catalog,
Optional schema,
- Optional traceToken,
TimeZoneKey timeZoneKey,
Locale locale,
Optional remoteUserAddress,
@@ -131,19 +133,19 @@ public Session(
SessionPropertyManager sessionPropertyManager,
Map preparedStatements,
Map sessionFunctions,
- Optional tracer,
WarningCollector warningCollector,
RuntimeStats runtimeStats,
Optional queryType)
{
this.queryId = requireNonNull(queryId, "queryId is null");
+ this.querySpan = querySpan;
+ this.rootSpan = rootSpan;
this.transactionId = requireNonNull(transactionId, "transactionId is null");
this.clientTransactionSupport = clientTransactionSupport;
this.identity = requireNonNull(identity, "identity is null");
this.source = requireNonNull(source, "source is null");
this.catalog = requireNonNull(catalog, "catalog is null");
this.schema = requireNonNull(schema, "schema is null");
- this.traceToken = requireNonNull(traceToken, "traceToken is null");
this.timeZoneKey = requireNonNull(timeZoneKey, "timeZoneKey is null");
this.locale = requireNonNull(locale, "locale is null");
this.remoteUserAddress = requireNonNull(remoteUserAddress, "remoteUserAddress is null");
@@ -172,7 +174,6 @@ public Session(
checkArgument(!transactionId.isPresent() || unprocessedCatalogProperties.isEmpty(), "Catalog session properties cannot be set if there is an open transaction");
checkArgument(catalog.isPresent() || !schema.isPresent(), "schema is set but catalog is not");
- this.tracer = requireNonNull(tracer, "tracer is null");
this.warningCollector = requireNonNull(warningCollector, "warningCollector is null");
this.runtimeStats = requireNonNull(runtimeStats, "runtimeStats is null");
this.queryType = requireNonNull(queryType, "queryType is null");
@@ -184,6 +185,16 @@ public QueryId getQueryId()
return queryId;
}
+ public BaseSpan getQuerySpan()
+ {
+ return querySpan;
+ }
+
+ public BaseSpan getRootSpan()
+ {
+ return rootSpan;
+ }
+
public String getUser()
{
return identity.getUser();
@@ -239,11 +250,6 @@ public Set getClientTags()
return clientTags;
}
- public Optional getTraceToken()
- {
- return traceToken;
- }
-
public ResourceEstimates getResourceEstimates()
{
return resourceEstimates;
@@ -322,11 +328,6 @@ public RuntimeStats getRuntimeStats()
return runtimeStats;
}
- public Optional getTracer()
- {
- return tracer;
- }
-
public WarningCollector getWarningCollector()
{
return warningCollector;
@@ -426,6 +427,8 @@ public Session beginTransactionId(TransactionId transactionId, TransactionManage
return new Session(
queryId,
+ querySpan,
+ rootSpan,
Optional.of(transactionId),
clientTransactionSupport,
new Identity(
@@ -439,7 +442,6 @@ public Session beginTransactionId(TransactionId transactionId, TransactionManage
source,
catalog,
schema,
- traceToken,
timeZoneKey,
locale,
remoteUserAddress,
@@ -454,7 +456,6 @@ public Session beginTransactionId(TransactionId transactionId, TransactionManage
sessionPropertyManager,
preparedStatements,
sessionFunctions,
- tracer,
warningCollector,
runtimeStats,
queryType);
@@ -508,7 +509,6 @@ public SessionRepresentation toSessionRepresentation()
source,
catalog,
schema,
- traceToken,
timeZoneKey,
locale,
remoteUserAddress,
@@ -530,13 +530,14 @@ public String toString()
{
return toStringHelper(this)
.add("queryId", queryId)
+ .add("querySpan", TracingManager.spanString(querySpan).orElse(null))
+ .add("rootSpan", rootSpan.toString())
.add("transactionId", transactionId)
.add("user", getUser())
.add("principal", getIdentity().getPrincipal().orElse(null))
.add("source", source.orElse(null))
.add("catalog", catalog.orElse(null))
.add("schema", schema.orElse(null))
- .add("traceToken", traceToken.orElse(null))
.add("timeZoneKey", timeZoneKey)
.add("locale", locale)
.add("remoteUserAddress", remoteUserAddress.orElse(null))
@@ -562,13 +563,14 @@ public static SessionBuilder builder(Session session)
public static class SessionBuilder
{
private QueryId queryId;
+ private BaseSpan querySpan = TracingManager.getInvalidSpan(); //do not initialize with null
+ private BaseSpan rootSpan = TracingManager.getInvalidSpan(); //do not initialize with null
private TransactionId transactionId;
private boolean clientTransactionSupport;
private Identity identity;
private String source;
private String catalog;
private String schema;
- private Optional traceToken = Optional.empty();
private TimeZoneKey timeZoneKey = TimeZoneKey.getTimeZoneKey(TimeZone.getDefault().getID());
private Locale locale = Locale.getDefault();
private String remoteUserAddress;
@@ -576,7 +578,6 @@ public static class SessionBuilder
private String clientInfo;
private Set clientTags = ImmutableSet.of();
private ResourceEstimates resourceEstimates;
- private Optional tracer = Optional.empty();
private long startTime = System.currentTimeMillis();
private final Map systemProperties = new HashMap<>();
private final Map> connectorProperties = new HashMap<>();
@@ -605,7 +606,6 @@ private SessionBuilder(Session session)
this.source = session.source.orElse(null);
this.catalog = session.catalog.orElse(null);
this.schema = session.schema.orElse(null);
- this.traceToken = requireNonNull(session.traceToken, "traceToken is null");
this.timeZoneKey = session.timeZoneKey;
this.locale = session.locale;
this.remoteUserAddress = session.remoteUserAddress.orElse(null);
@@ -617,7 +617,6 @@ private SessionBuilder(Session session)
session.unprocessedCatalogProperties.forEach((key, value) -> this.catalogSessionProperties.put(key, new HashMap<>(value)));
this.preparedStatements.putAll(session.preparedStatements);
this.sessionFunctions.putAll(session.sessionFunctions);
- this.tracer = requireNonNull(session.tracer, "tracer is null");
this.warningCollector = requireNonNull(session.warningCollector, "warningCollector is null");
this.runtimeStats = requireNonNull(session.runtimeStats, "runtimeStats is null");
this.queryType = requireNonNull(session.queryType, "queryType is null");
@@ -636,12 +635,6 @@ public SessionBuilder setTransactionId(TransactionId transactionId)
return this;
}
- public SessionBuilder setTracer(Optional tracer)
- {
- this.tracer = requireNonNull(tracer, "tracer is null");
- return this;
- }
-
public SessionBuilder setClientTransactionSupport()
{
this.clientTransactionSupport = true;
@@ -678,12 +671,6 @@ public SessionBuilder setSource(String source)
return this;
}
- public SessionBuilder setTraceToken(Optional traceToken)
- {
- this.traceToken = requireNonNull(traceToken, "traceToken is null");
- return this;
- }
-
public SessionBuilder setStartTime(long startTime)
{
this.startTime = startTime;
@@ -742,6 +729,18 @@ public SessionBuilder setConnectionProperty(ConnectorId connectorId, String prop
return this;
}
+ public SessionBuilder setQuerySpan(BaseSpan querySpan)
+ {
+ this.querySpan = querySpan;
+ return this;
+ }
+
+ public SessionBuilder setRootSpan(BaseSpan rootSpan)
+ {
+ this.rootSpan = rootSpan;
+ return this;
+ }
+
/**
* Sets a catalog property for the session. The property name and value must
* only contain characters from US-ASCII and must not be for '='.
@@ -837,13 +836,14 @@ public Session build()
{
return new Session(
queryId,
+ querySpan,
+ rootSpan,
Optional.ofNullable(transactionId),
clientTransactionSupport,
identity,
Optional.ofNullable(source),
Optional.ofNullable(catalog),
Optional.ofNullable(schema),
- traceToken,
timeZoneKey,
locale,
Optional.ofNullable(remoteUserAddress),
@@ -859,7 +859,6 @@ public Session build()
sessionPropertyManager,
preparedStatements,
sessionFunctions,
- tracer,
warningCollector,
runtimeStats,
queryType);
diff --git a/presto-main/src/main/java/com/facebook/presto/SessionRepresentation.java b/presto-main/src/main/java/com/facebook/presto/SessionRepresentation.java
index 7651ab2b96489..bc1e33b634ecf 100644
--- a/presto-main/src/main/java/com/facebook/presto/SessionRepresentation.java
+++ b/presto-main/src/main/java/com/facebook/presto/SessionRepresentation.java
@@ -30,6 +30,7 @@
import com.facebook.presto.spi.security.SelectedRole;
import com.facebook.presto.spi.security.TokenAuthenticator;
import com.facebook.presto.spi.session.ResourceEstimates;
+import com.facebook.presto.telemetry.TracingManager;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableMap;
@@ -54,7 +55,6 @@ public final class SessionRepresentation
private final Optional source;
private final Optional catalog;
private final Optional schema;
- private final Optional traceToken;
private final TimeZoneKey timeZoneKey;
private final Locale locale;
private final Optional remoteUserAddress;
@@ -81,7 +81,6 @@ public SessionRepresentation(
@JsonProperty("source") Optional source,
@JsonProperty("catalog") Optional catalog,
@JsonProperty("schema") Optional schema,
- @JsonProperty("traceToken") Optional traceToken,
@JsonProperty("timeZoneKey") TimeZoneKey timeZoneKey,
@JsonProperty("locale") Locale locale,
@JsonProperty("remoteUserAddress") Optional remoteUserAddress,
@@ -105,7 +104,6 @@ public SessionRepresentation(
this.source = requireNonNull(source, "source is null");
this.catalog = requireNonNull(catalog, "catalog is null");
this.schema = requireNonNull(schema, "schema is null");
- this.traceToken = requireNonNull(traceToken, "traceToken is null");
this.timeZoneKey = requireNonNull(timeZoneKey, "timeZoneKey is null");
this.locale = requireNonNull(locale, "locale is null");
this.remoteUserAddress = requireNonNull(remoteUserAddress, "remoteUserAddress is null");
@@ -188,13 +186,6 @@ public Optional getSchema()
return schema;
}
- @ThriftField(9)
- @JsonProperty
- public Optional getTraceToken()
- {
- return traceToken;
- }
-
@ThriftField(10)
@JsonProperty
public TimeZoneKey getTimeZoneKey()
@@ -307,6 +298,8 @@ public Session toSession(SessionPropertyManager sessionPropertyManager, MapResource Groups
*/
- public ListenableFuture> createQuery(QueryId queryId, String slug, int retryCount, SessionContext sessionContext, String query)
+ public ListenableFuture> createQuery(QueryId queryId, BaseSpan querySpan, BaseSpan rootSpan, String slug, int retryCount, SessionContext sessionContext, String query)
{
requireNonNull(queryId, "queryId is null");
requireNonNull(sessionContext, "sessionFactory is null");
@@ -242,14 +246,15 @@ public ListenableFuture> createQuery(QueryId queryId, String slug, int retryCo
checkArgument(!queryTracker.tryGetQuery(queryId).isPresent(), "query %s already exists", queryId);
DispatchQueryCreationFuture queryCreationFuture = new DispatchQueryCreationFuture();
- boundedQueryExecutor.execute(() -> {
- try {
- createQueryInternal(queryId, slug, retryCount, sessionContext, query, resourceGroupManager);
+
+ boundedQueryExecutor.execute(TracingManager.getCurrentContextWrap(() -> {
+ try (BaseSpan ignored = scopedSpan(querySpan, TracingEnum.DISPATCH.getName())) {
+ createQueryInternal(queryId, querySpan, rootSpan, slug, retryCount, sessionContext, query, resourceGroupManager);
}
finally {
queryCreationFuture.set(null);
}
- });
+ }));
return queryCreationFuture;
}
@@ -257,7 +262,7 @@ public ListenableFuture> createQuery(QueryId queryId, String slug, int retryCo
* Creates and registers a dispatch query with the query tracker. This method will never fail to register a query with the query
* tracker. If an error occurs while creating a dispatch query, a failed dispatch will be created and registered.
*/
- private void createQueryInternal(QueryId queryId, String slug, int retryCount, SessionContext sessionContext, String query, ResourceGroupManager resourceGroupManager)
+ private void createQueryInternal(QueryId queryId, BaseSpan querySpan, BaseSpan rootSpan, String slug, int retryCount, SessionContext sessionContext, String query, ResourceGroupManager resourceGroupManager)
{
Session session = null;
SessionBuilder sessionBuilder = null;
@@ -270,7 +275,7 @@ private void createQueryInternal(QueryId queryId, String slug, int retryCoun
}
// decode session
- sessionBuilder = sessionSupplier.createSessionBuilder(queryId, sessionContext, warningCollectorFactory);
+ sessionBuilder = sessionSupplier.createSessionBuilder(queryId, querySpan, rootSpan, sessionContext, warningCollectorFactory);
session = sessionBuilder.build();
// prepare query
@@ -338,6 +343,8 @@ private void createQueryInternal(QueryId queryId, String slug, int retryCoun
}
DispatchQuery failedDispatchQuery = failedDispatchQueryFactory.createFailedDispatchQuery(session, query, Optional.empty(), throwable);
queryCreated(failedDispatchQuery);
+
+ TracingManager.endSpanOnError(querySpan, throwable);
}
}
diff --git a/presto-main/src/main/java/com/facebook/presto/dispatcher/LocalDispatchQueryFactory.java b/presto-main/src/main/java/com/facebook/presto/dispatcher/LocalDispatchQueryFactory.java
index 14981c4f33fed..e6c036c345a9a 100644
--- a/presto-main/src/main/java/com/facebook/presto/dispatcher/LocalDispatchQueryFactory.java
+++ b/presto-main/src/main/java/com/facebook/presto/dispatcher/LocalDispatchQueryFactory.java
@@ -31,8 +31,6 @@
import com.facebook.presto.spi.resourceGroups.ResourceGroupId;
import com.facebook.presto.spi.security.AccessControl;
import com.facebook.presto.sql.analyzer.AnalyzerProviderManager;
-import com.facebook.presto.tracing.NoopTracerProvider;
-import com.facebook.presto.tracing.QueryStateTracingListener;
import com.facebook.presto.transaction.TransactionManager;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
@@ -158,7 +156,6 @@ public DispatchQuery createDispatchQuery(
metadata,
warningCollector);
- stateMachine.addStateChangeListener(new QueryStateTracingListener(stateMachine.getSession().getTracer().orElse(NoopTracerProvider.NOOP_TRACER)));
queryMonitor.queryCreatedEvent(stateMachine.getBasicQueryInfo(Optional.empty()));
ListenableFuture queryExecutionFuture = executor.submit(() -> {
diff --git a/presto-main/src/main/java/com/facebook/presto/event/QueryMonitor.java b/presto-main/src/main/java/com/facebook/presto/event/QueryMonitor.java
index 1998c567ebb04..d16dd796a076c 100644
--- a/presto-main/src/main/java/com/facebook/presto/event/QueryMonitor.java
+++ b/presto-main/src/main/java/com/facebook/presto/event/QueryMonitor.java
@@ -166,8 +166,7 @@ public void queryCreatedEvent(BasicQueryInfo queryInfo)
Optional.empty(),
Optional.empty(),
Optional.empty(),
- ImmutableList.of(),
- queryInfo.getSession().getTraceToken())));
+ ImmutableList.of())));
}
public void queryUpdatedEvent(QueryInfo queryInfo)
@@ -191,8 +190,7 @@ public void publishQueryProgressEvent(long monotonicallyIncreasingEventId, Basic
Optional.empty(),
Optional.empty(),
Optional.empty(),
- ImmutableList.of(),
- queryInfo.getSession().getTraceToken()),
+ ImmutableList.of()),
createQueryStatistics(queryInfo),
createQueryContext(queryInfo.getSession(), queryInfo.getResourceGroupId()),
queryInfo.getQueryType(),
@@ -214,8 +212,7 @@ public void queryImmediateFailureEvent(BasicQueryInfo queryInfo, ExecutionFailur
Optional.empty(),
Optional.empty(),
Optional.empty(),
- ImmutableList.of(),
- queryInfo.getSession().getTraceToken()),
+ ImmutableList.of()),
new QueryStatistics(
ofMillis(0),
ofMillis(0),
@@ -356,8 +353,7 @@ private QueryMetadata createQueryMetadata(QueryInfo queryInfo)
queryInfo.getOutputStage().flatMap(stage -> stageInfoCodec.toJsonWithLengthLimit(stage, maxJsonLimit)),
queryInfo.getRuntimeOptimizedStages().orElse(ImmutableList.of()).stream()
.map(stageId -> String.valueOf(stageId.getId()))
- .collect(toImmutableList()),
- queryInfo.getSession().getTraceToken());
+ .collect(toImmutableList()));
}
private List createOperatorStatistics(QueryInfo queryInfo)
diff --git a/presto-main/src/main/java/com/facebook/presto/event/SplitMonitor.java b/presto-main/src/main/java/com/facebook/presto/event/SplitMonitor.java
index 6a0296aac5499..1e875e30f171b 100644
--- a/presto-main/src/main/java/com/facebook/presto/event/SplitMonitor.java
+++ b/presto-main/src/main/java/com/facebook/presto/event/SplitMonitor.java
@@ -20,6 +20,7 @@
import com.facebook.presto.spi.eventlistener.SplitCompletedEvent;
import com.facebook.presto.spi.eventlistener.SplitFailureInfo;
import com.facebook.presto.spi.eventlistener.SplitStatistics;
+import com.facebook.presto.spi.telemetry.BaseSpan;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -27,6 +28,7 @@
import javax.inject.Inject;
import java.time.Duration;
+import java.util.Objects;
import java.util.Optional;
import static java.time.Duration.ofMillis;
@@ -46,17 +48,17 @@ public SplitMonitor(EventListenerManager eventListenerManager, ObjectMapper obje
this.objectMapper = requireNonNull(objectMapper, "objectMapper is null");
}
- public void splitCompletedEvent(TaskId taskId, DriverStats driverStats)
+ public void splitCompletedEvent(TaskId taskId, DriverStats driverStats, BaseSpan pipelineSpan)
{
- splitCompletedEvent(taskId, driverStats, null, null);
+ splitCompletedEvent(taskId, driverStats, null, null, pipelineSpan);
}
- public void splitFailedEvent(TaskId taskId, DriverStats driverStats, Throwable cause)
+ public void splitFailedEvent(TaskId taskId, DriverStats driverStats, Throwable cause, BaseSpan pipelineSpan)
{
- splitCompletedEvent(taskId, driverStats, cause.getClass().getName(), cause.getMessage());
+ splitCompletedEvent(taskId, driverStats, cause.getClass().getName(), cause.getMessage(), pipelineSpan);
}
- private void splitCompletedEvent(TaskId taskId, DriverStats driverStats, @Nullable String failureType, @Nullable String failureMessage)
+ private void splitCompletedEvent(TaskId taskId, DriverStats driverStats, @Nullable String failureType, @Nullable String failureMessage, BaseSpan pipelineSpan)
{
Optional timeToStart = Optional.empty();
if (driverStats.getStartTime() != null) {
@@ -93,10 +95,14 @@ private void splitCompletedEvent(TaskId taskId, DriverStats driverStats, @Nullab
timeToStart,
timeToEnd),
splitFailureMetadata,
- objectMapper.writeValueAsString(driverStats)));
+ objectMapper.writeValueAsString(driverStats)),
+ pipelineSpan);
}
catch (JsonProcessingException e) {
log.error(e, "Error processing split completion event for task %s", taskId);
}
+ if (!Objects.isNull(pipelineSpan)) {
+ pipelineSpan.end();
+ }
}
}
diff --git a/presto-main/src/main/java/com/facebook/presto/eventlistener/EventListenerManager.java b/presto-main/src/main/java/com/facebook/presto/eventlistener/EventListenerManager.java
index 24a1d04b54bb1..2d1d4b4a3d73f 100644
--- a/presto-main/src/main/java/com/facebook/presto/eventlistener/EventListenerManager.java
+++ b/presto-main/src/main/java/com/facebook/presto/eventlistener/EventListenerManager.java
@@ -14,6 +14,7 @@
package com.facebook.presto.eventlistener;
import com.facebook.airlift.log.Logger;
+import com.facebook.presto.common.telemetry.tracing.TracingEnum;
import com.facebook.presto.spi.classloader.ThreadContextClassLoader;
import com.facebook.presto.spi.eventlistener.EventListener;
import com.facebook.presto.spi.eventlistener.EventListenerFactory;
@@ -22,6 +23,7 @@
import com.facebook.presto.spi.eventlistener.QueryProgressEvent;
import com.facebook.presto.spi.eventlistener.QueryUpdatedEvent;
import com.facebook.presto.spi.eventlistener.SplitCompletedEvent;
+import com.facebook.presto.spi.telemetry.BaseSpan;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
@@ -32,6 +34,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
+import static com.facebook.presto.telemetry.TracingManager.scopedSpan;
import static com.facebook.presto.util.PropertiesUtil.loadProperties;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
@@ -122,9 +125,11 @@ public void publishQueryProgress(QueryProgressEvent queryProgressEvent)
.ifPresent(eventListener -> eventListener.publishQueryProgress(queryProgressEvent));
}
- public void splitCompleted(SplitCompletedEvent splitCompletedEvent)
+ public void splitCompleted(SplitCompletedEvent splitCompletedEvent, BaseSpan pipelineSpan)
{
- configuredEventListener.get()
- .ifPresent(eventListener -> eventListener.splitCompleted(splitCompletedEvent));
+ try (BaseSpan ignored = scopedSpan(pipelineSpan, TracingEnum.SPLIT.getName(), ImmutableMap.of("QUERY_ID", splitCompletedEvent.getQueryId(), "STAGE_ID", splitCompletedEvent.getStageId(), "TASK_ID", splitCompletedEvent.getTaskId(), "START_TIME", splitCompletedEvent.getStartTime().map(String::valueOf).orElse(""), "END_TIME", splitCompletedEvent.getEndTime().map(String::valueOf).orElse(""), "PAYLOAD", splitCompletedEvent.getPayload(), "FAILURE_INFO", splitCompletedEvent.getFailureInfo().map(String::valueOf).orElse("")))) {
+ configuredEventListener.get()
+ .ifPresent(eventListener -> eventListener.splitCompleted(splitCompletedEvent));
+ }
}
}
diff --git a/presto-main/src/main/java/com/facebook/presto/execution/QueryStateMachine.java b/presto-main/src/main/java/com/facebook/presto/execution/QueryStateMachine.java
index b22822fc0149e..ee26819736ac3 100644
--- a/presto-main/src/main/java/com/facebook/presto/execution/QueryStateMachine.java
+++ b/presto-main/src/main/java/com/facebook/presto/execution/QueryStateMachine.java
@@ -42,8 +42,10 @@
import com.facebook.presto.spi.security.SelectedRole;
import com.facebook.presto.spi.statistics.ColumnStatistics;
import com.facebook.presto.spi.statistics.TableStatistics;
+import com.facebook.presto.spi.telemetry.BaseSpan;
import com.facebook.presto.sql.planner.CanonicalPlanWithInfo;
import com.facebook.presto.sql.planner.PlanFragment;
+import com.facebook.presto.telemetry.TracingManager;
import com.facebook.presto.transaction.TransactionInfo;
import com.facebook.presto.transaction.TransactionManager;
import com.google.common.base.Ticker;
@@ -67,6 +69,7 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -95,6 +98,7 @@
import static com.facebook.presto.spi.StandardErrorCode.INVALID_ARGUMENTS;
import static com.facebook.presto.spi.StandardErrorCode.NOT_FOUND;
import static com.facebook.presto.spi.StandardErrorCode.USER_CANCELED;
+import static com.facebook.presto.telemetry.TracingManager.addEvent;
import static com.facebook.presto.util.Failures.toFailure;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
@@ -262,6 +266,11 @@ static QueryStateMachine beginWithTicker(
session = session.beginTransactionId(transactionId, transactionManager, accessControl);
}
+ BaseSpan querySpan = session.getQuerySpan();
+ BaseSpan rootSpan = session.getRootSpan();
+
+ TracingManager.setAttributes(querySpan, ImmutableMap.of("QUERY_TYPE", queryType.map(Enum::name).orElse("UNKNOWN")));
+
QueryStateMachine queryStateMachine = new QueryStateMachine(
query,
preparedQuery,
@@ -278,8 +287,32 @@ static QueryStateMachine beginWithTicker(
queryStateMachine.addStateChangeListener(newState -> {
QUERY_STATE_LOG.debug("Query %s is %s", queryStateMachine.getQueryId(), newState);
// mark finished or failed transaction as inactive
+
+ addEvent(querySpan, "query_state", newState.toString());
if (newState.isDone()) {
- queryStateMachine.getSession().getTransactionId().ifPresent(transactionManager::trySetInactive);
+ try {
+ queryStateMachine.getSession().getTransactionId().ifPresent(transactionManager::trySetInactive);
+
+ queryStateMachine.getFailureInfo().ifPresent(
+ failure -> {
+ ErrorCode errorCode = requireNonNull(failure.getErrorCode());
+
+ TracingManager.recordException(querySpan, failure.getMessage(), failure.toException(), errorCode);
+ });
+
+ queryStateMachine.getFailureInfo().orElseGet(() -> {
+ TracingManager.setSuccess(querySpan);
+ return null;
+ });
+ }
+ finally {
+ if (!Objects.isNull(querySpan)) {
+ querySpan.end();
+ }
+ if (!Objects.isNull(rootSpan)) {
+ rootSpan.end();
+ }
+ }
}
});
return queryStateMachine;
diff --git a/presto-main/src/main/java/com/facebook/presto/execution/RemoteTaskFactory.java b/presto-main/src/main/java/com/facebook/presto/execution/RemoteTaskFactory.java
index d6004387b745f..990be28409ae7 100644
--- a/presto-main/src/main/java/com/facebook/presto/execution/RemoteTaskFactory.java
+++ b/presto-main/src/main/java/com/facebook/presto/execution/RemoteTaskFactory.java
@@ -19,6 +19,7 @@
import com.facebook.presto.metadata.InternalNode;
import com.facebook.presto.metadata.Split;
import com.facebook.presto.spi.plan.PlanNodeId;
+import com.facebook.presto.spi.telemetry.BaseSpan;
import com.facebook.presto.sql.planner.PlanFragment;
import com.google.common.collect.Multimap;
@@ -35,5 +36,6 @@ RemoteTask createRemoteTask(Session session,
NodeStatsTracker nodeStatsTracker,
boolean summarizeTaskInfo,
TableWriteInfo tableWriteInfo,
- SchedulerStatsTracker schedulerStatsTracker);
+ SchedulerStatsTracker schedulerStatsTracker,
+ BaseSpan stagespan);
}
diff --git a/presto-main/src/main/java/com/facebook/presto/execution/SplitRunner.java b/presto-main/src/main/java/com/facebook/presto/execution/SplitRunner.java
index ded9bd28c1d49..16b3405a09771 100644
--- a/presto-main/src/main/java/com/facebook/presto/execution/SplitRunner.java
+++ b/presto-main/src/main/java/com/facebook/presto/execution/SplitRunner.java
@@ -13,6 +13,7 @@
*/
package com.facebook.presto.execution;
+import com.facebook.presto.spi.telemetry.BaseSpan;
import com.google.common.util.concurrent.ListenableFuture;
import io.airlift.units.Duration;
@@ -29,4 +30,9 @@ public interface SplitRunner
@Override
void close();
+
+ default BaseSpan getPipelineSpan()
+ {
+ return null;
+ }
}
diff --git a/presto-main/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java b/presto-main/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java
index 9efb9780e4e2e..3ff8836248436 100644
--- a/presto-main/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java
+++ b/presto-main/src/main/java/com/facebook/presto/execution/SqlQueryExecution.java
@@ -17,6 +17,7 @@
import com.facebook.presto.Session;
import com.facebook.presto.common.analyzer.PreparedQuery;
import com.facebook.presto.common.resourceGroups.QueryType;
+import com.facebook.presto.common.telemetry.tracing.TracingEnum;
import com.facebook.presto.cost.CostCalculator;
import com.facebook.presto.cost.HistoryBasedPlanStatisticsManager;
import com.facebook.presto.cost.StatsCalculator;
@@ -47,6 +48,7 @@
import com.facebook.presto.spi.plan.PlanNode;
import com.facebook.presto.spi.plan.PlanNodeIdAllocator;
import com.facebook.presto.spi.resourceGroups.ResourceGroupQueryLimits;
+import com.facebook.presto.spi.telemetry.BaseSpan;
import com.facebook.presto.split.CloseableSplitSourceProvider;
import com.facebook.presto.split.SplitManager;
import com.facebook.presto.sql.Optimizer;
@@ -101,6 +103,7 @@
import static com.facebook.presto.spi.StandardErrorCode.NOT_SUPPORTED;
import static com.facebook.presto.sql.Optimizer.PlanStage.OPTIMIZED_AND_VALIDATED;
import static com.facebook.presto.sql.planner.PlanNodeCanonicalInfo.getCanonicalInfo;
+import static com.facebook.presto.telemetry.TracingManager.scopedSpan;
import static com.facebook.presto.util.AnalyzerUtil.checkAccessPermissions;
import static com.facebook.presto.util.AnalyzerUtil.getAnalyzerContext;
import static com.google.common.base.Preconditions.checkArgument;
@@ -206,15 +209,20 @@ private SqlQueryExecution(
stateMachine.beginSemanticAnalyzing();
- try (TimeoutThread unused = new TimeoutThread(
- Thread.currentThread(),
- timeoutThreadExecutor,
- getQueryAnalyzerTimeout(getSession()))) {
- this.queryAnalysis = getSession()
- .getRuntimeStats()
- .recordWallAndCpuTime(ANALYZE_TIME_NANOS, () -> queryAnalyzer.analyze(analyzerContext, preparedQuery));
+ BaseSpan querySpan = getSession().getQuerySpan();
+ try (BaseSpan spanIgnored = scopedSpan(querySpan, TracingEnum.ANALYZER.getName())) {
+ try (TimeoutThread unused = new TimeoutThread(
+ Thread.currentThread(),
+ timeoutThreadExecutor,
+ getQueryAnalyzerTimeout(getSession()))) {
+ this.queryAnalysis = getSession()
+ .getRuntimeStats()
+ .recordWallAndCpuTime(ANALYZE_TIME_NANOS, () -> queryAnalyzer.analyze(analyzerContext, preparedQuery));
+ }
}
+ stateMachine.beginSemanticAnalyzing();
+
stateMachine.setUpdateType(queryAnalysis.getUpdateType());
stateMachine.setExpandedQuery(queryAnalysis.getExpandedQuery());
@@ -569,44 +577,66 @@ private PlanRoot doCreateLogicalPlanAndOptimize()
LOGICAL_PLANNER_TIME_NANOS,
() -> queryAnalyzer.plan(this.analyzerContext, queryAnalysis));
- Optimizer optimizer = new Optimizer(
- stateMachine.getSession(),
- metadata,
- planOptimizers,
- planChecker,
- analyzerContext.getVariableAllocator(),
- idAllocator,
- stateMachine.getWarningCollector(),
- statsCalculator,
- costCalculator,
- false);
+ BaseSpan querySpan = getSession().getQuerySpan();
+ try (BaseSpan ignored = scopedSpan(querySpan, TracingEnum.PLANNER.getName())) {
+ return optimizePlan(planNode);
+ }
+ }
+ catch (StackOverflowError e) {
+ throw new PrestoException(NOT_SUPPORTED, "statement is too large (stack overflow during analysis)", e);
+ }
+ }
+
+ private PlanRoot optimizePlan(PlanNode planNode)
+ {
+ Optimizer optimizer = new Optimizer(
+ stateMachine.getSession(),
+ metadata,
+ planOptimizers,
+ planChecker,
+ analyzerContext.getVariableAllocator(),
+ idAllocator,
+ stateMachine.getWarningCollector(),
+ statsCalculator,
+ costCalculator,
+ false);
- Plan plan = getSession().getRuntimeStats().recordWallAndCpuTime(
+ Plan plan;
+ try (BaseSpan ignored = scopedSpan("Plan Optimizer")) {
+ plan = getSession().getRuntimeStats().recordWallAndCpuTime(
OPTIMIZER_TIME_NANOS,
() -> optimizer.validateAndOptimizePlan(planNode, OPTIMIZED_AND_VALIDATED));
+ }
- queryPlan.set(plan);
- stateMachine.setPlanStatsAndCosts(plan.getStatsAndCosts());
- stateMachine.setPlanIdNodeMap(plan.getPlanIdNodeMap());
- List canonicalPlanWithInfos = getSession().getRuntimeStats().recordWallAndCpuTime(
- GET_CANONICAL_INFO_TIME_NANOS,
- () -> getCanonicalInfo(getSession(), plan.getRoot(), planCanonicalInfoProvider));
- stateMachine.setPlanCanonicalInfo(canonicalPlanWithInfos);
+ queryPlan.set(plan);
+ stateMachine.setPlanStatsAndCosts(plan.getStatsAndCosts());
+ stateMachine.setPlanIdNodeMap(plan.getPlanIdNodeMap());
+ List canonicalPlanWithInfos = getSession().getRuntimeStats().recordWallAndCpuTime(
+ GET_CANONICAL_INFO_TIME_NANOS,
+ () -> getCanonicalInfo(getSession(), plan.getRoot(), planCanonicalInfoProvider));
+ stateMachine.setPlanCanonicalInfo(canonicalPlanWithInfos);
- // extract inputs
+ // extract inputs
+ try (BaseSpan ignored = scopedSpan("extract-inputs")) {
List inputs = new InputExtractor(metadata, stateMachine.getSession()).extractInputs(plan.getRoot());
stateMachine.setInputs(inputs);
+ }
- // extract output
+ // extract output
+ try (BaseSpan ignored = scopedSpan("extract-outputs")) {
Optional