@@ -7,11 +7,13 @@ import (
7
7
"strconv"
8
8
"strings"
9
9
"time"
10
+ "unicode"
10
11
11
12
"github.com/google/uuid"
12
13
"golang.org/x/xerrors"
13
14
"tailscale.com/tailcfg"
14
15
16
+ "github.com/coder/coder/v2/coderd/healthcheck/health"
15
17
"github.com/coder/coder/v2/codersdk"
16
18
"github.com/coder/coder/v2/codersdk/healthsdk"
17
19
"github.com/coder/coder/v2/codersdk/workspacesdk"
@@ -351,72 +353,109 @@ func PeerDiagnostics(w io.Writer, d tailnet.PeerDiagnostics) {
351
353
}
352
354
353
355
type ConnDiags struct {
354
- ConnInfo * workspacesdk.AgentConnectionInfo
356
+ ConnInfo workspacesdk.AgentConnectionInfo
355
357
PingP2P bool
356
358
DisableDirect bool
357
359
LocalNetInfo * tailcfg.NetInfo
358
360
LocalInterfaces * healthsdk.InterfacesReport
359
361
AgentNetcheck * healthsdk.AgentNetcheckReport
360
362
ClientIPIsAWS bool
361
363
AgentIPIsAWS bool
364
+ Verbose bool
362
365
// TODO: More diagnostics
363
366
}
364
367
365
- func ConnDiagnostics (w io.Writer , d ConnDiags ) {
368
+ func (d ConnDiags ) Write (w io.Writer ) {
369
+ _ , _ = fmt .Fprintln (w , "" )
370
+ general , client , agent := d .splitDiagnostics ()
371
+ for _ , msg := range general {
372
+ _ , _ = fmt .Fprintln (w , msg )
373
+ }
374
+ if len (client ) > 0 {
375
+ _ , _ = fmt .Fprint (w , "Possible client-side issues with direct connection:\n \n " )
376
+ for _ , msg := range client {
377
+ _ , _ = fmt .Fprintf (w , " - %s\n \n " , msg )
378
+ }
379
+ }
380
+ if len (agent ) > 0 {
381
+ _ , _ = fmt .Fprint (w , "Possible agent-side issues with direct connections:\n \n " )
382
+ for _ , msg := range agent {
383
+ _ , _ = fmt .Fprintf (w , " - %s\n \n " , msg )
384
+ }
385
+ }
386
+ }
387
+
388
+ func (d ConnDiags ) splitDiagnostics () (general , client , agent []string ) {
366
389
if d .PingP2P {
367
- _ , _ = fmt . Fprint ( w , "✔ You are connected directly (p2p)\n " )
390
+ general = append ( general , "✔ You are connected directly (p2p)" )
368
391
} else {
369
- _ , _ = fmt . Fprint ( w , "❗ You are connected via a DERP relay, not directly (p2p)\n " )
392
+ general = append ( general , "❗ You are connected via a DERP relay, not directly (p2p)" )
370
393
}
371
394
372
395
if d .AgentNetcheck != nil {
373
396
for _ , msg := range d .AgentNetcheck .Interfaces .Warnings {
374
- _ , _ = fmt . Fprintf ( w , "❗ Agent: %s \n " , msg . Message )
397
+ agent = append ( agent , formatHealthMessage ( msg ) )
375
398
}
376
399
}
377
400
378
401
if d .LocalInterfaces != nil {
379
402
for _ , msg := range d .LocalInterfaces .Warnings {
380
- _ , _ = fmt . Fprintf ( w , "❗ Client: %s \n " , msg . Message )
403
+ client = append ( client , formatHealthMessage ( msg ) )
381
404
}
382
405
}
383
406
384
- if d .DisableDirect {
385
- _ , _ = fmt .Fprint (w , "❗ Direct connections are disabled locally, by `--disable-direct` or `CODER_DISABLE_DIRECT`\n " )
386
- return
407
+ if d .PingP2P && ! d .Verbose {
408
+ return general , client , agent
387
409
}
388
410
389
- if d .ConnInfo != nil && d .ConnInfo .DisableDirectConnections {
390
- _ , _ = fmt .Fprint (w , "❗ Your Coder administrator has blocked direct connections\n " )
391
- return
411
+ if d .DisableDirect {
412
+ general = append (general , "❗ Direct connections are disabled locally, by `--disable-direct` or `CODER_DISABLE_DIRECT`" )
413
+ if ! d .Verbose {
414
+ return general , client , agent
415
+ }
392
416
}
393
417
394
- if d .ConnInfo != nil && d .ConnInfo .DERPMap != nil {
395
- if ! d .ConnInfo .DERPMap .HasSTUN () {
396
- _ , _ = fmt .Fprint (w , "✘ The DERP map is not configured to use STUN, which will prevent direct connections from starting outside of local networks\n " )
397
- } else if d .LocalNetInfo != nil && ! d .LocalNetInfo .UDP {
398
- _ , _ = fmt .Fprint (w , "❗ Client could not connect to STUN over UDP, which may be preventing a direct connection\n " )
418
+ if d .ConnInfo .DisableDirectConnections {
419
+ general = append (general , "❗ Your Coder administrator has blocked direct connections" )
420
+ if ! d .Verbose {
421
+ return general , client , agent
399
422
}
400
423
}
401
424
425
+ if ! d .ConnInfo .DERPMap .HasSTUN () {
426
+ general = append (general , "✘ The DERP map is not configured to use STUN" )
427
+ } else if d .LocalNetInfo != nil && ! d .LocalNetInfo .UDP {
428
+ client = append (client , "✘ Client could not connect to STUN over UDP" )
429
+ }
430
+
402
431
if d .LocalNetInfo != nil && d .LocalNetInfo .MappingVariesByDestIP .EqualBool (true ) {
403
- _ , _ = fmt . Fprint ( w , "❗ Client is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers\n " )
432
+ client = append ( client , "❗ Client is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers" )
404
433
}
405
434
406
435
if d .AgentNetcheck != nil && d .AgentNetcheck .NetInfo != nil {
407
436
if d .AgentNetcheck .NetInfo .MappingVariesByDestIP .EqualBool (true ) {
408
- _ , _ = fmt . Fprint ( w , "❗ Agent is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers\n " )
437
+ agent = append ( agent , "❗ Agent is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers" )
409
438
}
410
439
if ! d .AgentNetcheck .NetInfo .UDP {
411
- _ , _ = fmt . Fprint ( w , "❗ Agent could not connect to STUN over UDP, which may be preventing a direct connection \n " )
440
+ agent = append ( agent , "✘ Agent could not connect to STUN over UDP" )
412
441
}
413
442
}
414
443
415
444
if d .ClientIPIsAWS {
416
- _ , _ = fmt . Fprint ( w , "❗ Client IP address is within an AWS range, which is known to cause problems with forming direct connections (AWS uses hard NAT)\n " )
445
+ client = append ( client , "❗ Client IP address is within an AWS range (AWS uses hard NAT)" )
417
446
}
418
447
419
448
if d .AgentIPIsAWS {
420
- _ , _ = fmt .Fprint (w , "❗ Agent IP address is within an AWS range, which is known to cause problems with forming direct connections (AWS uses hard NAT)\n " )
449
+ agent = append (agent , "❗ Agent IP address is within an AWS range (AWS uses hard NAT)" )
450
+ }
451
+ return general , client , agent
452
+ }
453
+
454
+ func formatHealthMessage (msg health.Message ) string {
455
+ if msg .Code != health .CodeInterfaceSmallMTU {
456
+ return msg .Message
421
457
}
458
+ r := []rune (strings .Replace (msg .Message , ", which may cause problems with direct connections" , "" , - 1 ))
459
+ out := string (append ([]rune {unicode .ToUpper (r [0 ])}, r [1 :]... ))
460
+ return fmt .Sprintf ("❗ %s, which may degrade the quality of direct connections" , out )
422
461
}
0 commit comments