-
Notifications
You must be signed in to change notification settings - Fork 41
[PECOBLR-435] added application name to track BiTool #837
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
4af6d6b
bc52608
c28d24c
764ede9
e737325
8b10ecf
a268d5f
1f57dbc
0408c4a
8043483
0e1b2f3
83fd62c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| package com.databricks.jdbc.common.util; | ||
|
|
||
| import static com.databricks.jdbc.common.util.WildcardUtil.isNullOrEmpty; | ||
|
|
||
| import com.databricks.jdbc.api.internal.IDatabricksConnectionContext; | ||
| import com.databricks.jdbc.telemetry.TelemetryHelper; | ||
| import com.databricks.sdk.core.UserAgent; | ||
|
|
||
| /** Helper class for determining and setting user agent and client app name. */ | ||
| public class UserAgentHelper { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any reason we split the existing UserAgentManager helper into a different UserAgent helper? (looks like an unnecessary split in my opinion.)
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just wanted the fallback mechanism utility to be separate. But, I agree, merging makes sense. |
||
| private static final String APP_NAME_SYSTEM_PROPERTY = "app.name"; | ||
| private static final String VERSION_FILLER = "version"; | ||
|
|
||
| /** | ||
| * Determines the application name using a fallback mechanism: 1. useragententry url param 2. | ||
| * applicationname url param 3. client info property "applicationname" 4. System property app.name | ||
| * | ||
| * @param connectionContext The connection context | ||
| * @param clientInfoAppName The application name from client info properties, can be null | ||
| * @return The determined application name or null if none is found | ||
| */ | ||
| static String determineApplicationName( | ||
| IDatabricksConnectionContext connectionContext, String clientInfoAppName) { | ||
| // First check URL params | ||
| String appName = connectionContext.getCustomerUserAgent(); | ||
| if (!isNullOrEmpty(appName)) { | ||
| return appName; | ||
| } | ||
|
|
||
| // Then check applicationname URL param | ||
| appName = connectionContext.getApplicationName(); | ||
| if (!isNullOrEmpty(appName)) { | ||
| return appName; | ||
| } | ||
|
|
||
| // Then check client info property | ||
| if (!isNullOrEmpty(clientInfoAppName)) { | ||
| return clientInfoAppName; | ||
| } | ||
|
|
||
| // Finally check system property | ||
| return System.getProperty(APP_NAME_SYSTEM_PROPERTY); | ||
| } | ||
|
|
||
| /** | ||
| * Updates both the telemetry client app name and HTTP user agent headers. To be called during | ||
| * connection initialization and when app name changes. | ||
| * | ||
| * @param connectionContext The connection context | ||
| * @param clientInfoAppName Optional client info app name, can be null | ||
| */ | ||
| public static void updateUserAgentAndTelemetry( | ||
| IDatabricksConnectionContext connectionContext, String clientInfoAppName) { | ||
| String appName = determineApplicationName(connectionContext, clientInfoAppName); | ||
| if (!isNullOrEmpty(appName)) { | ||
| // Update telemetry | ||
| TelemetryHelper.updateClientAppName(appName); | ||
|
|
||
| // Update HTTP user agent | ||
| int i = appName.indexOf('/'); | ||
| String customerName = (i < 0) ? appName : appName.substring(0, i); | ||
| String customerVersion = (i < 0) ? VERSION_FILLER : appName.substring(i + 1); | ||
|
shivam2680 marked this conversation as resolved.
Outdated
|
||
| UserAgent.withOtherInfo(customerName, UserAgent.sanitize(customerVersion)); | ||
|
shivam2680 marked this conversation as resolved.
Outdated
|
||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -126,6 +126,9 @@ Collection<ExternalLink> getResultChunks(StatementId statementId, long chunkInde | |
| */ | ||
| void resetAccessToken(String newAccessToken); | ||
|
|
||
| /** Update the user agent headers when application name changes */ | ||
| void updateUserAgent(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we are going to remove this, right? |
||
|
|
||
| TFetchResultsResp getMoreResults(IDatabricksStatementInternal parentStatement) | ||
| throws DatabricksSQLException; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |||||||||||||||||||||
| import static com.databricks.jdbc.common.util.DatabricksAuthUtil.initializeConfigWithToken; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| import com.databricks.jdbc.api.internal.IDatabricksConnectionContext; | ||||||||||||||||||||||
| import com.databricks.jdbc.common.util.UserAgentManager; | ||||||||||||||||||||||
| import com.databricks.jdbc.common.util.ValidationUtil; | ||||||||||||||||||||||
| import com.databricks.jdbc.dbclient.IDatabricksHttpClient; | ||||||||||||||||||||||
| import com.databricks.jdbc.dbclient.impl.common.TracingUtil; | ||||||||||||||||||||||
|
|
@@ -145,15 +146,28 @@ public void checkReadBytesAvailable(long numBytes) throws TTransportException {} | |||||||||||||||||||||
| /** Refreshes the custom headers by re-authenticating if necessary. */ | ||||||||||||||||||||||
| private void refreshHeadersIfRequired() { | ||||||||||||||||||||||
| Map<String, String> refreshedHeaders = databricksConfig.authenticate(); | ||||||||||||||||||||||
| customHeaders = | ||||||||||||||||||||||
| refreshedHeaders != null ? new HashMap<>(refreshedHeaders) : Collections.emptyMap(); | ||||||||||||||||||||||
| // Preserve existing custom headers (like User-Agent) and add/update auth headers | ||||||||||||||||||||||
| Map<String, String> newHeaders = new HashMap<>(customHeaders); | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does that mean we don't add user-Agent info in our current thrift flow? Do we pass it from DatabricksHttpClient? I see that DatabricksHttpClient needs change too.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not really.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Based on offline discussion) : SDK and thrift are not exhaustive set of places where this would be required. Any other call using HTTPClient will have the incorrect userAgent |
||||||||||||||||||||||
| if (refreshedHeaders != null) { | ||||||||||||||||||||||
| newHeaders.putAll(refreshedHeaders); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| customHeaders = newHeaders; | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor improved version :
Suggested change
|
||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| void resetAccessToken(String newAccessToken) { | ||||||||||||||||||||||
| this.databricksConfig = initializeConfigWithToken(newAccessToken, databricksConfig); | ||||||||||||||||||||||
| this.databricksConfig.resolve(); | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| /** Updates the user agent for thrift requests by adding it as a header */ | ||||||||||||||||||||||
| void updateUserAgent() { | ||||||||||||||||||||||
| // Add user agent as a header since the HTTP client's user agent is set during construction | ||||||||||||||||||||||
| // and cannot be changed. This ensures the updated user agent is sent with thrift requests. | ||||||||||||||||||||||
| Map<String, String> headers = new HashMap<>(customHeaders); | ||||||||||||||||||||||
| headers.put("User-Agent", UserAgentManager.getUserAgentString()); | ||||||||||||||||||||||
| customHeaders = headers; | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| @VisibleForTesting | ||||||||||||||||||||||
| void setResponseBuffer(ByteArrayInputStream responseBuffer) { | ||||||||||||||||||||||
| this.responseBuffer = responseBuffer; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we remove this comment? This seems misleading for someone having telemetry = OFF.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done