( ctx context.Context, agentConn workspacesdk.AgentConn, logger slog.Logger, networkInfoDir string, networkInfoInterval time.Duration, )
| 1538 | } |
| 1539 | |
| 1540 | func setStatsCallback( |
| 1541 | ctx context.Context, |
| 1542 | agentConn workspacesdk.AgentConn, |
| 1543 | logger slog.Logger, |
| 1544 | networkInfoDir string, |
| 1545 | networkInfoInterval time.Duration, |
| 1546 | ) (<-chan error, error) { |
| 1547 | fs, ok := ctx.Value("fs").(afero.Fs) |
| 1548 | if !ok { |
| 1549 | fs = afero.NewOsFs() |
| 1550 | } |
| 1551 | if err := fs.MkdirAll(networkInfoDir, 0o700); err != nil { |
| 1552 | return nil, xerrors.Errorf("mkdir: %w", err) |
| 1553 | } |
| 1554 | |
| 1555 | // The VS Code extension obtains the PID of the SSH process to |
| 1556 | // read files to display logs and network info. |
| 1557 | // |
| 1558 | // We get the parent PID because it's assumed `ssh` is calling this |
| 1559 | // command via the ProxyCommand SSH option. |
| 1560 | pid := os.Getppid() |
| 1561 | |
| 1562 | // The VS Code extension obtains the PID of the SSH process to |
| 1563 | // read the file below which contains network information to display. |
| 1564 | // |
| 1565 | // We get the parent PID because it's assumed `ssh` is calling this |
| 1566 | // command via the ProxyCommand SSH option. |
| 1567 | networkInfoFilePath := filepath.Join(networkInfoDir, fmt.Sprintf("%d.json", pid)) |
| 1568 | |
| 1569 | var ( |
| 1570 | firstErrTime time.Time |
| 1571 | errCh = make(chan error, 1) |
| 1572 | ) |
| 1573 | cb := func(start, end time.Time, virtual, _ map[netlogtype.Connection]netlogtype.Counts) { |
| 1574 | sendErr := func(tolerate bool, err error) { |
| 1575 | logger.Error(ctx, "collect network stats", slog.Error(err)) |
| 1576 | // Tolerate up to 1 minute of errors. |
| 1577 | if tolerate { |
| 1578 | if firstErrTime.IsZero() { |
| 1579 | logger.Info(ctx, "tolerating network stats errors for up to 1 minute") |
| 1580 | firstErrTime = time.Now() |
| 1581 | } |
| 1582 | if time.Since(firstErrTime) < time.Minute { |
| 1583 | return |
| 1584 | } |
| 1585 | } |
| 1586 | |
| 1587 | select { |
| 1588 | case errCh <- err: |
| 1589 | default: |
| 1590 | } |
| 1591 | } |
| 1592 | |
| 1593 | stats, err := collectNetworkStats(ctx, agentConn, start, end, virtual) |
| 1594 | if err != nil { |
| 1595 | sendErr(true, err) |
| 1596 | return |
| 1597 | } |
no test coverage detected