Skip to content

Commit

Permalink
WL#15706, Add OpenTelemetry tracing.
Browse files Browse the repository at this point in the history
Change-Id: Ib2aa3406e638abc8bed28b07eb66c51bfd3a57ea
  • Loading branch information
fjssilva committed Mar 8, 2024
1 parent 6758555 commit b1da962
Show file tree
Hide file tree
Showing 44 changed files with 3,250 additions and 1,447 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

Version 8.4.0

- WL#15706, Add OpenTelemetry tracing.

- WL#16174, Support for VECTOR data type.

- Fix for Bug#36380711, Tests failing due to removal of deprecated features.
Expand Down
2 changes: 1 addition & 1 deletion build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ See also com.mysql.cj.conf.PropertyDefinitions.SYSP_* variables for other test o
</propertyset>

<!-- Java compiler arguments to widen warnings detection and fail on warnings. -->
<condition property="javac.compilerarg" value="-Xlint:all,-path -Werror" else="">
<condition property="javac.compilerarg" value="-Xlint:all,-path,-try -Werror" else="">
<istrue value="${com.mysql.cj.build.failOnWarnings}" />
</condition>

Expand Down
2 changes: 2 additions & 0 deletions src/main/core-api/java/com/mysql/cj/MessageBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public interface MessageBuilder<M extends Message> {

M buildClose();

M buildComQuery(M sharedPacket, Session sess, String query, Query callingQuery, String characterEncoding);

M buildComQuery(M sharedPacket, Session sess, PreparedQuery preparedQuery, QueryBindings bindings, String characterEncoding);

}
19 changes: 18 additions & 1 deletion src/main/core-api/java/com/mysql/cj/QueryAttributesBindings.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,19 @@ public interface QueryAttributesBindings {
*
* @param name
* the query attribute name.
*
* @param value
* the query attribute value.
*/
void setAttribute(String name, Object value);

/**
* Removes the specified query attribute from the list of query attributes.
*
* @param name
* the query attribute name.
*/
void removeAttribute(String name);

/**
* Get the count of query attributes in the list.
*
Expand Down Expand Up @@ -68,6 +75,16 @@ public interface QueryAttributesBindings {
*/
void runThroughAll(Consumer<BindValue> bindAttribute);

/**
* Checks if there's already an attribute with the specified name.
*
* @param name
* the query attribute name.
* @return
* <code>true</code> if the specified attribute name already exists.
*/
boolean containsAttribute(String name);

/**
* Removes all query attributes from the query attributes list.
*/
Expand Down
65 changes: 57 additions & 8 deletions src/main/core-api/java/com/mysql/cj/QueryInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public class QueryInfo {

private static final String INSERT_STATEMENT = "INSERT";
private static final String REPLACE_STATEMENT = "REPLACE";
private static final String MULTIPLE_QUERIES_TAG = "(multiple queries)";

private static final String VALUE_CLAUSE = "VALUE";
private static final String AS_CLAUSE = "AS";
Expand All @@ -55,6 +56,7 @@ public class QueryInfo {
private int queryLength = 0;
private int queryStartPos = 0;
private char statementFirstChar = Character.MIN_VALUE;
private String statementKeyword = "";
private int batchCount = 1;
private int numberOfPlaceholders = 0;
private int numberOfQueries = 0;
Expand Down Expand Up @@ -102,17 +104,23 @@ public QueryInfo(String sql, Session session, String encoding) {
} else {
this.numberOfQueries = 1;
this.statementFirstChar = Character.toUpperCase(strInspector.getChar());

// Capture the statement keyword.
int endStatementKeyword = 0;
int nextChar = this.queryStartPos;
StringBuilder sbStatementKeyword = new StringBuilder();
do {
sbStatementKeyword.append(Character.toUpperCase(strInspector.getChar()));
endStatementKeyword = nextChar + 1;
strInspector.incrementPosition();
nextChar = strInspector.indexOfNextChar();
} while (nextChar == endStatementKeyword);
this.statementKeyword = sbStatementKeyword.toString();
}

// Only INSERT and REPLACE statements support multi-values clause rewriting.
boolean isInsert = strInspector.matchesIgnoreCase(INSERT_STATEMENT) != -1;
if (isInsert) {
strInspector.incrementPosition(INSERT_STATEMENT.length()); // Advance to the end of "INSERT".
}
boolean isReplace = !isInsert && strInspector.matchesIgnoreCase(REPLACE_STATEMENT) != -1;
if (isReplace) {
strInspector.incrementPosition(REPLACE_STATEMENT.length()); // Advance to the end of "REPLACE".
}
boolean isInsert = INSERT_STATEMENT.equalsIgnoreCase(this.statementKeyword);
boolean isReplace = !isInsert && REPLACE_STATEMENT.equalsIgnoreCase(this.statementKeyword);

// Check if the statement has potential to be rewritten as a multi-values clause statement, i.e., if it is an INSERT or REPLACE statement and
// 'rewriteBatchedStatements' is enabled.
Expand Down Expand Up @@ -338,6 +346,10 @@ public QueryInfo(String sql, Session session, String encoding) {
int length = end - begin;
this.staticSqlParts[i] = StringUtils.getBytes(this.sql, begin, length, this.encoding);
}

if (this.numberOfQueries > 1) {
this.statementKeyword = MULTIPLE_QUERIES_TAG;
}
}

/**
Expand All @@ -358,6 +370,7 @@ private QueryInfo(QueryInfo baseQueryInfo, int batchCount) {
this.queryLength = 0;
this.queryStartPos = this.baseQueryInfo.queryStartPos;
this.statementFirstChar = this.baseQueryInfo.statementFirstChar;
this.statementKeyword = this.baseQueryInfo.statementKeyword;
this.batchCount = batchCount;
this.numberOfPlaceholders = this.baseQueryInfo.numberOfPlaceholders * this.batchCount;
this.numberOfQueries = 1;
Expand Down Expand Up @@ -458,6 +471,16 @@ public char getFirstStmtChar() {
return this.baseQueryInfo.statementFirstChar;
}

/**
* Returns the statement keyword from the query used to build this {@link QueryInfo}.
*
* @return
* the statement keyword
*/
public String getStatementKeyword() {
return this.statementKeyword;
}

/**
* If this object represents a query that is re-writable as a multi-values statement and if rewriting batched statements is enabled, then returns the
* length of the parsed VALUES clause section, including the placeholder characters themselves, otherwise returns -1.
Expand Down Expand Up @@ -585,6 +608,32 @@ public static char firstCharOfStatementUc(String sql, boolean noBackslashEscapes
return Character.toUpperCase(sql.charAt(statementKeywordPos));
}

/**
* Finds and returns the statement keyword from the specified SQL, skipping comments and quoted text.
*
* @param sql
* the query to search
* @param noBackslashEscapes
* whether backslash escapes are disabled or not
* @return the statement keyword of the query
*/
public static String getStatementKeyword(String sql, boolean noBackslashEscapes) {
StringInspector strInspector = new StringInspector(sql, 0, OPENING_MARKERS, CLOSING_MARKERS, OVERRIDING_MARKERS,
noBackslashEscapes ? SearchMode.__MRK_COM_MYM_HNT_WS : SearchMode.__BSE_MRK_COM_MYM_HNT_WS);
int begin = strInspector.indexOfNextAlphanumericChar();
if (begin == -1) {
return "";
}
int end = 0;
int nextChar = begin;
do {
end = nextChar + 1;
strInspector.incrementPosition();
nextChar = strInspector.indexOfNextChar();
} while (nextChar == end);
return sql.substring(begin, end).toUpperCase();
}

/**
* Checks whether the given query is safe to run in a read-only session. In case of doubt it is assumed to be safe. This operation does not take into
* consideration the multiplicity of queries in the specified SQL.
Expand Down
21 changes: 21 additions & 0 deletions src/main/core-api/java/com/mysql/cj/Session.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import com.mysql.cj.protocol.ResultBuilder;
import com.mysql.cj.protocol.ServerSession;
import com.mysql.cj.result.Row;
import com.mysql.cj.telemetry.TelemetryHandler;

/**
* {@link Session} exposes logical level which user API uses internally to call {@link Protocol} methods.
Expand Down Expand Up @@ -111,6 +112,26 @@ public interface Session {
*/
ProfilerEventHandler getProfilerEventHandler();

/**
* Returns the comment that will be prepended to all statements sent to the server.
*
* @return query comment string
*/
String getQueryComment();

/**
* Sets the comment that will be prepended to all statements sent to the server. Do not use slash-star or star-slash tokens in the comment as these will be
* added by the driver itself.
*
* @param comment
* query comment string
*/
void setQueryComment(String comment);

void setTelemetryHandler(TelemetryHandler telemetryHandler);

TelemetryHandler getTelemetryHandler();

HostInfo getHostInfo();

String getQueryTimingUnits();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ public enum SslMode {
PREFERRED, REQUIRED, VERIFY_CA, VERIFY_IDENTITY, DISABLED;
}

public enum OpenTelemetry {
PREFERRED, REQUIRED, DISABLED;
}

public enum XdevapiSslMode {
REQUIRED, VERIFY_CA, VERIFY_IDENTITY, DISABLED;
}
Expand All @@ -158,14 +162,13 @@ public enum DatabaseTerm {
CATALOG, SCHEMA;
}

private static String STANDARD_LOGGER_NAME = StandardLogger.class.getName();

/**
* Static unmodifiable {@link PropertyKey} -&gt; {@link PropertyDefinition} map.
*/
public static final Map<PropertyKey, PropertyDefinition<?>> PROPERTY_KEY_TO_PROPERTY_DEFINITION;

static {
String STANDARD_LOGGER_NAME = StandardLogger.class.getName();

PropertyDefinition<?>[] pdefs = new PropertyDefinition<?>[] {
//
// CATEGORY_AUTHENTICATION
Expand Down Expand Up @@ -801,6 +804,9 @@ public enum DatabaseTerm {
new BooleanPropertyDefinition(PropertyKey.autoGenerateTestcaseScript, DEFAULT_VALUE_FALSE, RUNTIME_MODIFIABLE,
Messages.getString("ConnectionProperties.autoGenerateTestcaseScript"), "3.1.9", CATEGORY_DEBUGING_PROFILING, 18),

new EnumPropertyDefinition<>(PropertyKey.openTelemetry, OpenTelemetry.PREFERRED, RUNTIME_MODIFIABLE,
Messages.getString("ConnectionProperties.openTelemetry"), "8.1.0", CATEGORY_DEBUGING_PROFILING, 19),

//
// CATEGORY_EXCEPTIONS
//
Expand Down
3 changes: 2 additions & 1 deletion src/main/core-api/java/com/mysql/cj/conf/PropertyKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,11 @@ public enum PropertyKey {
nullDatabaseMeansCurrent("nullDatabaseMeansCurrent", "nullCatalogMeansCurrent", true), //
ociConfigFile("ociConfigFile", true), //
ociConfigProfile("ociConfigProfile", true), //
openTelemetry("openTelemetry", true), //
overrideSupportsIntegrityEnhancementFacility("overrideSupportsIntegrityEnhancementFacility", true), //
packetDebugBufferSize("packetDebugBufferSize", true), //
padCharsWithSpace("padCharsWithSpace", true), //
paranoid("paranoid", false), //
queryInfoCacheFactory("queryInfoCacheFactory", "parseInfoCacheFactory", true), //
password1("password1", true), //
password2("password2", true), //
password3("password3", true), //
Expand All @@ -183,6 +183,7 @@ public enum PropertyKey {
profileSQL("profileSQL", true), //
propertiesTransform("propertiesTransform", true), //
queriesBeforeRetrySource("queriesBeforeRetrySource", "queriesBeforeRetryMaster", true), //
queryInfoCacheFactory("queryInfoCacheFactory", "parseInfoCacheFactory", true), //
queryInterceptors("queryInterceptors", true), //
queryTimeoutKillsConnection("queryTimeoutKillsConnection", true), //
readFromSourceWhenNoReplicas("readFromSourceWhenNoReplicas", "readFromMasterWhenNoSlaves", true), //
Expand Down
18 changes: 0 additions & 18 deletions src/main/core-api/java/com/mysql/cj/protocol/Protocol.java
Original file line number Diff line number Diff line change
Expand Up @@ -230,24 +230,6 @@ <T extends ProtocolEntity> T read(Class<Resultset> requiredClass, int maxRows, b
*/
InputStream getLocalInfileInputStream();

/**
* Returns the comment that will be prepended to all statements
* sent to the server.
*
* @return query comment string
*/
String getQueryComment();

/**
* Sets the comment that will be prepended to all statements
* sent to the server. Do not use slash-star or star-slash tokens
* in the comment as these will be added by the driver itself.
*
* @param comment
* query comment string
*/
void setQueryComment(String comment);

/**
* Read messages from server and deliver them to resultBuilder.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by
* the Free Software Foundation.
*
* This program is designed to work with certain software that is licensed under separate terms, as designated in a particular file or component or in
* included license documentation. The authors of MySQL hereby grant you an additional permission to link the program and your derivative works with the
* separately licensed software that they have either included with the program or referenced in the documentation.
*
* Without limiting anything contained in the foregoing, this file, which is part of MySQL Connector/J, is also subject to the Universal FOSS Exception,
* version 1.0, a copy of which can be found at http://oss.oracle.com/licenses/universal-foss-exception.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

package com.mysql.cj.telemetry;

/**
* No-op implementation of {@link TelemetryHandler}.
*/
public class NoopTelemetryHandler implements TelemetryHandler {

private static NoopTelemetryHandler INSTANCE = new NoopTelemetryHandler();

public static NoopTelemetryHandler getInstance() {
return INSTANCE;
}

private NoopTelemetryHandler() {
}

@Override
public TelemetrySpan startSpan(TelemetrySpanName spanName, Object... args) {
return NoopTelemetrySpan.getInstance();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by
* the Free Software Foundation.
*
* This program is designed to work with certain software that is licensed under separate terms, as designated in a particular file or component or in
* included license documentation. The authors of MySQL hereby grant you an additional permission to link the program and your derivative works with the
* separately licensed software that they have either included with the program or referenced in the documentation.
*
* Without limiting anything contained in the foregoing, this file, which is part of MySQL Connector/J, is also subject to the Universal FOSS Exception,
* version 1.0, a copy of which can be found at http://oss.oracle.com/licenses/universal-foss-exception.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

package com.mysql.cj.telemetry;

/**
* No-op implementation of {@link TelemetryScope}.
*/
public class NoopTelemetryScope implements TelemetryScope {

private static NoopTelemetryScope INSTANCE = new NoopTelemetryScope();

public static NoopTelemetryScope getInstance() {
return INSTANCE;
}

private NoopTelemetryScope() {
}

}

0 comments on commit b1da962

Please sign in to comment.