Skip to content

Commit c1aa4ae

Browse files
committed
trace2: add trace2 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 2c9b832 commit c1aa4ae

34 files changed

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

@@ -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: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Net;
44
using System.Net.Http;
5+
using System.Threading;
56
using System.Threading.Tasks;
67
using Atlassian.Bitbucket.Cloud;
78
using GitCredentialManager;
@@ -79,7 +80,10 @@ public async Task<ICredential> GetCredentialAsync(InputArguments input)
7980
if (StringComparer.OrdinalIgnoreCase.Equals(input.Protocol, "http")
8081
&& BitbucketHelper.IsBitbucketOrg(input))
8182
{
82-
throw new Exception("Unencrypted HTTP is not supported for Bitbucket.org. Ensure the repository remote URL is using HTTPS.");
83+
var message =
84+
"Unencrypted HTTP is not supported for Bitbucket.org. Ensure the repository remote URL is using HTTPS.";
85+
_context.Trace2.WriteError(message);
86+
throw new Exception(message);
8387
}
8488

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

152158
switch (result.AuthenticationMode)
@@ -160,8 +166,10 @@ private async Task<ICredential> GetRefreshedCredentials(InputArguments input, Au
160166
break;
161167

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

167175
// Fall through to the start of the interactive OAuth authentication flow
@@ -176,8 +184,10 @@ private async Task<ICredential> GetRefreshedCredentials(InputArguments input, Au
176184
}
177185
catch (OAuth2Exception ex)
178186
{
179-
_context.Trace.WriteLine("Failed to refresh existing OAuth credential using refresh token");
187+
var message = "Failed to refresh existing OAuth credential using refresh token";
188+
_context.Trace.WriteLine(message);
180189
_context.Trace.WriteException(ex);
190+
_context.Trace2.WriteError(message);
181191

182192
// We failed to refresh the AT using the RT; log the refresh failure and fall through to restart
183193
// the OAuth authentication flow
@@ -279,7 +289,7 @@ public async Task<AuthenticationModes> GetSupportedAuthenticationModesAsync(Inpu
279289
try
280290
{
281291
var authenticationMethods = await _restApiRegistry.Get(input).GetAuthenticationMethodsAsync();
282-
292+
283293
var modes = AuthenticationModes.None;
284294

285295
if (authenticationMethods.Contains(AuthenticationMethod.BasicAuth))
@@ -298,8 +308,12 @@ public async Task<AuthenticationModes> GetSupportedAuthenticationModesAsync(Inpu
298308
}
299309
catch (Exception ex)
300310
{
301-
_context.Trace.WriteLine($"Failed to query '{input.GetRemoteUri()}' for supported authentication schemes.");
311+
var format = "Failed to query '{0}' for supported authentication schemes.";
312+
var message = string.Format(format, input.GetRemoteUri());
313+
314+
_context.Trace.WriteLine(message);
302315
_context.Trace.WriteException(ex);
316+
_context.Trace2.WriteError(message, format);
303317

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

@@ -356,7 +370,11 @@ private async Task<string> ResolveOAuthUserNameAsync(InputArguments input, strin
356370
return result.Response.UserName;
357371
}
358372

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

362380
private async Task<string> ResolveBasicAuthUserNameAsync(InputArguments input, string username, string password)
@@ -367,7 +385,11 @@ private async Task<string> ResolveBasicAuthUserNameAsync(InputArguments input, s
367385
return result.Response.UserName;
368386
}
369387

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

373395
private async Task<bool> ValidateCredentialsWork(InputArguments input, ICredential credentials, AuthenticationModes authModes)
@@ -404,8 +426,10 @@ private async Task<bool> ValidateCredentialsWork(InputArguments input, ICredenti
404426
}
405427
catch (Exception ex)
406428
{
407-
_context.Trace.WriteLine($"Failed to validate existing credentials using OAuth");
429+
var message = "Failed to validate existing credentials using OAuth";
430+
_context.Trace.WriteLine(message);
408431
_context.Trace.WriteException(ex);
432+
_context.Trace2.WriteError(message);
409433
}
410434
}
411435

@@ -419,8 +443,10 @@ private async Task<bool> ValidateCredentialsWork(InputArguments input, ICredenti
419443
}
420444
catch (Exception ex)
421445
{
422-
_context.Trace.WriteLine($"Failed to validate existing credentials using Basic Auth");
446+
var message = "Failed to validate existing credentials using Basic Auth";
447+
_context.Trace.WriteLine(message);
423448
_context.Trace.WriteException(ex);
449+
_context.Trace2.WriteError(message);
424450
return false;
425451
}
426452
}

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, Environment.NewLine, gitEx.GitErrorMessage);
152+
Context.Trace2.WriteError(message);
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);
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);
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)