Skip to content

Commit 111e5b9

Browse files
committed
trace2: add error tracing statements
Add TRACE2 error tracing statements throughout GCM codebase. Note that this is a best effort - there are certain places (most notably static and unsafe methods) where statements were purposefully not added because it is either not safe or was deemed to much lift/churn to do so.
1 parent ff42ab5 commit 111e5b9

34 files changed

+521
-186
lines changed

src/shared/Atlassian.Bitbucket.UI/Commands/CredentialsCommand.cs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ private async Task<int> ExecuteAsync(Uri url, string userName, bool showOAuth, b
4848

4949
if (!viewModel.WindowResult || viewModel.SelectedMode == AuthenticationModes.None)
5050
{
51-
throw new Exception("User cancelled dialog.");
51+
var message = "User cancelled dialog.";
52+
Context.Trace2.WriteError(message);
53+
throw new Exception(message);
5254
}
5355

5456
switch (viewModel.SelectedMode)
@@ -70,8 +72,11 @@ private async Task<int> ExecuteAsync(Uri url, string userName, bool showOAuth, b
7072
break;
7173

7274
default:
73-
throw new ArgumentOutOfRangeException(nameof(AuthenticationModes),
74-
"Unknown authentication mode", viewModel.SelectedMode.ToString());
75+
var actualValue = "Unknown authentication mode";
76+
var message = viewModel.SelectedMode.ToString();
77+
78+
Context.Trace2.WriteError($"{actualValue}: {message}");
79+
throw new ArgumentOutOfRangeException(nameof(AuthenticationModes), actualValue, message);
7580
}
7681

7782
return 0;

src/shared/Atlassian.Bitbucket/BitbucketAuthentication.cs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,11 @@ public async Task<CredentialsPromptResult> GetCredentialsAsync(Uri targetUri, st
8888
// We need at least one mode!
8989
if (modes == AuthenticationModes.None)
9090
{
91-
throw new ArgumentException(@$"Must specify at least one {nameof(AuthenticationModes)}", nameof(modes));
91+
var format = @"Must specify at least one {0}";
92+
var message = string.Format(format, nameof(AuthenticationModes));
93+
94+
Context.Trace2.WriteError(message, format);
95+
throw new ArgumentException(message, nameof(modes));
9296
}
9397

9498
// Shell out to the UI helper and show the Bitbucket u/p prompt
@@ -128,12 +132,16 @@ public async Task<CredentialsPromptResult> GetCredentialsAsync(Uri targetUri, st
128132
{
129133
if (!output.TryGetValue("username", out userName))
130134
{
131-
throw new Exception("Missing username in response");
135+
var message = "Missing username in response";
136+
Context.Trace2.WriteError(message);
137+
throw new Exception(message);
132138
}
133139

134140
if (!output.TryGetValue("password", out password))
135141
{
136-
throw new Exception("Missing password in response");
142+
var message = "Missing password in response";
143+
Context.Trace2.WriteError(message);
144+
throw new Exception(message);
137145
}
138146

139147
return new CredentialsPromptResult(
@@ -172,7 +180,11 @@ public async Task<CredentialsPromptResult> GetCredentialsAsync(Uri targetUri, st
172180
return new CredentialsPromptResult(AuthenticationModes.OAuth);
173181

174182
case AuthenticationModes.None:
175-
throw new ArgumentOutOfRangeException(nameof(modes), @$"At least one {nameof(AuthenticationModes)} must be supplied");
183+
var format = "At least one {0} must be supplied";
184+
var message = string.Format(format, nameof(AuthenticationModes));
185+
186+
Context.Trace2.WriteError(message, format);
187+
throw new ArgumentOutOfRangeException(nameof(modes), message);
176188

177189
default:
178190
var menuTitle = $"Select an authentication method for '{targetUri}'";
@@ -190,7 +202,9 @@ public async Task<CredentialsPromptResult> GetCredentialsAsync(Uri targetUri, st
190202
if (choice == oauthItem) goto case AuthenticationModes.OAuth;
191203
if (choice == basicItem) goto case AuthenticationModes.Basic;
192204

193-
throw new Exception();
205+
Exception e = new Exception();
206+
Context.Trace2.WriteError(e.Message);
207+
throw e;
194208
}
195209
}
196210
}

src/shared/Atlassian.Bitbucket/BitbucketHostProvider.cs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ public async Task<ICredential> GetCredentialAsync(InputArguments input)
7979
if (StringComparer.OrdinalIgnoreCase.Equals(input.Protocol, "http")
8080
&& BitbucketHelper.IsBitbucketOrg(input))
8181
{
82-
throw new Exception("Unencrypted HTTP is not supported for Bitbucket.org. Ensure the repository remote URL is using HTTPS.");
82+
var message =
83+
"Unencrypted HTTP is not supported for Bitbucket.org. Ensure the repository remote URL is using HTTPS.";
84+
_context.Trace2.WriteError(message);
85+
throw new Exception(message);
8386
}
8487

8588
var authModes = await GetSupportedAuthenticationModesAsync(input);
@@ -145,8 +148,10 @@ private async Task<ICredential> GetRefreshedCredentials(InputArguments input, Au
145148
var result = await _bitbucketAuth.GetCredentialsAsync(remoteUri, input.UserName, authModes);
146149
if (result is null || result.AuthenticationMode == AuthenticationModes.None)
147150
{
148-
_context.Trace.WriteLine("User cancelled credential prompt");
149-
throw new Exception("User cancelled credential prompt.");
151+
var message = "User cancelled credential prompt";
152+
_context.Trace.WriteLine(message);
153+
_context.Trace2.WriteError(message);
154+
throw new Exception(message);
150155
}
151156

152157
switch (result.AuthenticationMode)
@@ -160,8 +165,10 @@ private async Task<ICredential> GetRefreshedCredentials(InputArguments input, Au
160165
break;
161166

162167
default:
163-
throw new ArgumentOutOfRangeException(
164-
$"Unexpected {nameof(AuthenticationModes)} returned from prompt");
168+
var format = "Unexpected {0} returned from prompt";
169+
var message = string.Format(format, nameof(AuthenticationModes));
170+
_context.Trace2.WriteError(message, format);
171+
throw new ArgumentOutOfRangeException(message);
165172
}
166173

167174
// Fall through to the start of the interactive OAuth authentication flow
@@ -176,8 +183,10 @@ private async Task<ICredential> GetRefreshedCredentials(InputArguments input, Au
176183
}
177184
catch (OAuth2Exception ex)
178185
{
179-
_context.Trace.WriteLine("Failed to refresh existing OAuth credential using refresh token");
186+
var message = "Failed to refresh existing OAuth credential using refresh token";
187+
_context.Trace.WriteLine(message);
180188
_context.Trace.WriteException(ex);
189+
_context.Trace2.WriteError(message);
181190

182191
// We failed to refresh the AT using the RT; log the refresh failure and fall through to restart
183192
// the OAuth authentication flow
@@ -279,7 +288,7 @@ public async Task<AuthenticationModes> GetSupportedAuthenticationModesAsync(Inpu
279288
try
280289
{
281290
var authenticationMethods = await _restApiRegistry.Get(input).GetAuthenticationMethodsAsync();
282-
291+
283292
var modes = AuthenticationModes.None;
284293

285294
if (authenticationMethods.Contains(AuthenticationMethod.BasicAuth))
@@ -298,8 +307,12 @@ public async Task<AuthenticationModes> GetSupportedAuthenticationModesAsync(Inpu
298307
}
299308
catch (Exception ex)
300309
{
301-
_context.Trace.WriteLine($"Failed to query '{input.GetRemoteUri()}' for supported authentication schemes.");
310+
var format = "Failed to query '{0}' for supported authentication schemes.";
311+
var message = string.Format(format, input.GetRemoteUri());
312+
313+
_context.Trace.WriteLine(message);
302314
_context.Trace.WriteException(ex);
315+
_context.Trace2.WriteError(message, format);
303316

304317
_context.Terminal.WriteLine($"warning: failed to query '{input.GetRemoteUri()}' for supported authentication schemes.");
305318

@@ -356,7 +369,11 @@ private async Task<string> ResolveOAuthUserNameAsync(InputArguments input, strin
356369
return result.Response.UserName;
357370
}
358371

359-
throw new Exception($"Failed to resolve username. HTTP: {result.StatusCode}");
372+
var format = "Failed to resolve username. HTTP: {0}";
373+
var message = string.Format(format, result.StatusCode);
374+
_context.Trace2.WriteError(message, format);
375+
376+
throw new Exception(message);
360377
}
361378

362379
private async Task<string> ResolveBasicAuthUserNameAsync(InputArguments input, string username, string password)
@@ -367,7 +384,11 @@ private async Task<string> ResolveBasicAuthUserNameAsync(InputArguments input, s
367384
return result.Response.UserName;
368385
}
369386

370-
throw new Exception($"Failed to resolve username. HTTP: {result.StatusCode}");
387+
var format = "Failed to resolve username. HTTP: {0}";
388+
var message = string.Format(format, result.StatusCode);
389+
_context.Trace2.WriteError(message, format);
390+
391+
throw new Exception(message);
371392
}
372393

373394
private async Task<bool> ValidateCredentialsWork(InputArguments input, ICredential credentials, AuthenticationModes authModes)
@@ -404,8 +425,10 @@ private async Task<bool> ValidateCredentialsWork(InputArguments input, ICredenti
404425
}
405426
catch (Exception ex)
406427
{
407-
_context.Trace.WriteLine($"Failed to validate existing credentials using OAuth");
428+
var message = "Failed to validate existing credentials using OAuth";
429+
_context.Trace.WriteLine(message);
408430
_context.Trace.WriteException(ex);
431+
_context.Trace2.WriteError(message);
409432
}
410433
}
411434

@@ -419,8 +442,10 @@ private async Task<bool> ValidateCredentialsWork(InputArguments input, ICredenti
419442
}
420443
catch (Exception ex)
421444
{
422-
_context.Trace.WriteLine($"Failed to validate existing credentials using Basic Auth");
445+
var message = "Failed to validate existing credentials using Basic Auth";
446+
_context.Trace.WriteLine(message);
423447
_context.Trace.WriteException(ex);
448+
_context.Trace2.WriteError(message);
424449
return false;
425450
}
426451
}

src/shared/Atlassian.Bitbucket/DataCenter/BitbucketRestApi.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public BitbucketRestApi(ICommandContext context)
2020
EnsureArgument.NotNull(context, nameof(context));
2121

2222
_context = context;
23-
23+
2424
}
2525

2626
public async Task<RestApiResult<IUserInfo>> GetUserInformationAsync(string userName, string password, bool isBearerToken)
@@ -35,7 +35,7 @@ public async Task<RestApiResult<IUserInfo>> GetUserInformationAsync(string userN
3535
}
3636

3737
// Bitbucket Server/DC doesn't actually provide a REST API we can use to trade an access_token for the owning username,
38-
// therefore this is always going to return a placeholder username, however this call does provide a way to validate the
38+
// therefore this is always going to return a placeholder username, however this call does provide a way to validate the
3939
// credentials we do have
4040
var requestUri = new Uri(ApiUri, "api/1.0/users");
4141
using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUri))
@@ -131,14 +131,16 @@ public void Dispose()
131131

132132
private HttpClient HttpClient => _httpClient ??= _context.HttpClientFactory.CreateClient();
133133

134-
private Uri ApiUri
134+
private Uri ApiUri
135135
{
136-
get
136+
get
137137
{
138138
var remoteUri = _context.Settings?.RemoteUri;
139139
if (remoteUri == null)
140140
{
141-
throw new ArgumentException("RemoteUri must be defined to generate Bitbucket DC OAuth2 endpoint Urls");
141+
var message = "RemoteUri must be defined to generate Bitbucket DC OAuth2 endpoint Urls";
142+
_context.Trace2.WriteError(message);
143+
throw new ArgumentException(message);
142144
}
143145

144146
return new Uri(BitbucketHelper.GetBaseUri(remoteUri) + "/rest/");

src/shared/Core.UI/Commands/CredentialsCommand.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ private async Task<int> ExecuteAsync(CommandOptions options)
6363

6464
if (!viewModel.WindowResult)
6565
{
66-
throw new Exception("User cancelled dialog.");
66+
var message = "User cancelled dialog.";
67+
Context.Trace2.WriteError(message);
68+
throw new Exception(message);
6769
}
6870

6971
WriteResult(

src/shared/Core.UI/Commands/DeviceCodeCommand.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ private async Task<int> ExecuteAsync(string code, string url, bool noLogo)
4141

4242
if (!viewModel.WindowResult)
4343
{
44-
throw new Exception("User cancelled dialog.");
44+
var message = "User cancelled dialog.";
45+
Context.Trace2.WriteError(message);
46+
throw new Exception(message);
4547
}
4648

4749
return 0;

src/shared/Core.UI/Commands/OAuthCommand.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,9 @@ private async Task<int> ExecuteAsync(CommandOptions options)
6666

6767
if (!viewModel.WindowResult)
6868
{
69-
throw new Exception("User cancelled dialog.");
69+
var message = "User cancelled dialog.";
70+
Context.Trace2.WriteError(message);
71+
throw new Exception(message);
7072
}
7173

7274
var result = new Dictionary<string, string>();
@@ -81,7 +83,9 @@ private async Task<int> ExecuteAsync(CommandOptions options)
8183
break;
8284

8385
default:
84-
throw new ArgumentOutOfRangeException();
86+
var e = new ArgumentOutOfRangeException();
87+
Context.Trace2.WriteError(e.Message);
88+
throw e;
8589
}
8690

8791
WriteResult(result);

src/shared/Core.UI/HelperApplication.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ private bool WriteException(Exception ex)
5858
{
5959
["error"] = ex.Message
6060
});
61+
Context.Trace2.WriteError(ex.Message);
6162

6263
return true;
6364
}

src/shared/Core/Application.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,18 +134,32 @@ private void OnException(Exception ex, InvocationContext invocationContext)
134134

135135
private bool WriteException(Exception ex)
136136
{
137+
string format;
138+
string message;
139+
137140
// Try and use a nicer format for some well-known exception types
138141
switch (ex)
139142
{
140143
case GitException gitEx:
141-
Context.Streams.Error.WriteLine("fatal: {0} [{1}]", gitEx.Message, gitEx.ExitCode);
144+
format = "fatal: {0} [{1}]";
145+
message = string.Format(format, gitEx.Message, gitEx.ExitCode);
146+
147+
Context.Streams.Error.WriteLine(message);
142148
Context.Streams.Error.WriteLine(gitEx.GitErrorMessage);
149+
150+
format += "{2}{3}";
151+
message = string.Format(format, gitEx.Message, gitEx.ExitCode, Environment.NewLine, gitEx.GitErrorMessage);
152+
Context.Trace2.WriteError(message, format);
143153
break;
144154
case InteropException interopEx:
145-
Context.Streams.Error.WriteLine("fatal: {0} [0x{1:x}]", interopEx.Message, interopEx.ErrorCode);
155+
format = "fatal: {0} [0x{1:x}]";
156+
message = string.Format(format, interopEx.Message, interopEx.ErrorCode);
157+
Context.Streams.Error.WriteLine(message, format);
146158
break;
147159
default:
148-
Context.Streams.Error.WriteLine("fatal: {0}", ex.Message);
160+
format = "fatal: {0}";
161+
message = string.Format(format, ex.Message);
162+
Context.Streams.Error.WriteLine(message, format);
149163
break;
150164
}
151165

src/shared/Core/Authentication/AuthenticationBase.cs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ protected internal virtual async Task<IDictionary<string, string>> InvokeHelperA
4646
var process = ChildProcess.Start(Context.Trace2, procStartInfo, Trace2ProcessClass.UIHelper);
4747
if (process is null)
4848
{
49-
throw new Exception($"Failed to start helper process: {path} {args}");
49+
var format = "Failed to start helper process: {0} {1}";
50+
var message = string.Format(format, path, args);
51+
52+
Context.Trace2.WriteError(message, format);
53+
throw new Exception(message);
5054
}
5155

5256
// Kill the process upon a cancellation request
@@ -69,7 +73,11 @@ protected internal virtual async Task<IDictionary<string, string>> InvokeHelperA
6973
errorMessage = "Unknown";
7074
}
7175

72-
throw new Exception($"helper error ({exitCode}): {errorMessage}");
76+
var format = "helper error ({0}): {1}";
77+
var message = string.Format(format, exitCode, errorMessage);
78+
79+
Context.Trace2.WriteError(message, format);
80+
throw new Exception(message);
7381
}
7482

7583
return resultDict;
@@ -86,7 +94,10 @@ protected void ThrowIfUserInteractionDisabled()
8694

8795
Context.Trace.WriteLine($"{envName} / {cfgName} is false/never; user interactivity has been disabled.");
8896

89-
throw new InvalidOperationException("Cannot prompt because user interactivity has been disabled.");
97+
var message = "Cannot prompt because user interactivity has been disabled.";
98+
Context.Trace2.WriteError(message);
99+
100+
throw new InvalidOperationException(message);
90101
}
91102
}
92103

@@ -96,7 +107,10 @@ protected void ThrowIfGuiPromptsDisabled()
96107
{
97108
Context.Trace.WriteLine($"{Constants.EnvironmentVariables.GitTerminalPrompts} is 0; GUI prompts have been disabled.");
98109

99-
throw new InvalidOperationException("Cannot show prompt because GUI prompts have been disabled.");
110+
var message = "Cannot show prompt because GUI prompts have been disabled.";
111+
Context.Trace2.WriteError(message);
112+
113+
throw new InvalidOperationException(message);
100114
}
101115
}
102116

@@ -106,7 +120,10 @@ protected void ThrowIfTerminalPromptsDisabled()
106120
{
107121
Context.Trace.WriteLine($"{Constants.EnvironmentVariables.GitTerminalPrompts} is 0; terminal prompts have been disabled.");
108122

109-
throw new InvalidOperationException("Cannot prompt because terminal prompts have been disabled.");
123+
var message = "Cannot prompt because terminal prompts have been disabled.";
124+
Context.Trace2.WriteError(message);
125+
126+
throw new InvalidOperationException(message);
110127
}
111128
}
112129

0 commit comments

Comments
 (0)