CurtHagenlocher commented on code in PR #3022:
URL: https://github.com/apache/arrow-adbc/pull/3022#discussion_r2183649197
##########
csharp/src/Drivers/BigQuery/BigQueryParameters.cs:
##########
@@ -68,5 +69,10 @@ internal class BigQueryConstants
// default value per
https://pkg.go.dev/cloud.google.com/go/bigquery#section-readme
public const string DetectProjectId = "*detect-project-id*";
+
+ // What ODBC uses
Review Comment:
Consider amending the comment to explain why we would use the same value as
ODBC (versus e.g. `_bqadbc_temp_tables`).
##########
csharp/src/Drivers/BigQuery/RetryManager.cs:
##########
@@ -67,7 +73,9 @@ public static async Task<T> ExecuteWithRetriesAsync<T>(
{
if (tokenProtectedResource.TokenRequiresUpdate(ex) ==
true)
{
+ activity?.AddBigQueryTag("update_token.status",
"Required");
await tokenProtectedResource.UpdateToken();
+ activity?.AddBigQueryTag("update_token.status",
"Completed");
Review Comment:
What's the behavior when adding the same tag twice? It keeps the most recent
one or it keeps all of them?
##########
csharp/src/Drivers/BigQuery/BigQueryConnection.cs:
##########
@@ -36,16 +38,17 @@ namespace Apache.Arrow.Adbc.Drivers.BigQuery
/// <summary>
/// BigQuery-specific implementation of <see cref="AdbcConnection"/>
/// </summary>
- public class BigQueryConnection : AdbcConnection, ITokenProtectedResource
+ public class BigQueryConnection : TracingConnection,
ITokenProtectedResource
{
readonly Dictionary<string, string> properties;
readonly HttpClient httpClient;
bool includePublicProjectIds = false;
const string infoDriverName = "ADBC BigQuery Driver";
- const string infoDriverVersion = "1.0.1";
const string infoVendorName = "BigQuery";
- const string infoDriverArrowVersion = "19.0.0";
- const string publicProjectId = "bigquery-public-data";
+ readonly string? infoDriverArrowVersion;
+
+ private static readonly string s_assemblyName =
BigQueryUtils.GetAssemblyName(typeof(BigQueryStatement));
+ private static readonly string s_assemblyVersion =
BigQueryUtils.GetAssemblyVersion(typeof(BigQueryStatement));
Review Comment:
Instead of capturing these three times in `BigQueryConnection`,
`BigQueryStatement` and `BigQueryStatement.MultiArrowReader`, consider storing
them in just `BigQueryUtils` and referencing them from there.
##########
csharp/src/Drivers/BigQuery/BigQueryUtils.cs:
##########
@@ -33,5 +34,11 @@ public static bool TokenRequiresUpdate(Exception ex)
return result;
}
+
+ internal static string GetAssemblyName(Type type) =>
type.Assembly.GetName().Name!;
+
+ internal static string GetAssemblyVersion(Type type) =>
FileVersionInfo.GetVersionInfo(type.Assembly.Location).ProductVersion ??
string.Empty;
+
+ internal static bool TracingToFile() { return false; }
Review Comment:
Consider making a property instead of a method.
##########
csharp/src/Drivers/BigQuery/BigQueryStatement.cs:
##########
@@ -355,112 +388,215 @@ private QueryOptions ValidateOptions()
if (firstProjectId != null)
{
options.ProjectId = firstProjectId;
+ activity?.AddBigQueryTag("detected_client_project_id",
firstProjectId);
+ // need to reopen the Client with the projectId
specified
+ this.bigQueryConnection.Open(firstProjectId);
}
}
}
if (Options == null || Options.Count == 0)
return options;
+ string largeResultDatasetId =
BigQueryConstants.DefaultLargeDatasetId;
+
foreach (KeyValuePair<string, string> keyValuePair in Options)
{
- if (keyValuePair.Key == BigQueryParameters.AllowLargeResults)
+ switch (keyValuePair.Key)
{
- options.AllowLargeResults = true ?
keyValuePair.Value.ToLower().Equals("true") : false;
- }
- if (keyValuePair.Key ==
BigQueryParameters.LargeResultsDestinationTable)
- {
- string destinationTable = keyValuePair.Value;
+ case BigQueryParameters.AllowLargeResults:
+ options.AllowLargeResults = true ?
keyValuePair.Value.ToLower().Equals("true") : false;
Review Comment:
There are two existing and one new instance of `s.ToLower().Equals("true")`
in this file, which is strictly worse than `s.Equals("true",
StringComparer.OrdinalIgnoreCase)`.
##########
csharp/src/Drivers/BigQuery/BigQueryConnection.cs:
##########
@@ -282,89 +331,97 @@ public override IArrowArrayStream
GetInfo(IReadOnlyList<AdbcInfoCode> codes)
),
true
)
- },
- new int[] { 0, 1, 2, 3, 4, 5 }.ToArray(),
- UnionMode.Dense);
+ },
+ new int[] { 0, 1, 2, 3, 4, 5 }.ToArray(),
+ UnionMode.Dense);
- if (codes.Count == 0)
- {
- codes = infoSupportedCodes;
- }
+ if (codes.Count == 0)
+ {
+ codes = infoSupportedCodes;
+ }
- UInt32Array.Builder infoNameBuilder = new UInt32Array.Builder();
- ArrowBuffer.Builder<byte> typeBuilder = new
ArrowBuffer.Builder<byte>();
- ArrowBuffer.Builder<int> offsetBuilder = new
ArrowBuffer.Builder<int>();
- StringArray.Builder stringInfoBuilder = new StringArray.Builder();
- int nullCount = 0;
- int arrayLength = codes.Count;
+ UInt32Array.Builder infoNameBuilder = new
UInt32Array.Builder();
+ ArrowBuffer.Builder<byte> typeBuilder = new
ArrowBuffer.Builder<byte>();
+ ArrowBuffer.Builder<int> offsetBuilder = new
ArrowBuffer.Builder<int>();
+ StringArray.Builder stringInfoBuilder = new
StringArray.Builder();
+ int nullCount = 0;
+ int arrayLength = codes.Count;
- foreach (AdbcInfoCode code in codes)
- {
- switch (code)
+ foreach (AdbcInfoCode code in codes)
{
- case AdbcInfoCode.DriverName:
- infoNameBuilder.Append((UInt32)code);
- typeBuilder.Append(strValTypeID);
- offsetBuilder.Append(stringInfoBuilder.Length);
- stringInfoBuilder.Append(infoDriverName);
- break;
- case AdbcInfoCode.DriverVersion:
- infoNameBuilder.Append((UInt32)code);
- typeBuilder.Append(strValTypeID);
- offsetBuilder.Append(stringInfoBuilder.Length);
- stringInfoBuilder.Append(infoDriverVersion);
- break;
- case AdbcInfoCode.DriverArrowVersion:
- infoNameBuilder.Append((UInt32)code);
- typeBuilder.Append(strValTypeID);
- offsetBuilder.Append(stringInfoBuilder.Length);
- stringInfoBuilder.Append(infoDriverArrowVersion);
- break;
- case AdbcInfoCode.VendorName:
- infoNameBuilder.Append((UInt32)code);
- typeBuilder.Append(strValTypeID);
- offsetBuilder.Append(stringInfoBuilder.Length);
- stringInfoBuilder.Append(infoVendorName);
- break;
- default:
- infoNameBuilder.Append((UInt32)code);
- typeBuilder.Append(strValTypeID);
- offsetBuilder.Append(stringInfoBuilder.Length);
- stringInfoBuilder.AppendNull();
- nullCount++;
- break;
+ string tagKey =
SemanticConventions.Db.Operation.Parameter(code.ToString().ToLowerInvariant());
+ Func<object?> tagValue = () => null;
+ switch (code)
+ {
+ case AdbcInfoCode.DriverName:
+ infoNameBuilder.Append((UInt32)code);
+ typeBuilder.Append(strValTypeID);
+ offsetBuilder.Append(stringInfoBuilder.Length);
+ stringInfoBuilder.Append(infoDriverName);
+ tagValue = () => infoDriverName;
Review Comment:
Why does it makes sense to capture these as delegates instead of just
recording the object value?
##########
csharp/test/Drivers/BigQuery/DriverTests.cs:
##########
@@ -291,7 +291,7 @@ public void CanExecuteQuery()
AdbcConnection adbcConnection =
GetAdbcConnection(environment.Name);
AdbcStatement statement = adbcConnection.CreateStatement();
- statement.SqlQuery = environment.Query;
+ statement.SqlQuery = "select * from
mashuptest-154002.NWIND.AdbcAllTypes"; // environment.Query;
Review Comment:
Should this be reverted?
##########
csharp/src/Drivers/BigQuery/BigQueryStatement.cs:
##########
@@ -302,25 +331,27 @@ private IArrowType GetType(TableFieldSchema field,
IArrowType type)
return type;
}
- private IArrowReader?
ReadChunkWithRetries(TokenProtectedReadClientManger clientMgr, string
streamName)
+ private IArrowReader?
ReadChunkWithRetries(TokenProtectedReadClientManger clientMgr, string
streamName, Activity? activity)
{
- Func<Task<IArrowReader?>> func = () =>
Task.FromResult<IArrowReader?>(ReadChunk(clientMgr, streamName));
- return
RetryManager.ExecuteWithRetriesAsync<IArrowReader?>(clientMgr, func,
MaxRetryAttempts, RetryDelayMs).GetAwaiter().GetResult();
+ Func<Task<IArrowReader?>> func = () =>
Task.FromResult<IArrowReader?>(ReadChunk(clientMgr, streamName, activity));
+ return
RetryManager.ExecuteWithRetriesAsync<IArrowReader?>(clientMgr, func, activity,
MaxRetryAttempts, RetryDelayMs).GetAwaiter().GetResult();
}
- private static IArrowReader? ReadChunk(TokenProtectedReadClientManger
clientMgr, string streamName)
+ private static IArrowReader? ReadChunk(TokenProtectedReadClientManger
clientMgr, string streamName, Activity? activity)
{
- return ReadChunk(clientMgr.ReadClient, streamName);
+ return ReadChunk(clientMgr.ReadClient, streamName, activity);
}
- private static IArrowReader? ReadChunk(BigQueryReadClient client,
string streamName)
+ private static IArrowReader? ReadChunk(BigQueryReadClient client,
string streamName, Activity? activity)
{
// Ideally we wouldn't need to indirect through a stream, but the
necessary APIs in Arrow
// are internal. (TODO: consider changing Arrow).
+ activity?.AddBigQueryTag("read_stream", streamName);
Review Comment:
Is the stream name system-generated or can it expose an arbitrary user
identifier?
I'll stop asking this question, but might apply to other things like the
destination table.
##########
csharp/src/Drivers/BigQuery/BigQueryConnection.cs:
##########
@@ -36,16 +38,17 @@ namespace Apache.Arrow.Adbc.Drivers.BigQuery
/// <summary>
/// BigQuery-specific implementation of <see cref="AdbcConnection"/>
/// </summary>
- public class BigQueryConnection : AdbcConnection, ITokenProtectedResource
+ public class BigQueryConnection : TracingConnection,
ITokenProtectedResource
{
readonly Dictionary<string, string> properties;
readonly HttpClient httpClient;
bool includePublicProjectIds = false;
const string infoDriverName = "ADBC BigQuery Driver";
- const string infoDriverVersion = "1.0.1";
const string infoVendorName = "BigQuery";
- const string infoDriverArrowVersion = "19.0.0";
- const string publicProjectId = "bigquery-public-data";
+ readonly string? infoDriverArrowVersion;
Review Comment:
Why is this an instance field while the next two are static fields?
##########
csharp/src/Drivers/BigQuery/BigQueryConnection.cs:
##########
@@ -97,136 +104,176 @@ public BigQueryConnection(IReadOnlyDictionary<string,
string> properties)
internal int RetryDelayMs { get; private set; } = 200;
+ public override string AssemblyVersion => s_assemblyVersion;
+
+ public override string AssemblyName => s_assemblyName;
+
/// <summary>
/// Initializes the internal BigQuery connection
/// </summary>
+ /// <param name="projectId">A project ID that has been specified by
the caller, not a user.</param>
/// <exception cref="ArgumentException"></exception>
- internal BigQueryClient Open()
+ internal BigQueryClient Open(string? projectId = null)
{
- string? projectId = null;
- string? billingProjectId = null;
- TimeSpan? clientTimeout = null;
-
- // if the caller doesn't specify a projectId, use the default
- if (!this.properties.TryGetValue(BigQueryParameters.ProjectId, out
projectId))
- projectId = BigQueryConstants.DetectProjectId;
-
- // in some situations, the publicProjectId gets passed and causes
an error when we try to create a query job:
- // Google.GoogleApiException : The service bigquery has thrown
an exception. HttpStatusCode is Forbidden.
- // Access Denied: Project bigquery-public-data: User does not
have bigquery.jobs.create permission in
- // project bigquery-public-data.
- // so if that is the case, treat it as if we need to detect the
projectId
- if (projectId.Equals(publicProjectId,
StringComparison.OrdinalIgnoreCase))
- projectId = BigQueryConstants.DetectProjectId;
-
- // the billing project can be null if it's not specified
- this.properties.TryGetValue(BigQueryParameters.BillingProjectId,
out billingProjectId);
-
- if
(this.properties.TryGetValue(BigQueryParameters.IncludePublicProjectId, out
string? result))
+ return this.TraceActivity(activity =>
{
- if (!string.IsNullOrEmpty(result))
- this.includePublicProjectIds = Convert.ToBoolean(result);
- }
+ string? billingProjectId = null;
+ TimeSpan? clientTimeout = null;
- if (this.properties.TryGetValue(BigQueryParameters.ClientTimeout,
out string? timeoutSeconds) &&
- int.TryParse(timeoutSeconds, out int seconds))
- {
- clientTimeout = TimeSpan.FromSeconds(seconds);
- }
+ if (string.IsNullOrEmpty(projectId))
+ {
+ // if the caller doesn't specify a projectId, use the
default
+ if
(!this.properties.TryGetValue(BigQueryParameters.ProjectId, out projectId))
+ {
+ projectId = BigQueryConstants.DetectProjectId;
+ }
+ else
+ {
+
activity?.AddBigQueryParameterTag(BigQueryParameters.ProjectId, projectId);
+ }
- SetCredential();
+ // in some situations, the publicProjectId gets passed and
causes an error when we try to create a query job:
+ // Google.GoogleApiException : The service bigquery
has thrown an exception. HttpStatusCode is Forbidden.
+ // Access Denied: Project bigquery-public-data: User
does not have bigquery.jobs.create permission in
+ // project bigquery-public-data.
+ // so if that is the case, treat it as if we need to
detect the projectId
+ if (projectId.Equals(BigQueryConstants.PublicProjectId,
StringComparison.OrdinalIgnoreCase))
+ {
+ projectId = BigQueryConstants.DetectProjectId;
+
activity?.AddBigQueryTag("change_public_projectId_to_detect_project_id",
projectId);
+ }
+ }
- BigQueryClientBuilder bigQueryClientBuilder = new
BigQueryClientBuilder()
- {
- ProjectId = projectId,
- QuotaProject = billingProjectId,
- GoogleCredential = Credential
- };
+ // the billing project can be null if it's not specified
+ if
(this.properties.TryGetValue(BigQueryParameters.BillingProjectId, out
billingProjectId))
+ {
+
activity?.AddBigQueryParameterTag((BigQueryParameters.BillingProjectId),
billingProjectId);
+ }
+
+ if
(this.properties.TryGetValue(BigQueryParameters.IncludePublicProjectId, out
string? result))
+ {
+ if (!string.IsNullOrEmpty(result))
+ {
+ this.includePublicProjectIds =
Convert.ToBoolean(result);
+
activity?.AddBigQueryParameterTag(BigQueryParameters.IncludePublicProjectId,
this.includePublicProjectIds);
+ }
+ }
- BigQueryClient client = bigQueryClientBuilder.Build();
+ if
(this.properties.TryGetValue(BigQueryParameters.ClientTimeout, out string?
timeoutSeconds) &&
+ int.TryParse(timeoutSeconds, out int seconds))
+ {
+ clientTimeout = TimeSpan.FromSeconds(seconds);
+
activity?.AddBigQueryParameterTag(BigQueryParameters.ClientTimeout, seconds);
+ }
- if (clientTimeout.HasValue)
- {
- client.Service.HttpClient.Timeout = clientTimeout.Value;
- }
+ SetCredential();
+
+ BigQueryClientBuilder bigQueryClientBuilder = new
BigQueryClientBuilder()
+ {
+ ProjectId = projectId,
+ QuotaProject = billingProjectId,
+ GoogleCredential = Credential
+ };
- Client = client;
- return client;
+ BigQueryClient client = bigQueryClientBuilder.Build();
+
+ if (clientTimeout.HasValue)
+ {
+ client.Service.HttpClient.Timeout = clientTimeout.Value;
+ }
+
+ Client = client;
+ return client;
+ });
}
internal void SetCredential()
{
- string? clientId = null;
- string? clientSecret = null;
- string? refreshToken = null;
- string? accessToken = null;
- string? audienceUri = null;
- string? authenticationType = null;
-
- string tokenEndpoint = BigQueryConstants.TokenEndpoint;
+ this.TraceActivity(activity =>
+ {
+ string? clientId = null;
+ string? clientSecret = null;
+ string? refreshToken = null;
+ string? accessToken = null;
+ string? audienceUri = null;
+ string? authenticationType = null;
- if
(!this.properties.TryGetValue(BigQueryParameters.AuthenticationType, out
authenticationType))
- throw new ArgumentException($"The
{BigQueryParameters.AuthenticationType} parameter is not present");
+ string tokenEndpoint = BigQueryConstants.TokenEndpoint;
- if
(this.properties.TryGetValue(BigQueryParameters.AuthenticationType, out string?
newAuthenticationType))
- {
- if (!string.IsNullOrEmpty(newAuthenticationType))
- authenticationType = newAuthenticationType;
+ if
(!this.properties.TryGetValue(BigQueryParameters.AuthenticationType, out
authenticationType))
+ {
+ throw new ArgumentException($"The
{BigQueryParameters.AuthenticationType} parameter is not present");
+ }
- if
(!authenticationType.Equals(BigQueryConstants.UserAuthenticationType,
StringComparison.OrdinalIgnoreCase) &&
-
!authenticationType.Equals(BigQueryConstants.ServiceAccountAuthenticationType,
StringComparison.OrdinalIgnoreCase) &&
-
!authenticationType.Equals(BigQueryConstants.EntraIdAuthenticationType,
StringComparison.OrdinalIgnoreCase))
+ if
(this.properties.TryGetValue(BigQueryParameters.AuthenticationType, out string?
newAuthenticationType))
{
- throw new ArgumentException($"The
{BigQueryParameters.AuthenticationType} parameter can only be
`{BigQueryConstants.UserAuthenticationType}`,
`{BigQueryConstants.ServiceAccountAuthenticationType}` or
`{BigQueryConstants.EntraIdAuthenticationType}`");
+ if (!string.IsNullOrEmpty(newAuthenticationType))
+ authenticationType = newAuthenticationType;
+
+ if
(!authenticationType.Equals(BigQueryConstants.UserAuthenticationType,
StringComparison.OrdinalIgnoreCase) &&
+
!authenticationType.Equals(BigQueryConstants.ServiceAccountAuthenticationType,
StringComparison.OrdinalIgnoreCase) &&
+
!authenticationType.Equals(BigQueryConstants.EntraIdAuthenticationType,
StringComparison.OrdinalIgnoreCase))
+ {
+ throw new ArgumentException($"The
{BigQueryParameters.AuthenticationType} parameter can only be
`{BigQueryConstants.UserAuthenticationType}`,
`{BigQueryConstants.ServiceAccountAuthenticationType}` or
`{BigQueryConstants.EntraIdAuthenticationType}`");
+ }
+ else
+ {
+
activity?.AddBigQueryParameterTag((BigQueryParameters.AuthenticationType),
authenticationType);
+ }
}
- }
- if (!string.IsNullOrEmpty(authenticationType) &&
authenticationType.Equals(BigQueryConstants.UserAuthenticationType,
StringComparison.OrdinalIgnoreCase))
- {
- if (!this.properties.TryGetValue(BigQueryParameters.ClientId,
out clientId))
- throw new ArgumentException($"The
{BigQueryParameters.ClientId} parameter is not present");
+ if (!string.IsNullOrEmpty(authenticationType) &&
authenticationType.Equals(BigQueryConstants.UserAuthenticationType,
StringComparison.OrdinalIgnoreCase))
+ {
+ if
(!this.properties.TryGetValue(BigQueryParameters.ClientId, out clientId))
+ throw new ArgumentException($"The
{BigQueryParameters.ClientId} parameter is not present");
- if
(!this.properties.TryGetValue(BigQueryParameters.ClientSecret, out
clientSecret))
- throw new ArgumentException($"The
{BigQueryParameters.ClientSecret} parameter is not present");
+ if
(!this.properties.TryGetValue(BigQueryParameters.ClientSecret, out
clientSecret))
+ throw new ArgumentException($"The
{BigQueryParameters.ClientSecret} parameter is not present");
- if
(!this.properties.TryGetValue(BigQueryParameters.RefreshToken, out
refreshToken))
- throw new ArgumentException($"The
{BigQueryParameters.RefreshToken} parameter is not present");
+ if
(!this.properties.TryGetValue(BigQueryParameters.RefreshToken, out
refreshToken))
+ throw new ArgumentException($"The
{BigQueryParameters.RefreshToken} parameter is not present");
- Credential =
ApplyScopes(GoogleCredential.FromAccessToken(GetAccessToken(clientId,
clientSecret, refreshToken, tokenEndpoint)));
- }
- else if (!string.IsNullOrEmpty(authenticationType) &&
authenticationType.Equals(BigQueryConstants.EntraIdAuthenticationType,
StringComparison.OrdinalIgnoreCase))
- {
- if
(!this.properties.TryGetValue(BigQueryParameters.AccessToken, out accessToken))
- throw new ArgumentException($"The
{BigQueryParameters.AccessToken} parameter is not present");
+ Credential =
ApplyScopes(GoogleCredential.FromAccessToken(GetAccessToken(clientId,
clientSecret, refreshToken, tokenEndpoint)));
+ }
+ else if (!string.IsNullOrEmpty(authenticationType) &&
authenticationType.Equals(BigQueryConstants.EntraIdAuthenticationType,
StringComparison.OrdinalIgnoreCase))
+ {
+ if
(!this.properties.TryGetValue(BigQueryParameters.AccessToken, out accessToken))
+ throw new ArgumentException($"The
{BigQueryParameters.AccessToken} parameter is not present");
- if
(!this.properties.TryGetValue(BigQueryParameters.AudienceUri, out audienceUri))
- throw new ArgumentException($"The
{BigQueryParameters.AudienceUri} parameter is not present");
+ if
(!this.properties.TryGetValue(BigQueryParameters.AudienceUri, out audienceUri))
+ throw new ArgumentException($"The
{BigQueryParameters.AudienceUri} parameter is not present");
- Credential =
ApplyScopes(GoogleCredential.FromAccessToken(TradeEntraIdTokenForBigQueryToken(audienceUri,
accessToken)));
- }
- else if (!string.IsNullOrEmpty(authenticationType) &&
authenticationType.Equals(BigQueryConstants.ServiceAccountAuthenticationType,
StringComparison.OrdinalIgnoreCase))
- {
- string? json = string.Empty;
+ Credential =
ApplyScopes(GoogleCredential.FromAccessToken(TradeEntraIdTokenForBigQueryToken(audienceUri,
accessToken)));
+ }
+ else if (!string.IsNullOrEmpty(authenticationType) &&
authenticationType.Equals(BigQueryConstants.ServiceAccountAuthenticationType,
StringComparison.OrdinalIgnoreCase))
+ {
+ string? json = string.Empty;
- if
(!this.properties.TryGetValue(BigQueryParameters.JsonCredential, out json))
- throw new ArgumentException($"The
{BigQueryParameters.JsonCredential} parameter is not present");
+ if
(!this.properties.TryGetValue(BigQueryParameters.JsonCredential, out json))
+ throw new ArgumentException($"The
{BigQueryParameters.JsonCredential} parameter is not present");
- Credential = ApplyScopes(GoogleCredential.FromJson(json));
- }
- else
- {
- throw new ArgumentException($"{authenticationType} is not a
valid authenticationType");
- }
+ Credential = ApplyScopes(GoogleCredential.FromJson(json));
+ }
+ else
+ {
+ throw new ArgumentException($"{authenticationType} is not
a valid authenticationType");
+ }
+ });
}
public override void SetOption(string key, string value)
{
- this.properties[key] = value;
-
- if (key.Equals(BigQueryParameters.AccessToken))
+ this.TraceActivity(activity =>
{
- UpdateClientToken();
- }
+ activity?.AddTag(key + ".set", value);
Review Comment:
It seems like a bad idea to log an access token under any circumstances. Are
there other sensitive option values we should also avoid logging (or tie to
`BigQueryUtils.TracingToFile`, which looks like a proxy for "is safe to log
sensitive information")?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]